From 449cc2501ec453c5d1511e7e5353d55793cad5ab Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Fri, 1 Aug 2025 21:30:34 +0900 Subject: [PATCH 01/28] Use `File` instead of `IO`, for read/write singleton methods --- tool/make-snapshot | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tool/make-snapshot b/tool/make-snapshot index 99609a8977f19c..7a9797d13d2d9f 100755 --- a/tool/make-snapshot +++ b/tool/make-snapshot @@ -334,7 +334,7 @@ def package(vcs, rev, destdir, tmp = nil) FileUtils.rm(file, verbose: $VERBOSE) end - status = IO.read(File.dirname(__FILE__) + "/prereq.status") + status = File.read(File.dirname(__FILE__) + "/prereq.status") Dir.chdir(tmp) if tmp if !File.directory?(v) @@ -346,10 +346,10 @@ def package(vcs, rev, destdir, tmp = nil) File.open("#{v}/revision.h", "wb") {|f| f.puts vcs.revision_header(revision, modified) } - version ||= (versionhdr = IO.read("#{v}/version.h"))[RUBY_VERSION_PATTERN, 1] + version ||= (versionhdr = File.read("#{v}/version.h"))[RUBY_VERSION_PATTERN, 1] version ||= begin - include_ruby_versionhdr = IO.read("#{v}/include/ruby/version.h") + include_ruby_versionhdr = File.read("#{v}/include/ruby/version.h") api_major_version = include_ruby_versionhdr[/^\#define\s+RUBY_API_VERSION_MAJOR\s+([\d.]+)/, 1] api_minor_version = include_ruby_versionhdr[/^\#define\s+RUBY_API_VERSION_MINOR\s+([\d.]+)/, 1] version_teeny = versionhdr[/^\#define\s+RUBY_VERSION_TEENY\s+(\d+)/, 1] @@ -358,14 +358,14 @@ def package(vcs, rev, destdir, tmp = nil) version or return if patchlevel unless tag.empty? - versionhdr ||= IO.read("#{v}/version.h") + versionhdr ||= File.read("#{v}/version.h") patchlevel = versionhdr[/^\#define\s+RUBY_PATCHLEVEL\s+(\d+)/, 1] tag = (patchlevel ? "p#{patchlevel}" : vcs.revision_name(revision)) end elsif prerelease - versionhdr ||= IO.read("#{v}/version.h") + versionhdr ||= File.read("#{v}/version.h") versionhdr.sub!(/^\#\s*define\s+RUBY_PATCHLEVEL_STR\s+"\K.+?(?=")/, tag) or raise "no match of RUBY_PATCHLEVEL_STR to replace" - IO.write("#{v}/version.h", versionhdr) + File.write("#{v}/version.h", versionhdr) else tag ||= vcs.revision_name(revision) end @@ -439,11 +439,11 @@ def package(vcs, rev, destdir, tmp = nil) clean.add("autom4te.cache") clean.add("enc/unicode/data") print "creating prerequisites..." - if File.file?("common.mk") && /^prereq/ =~ commonmk = IO.read("common.mk") + if File.file?("common.mk") && /^prereq/ =~ commonmk = File.read("common.mk") puts extout = clean.add('tmp') begin - status = IO.read("tool/prereq.status") + status = File.read("tool/prereq.status") rescue Errno::ENOENT # use fallback file end @@ -456,7 +456,7 @@ def package(vcs, rev, destdir, tmp = nil) File.binwrite("#{defaults}/ruby.rb", "") miniruby = ENV['MINIRUBY'] + " -I. -I#{extout} -rcross" baseruby = ENV["BASERUBY"] - mk = (IO.read("template/Makefile.in") rescue IO.read("Makefile.in")). + mk = (File.read("template/Makefile.in") rescue File.read("Makefile.in")). gsub(/^@.*\n/, '') vars = { "EXTOUT"=>extout, From ddbfe353c2100400f60d6bd012cc175ca4b518ab Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Fri, 1 Aug 2025 21:32:17 +0900 Subject: [PATCH 02/28] Use autogen.sh if exists --- tool/make-snapshot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tool/make-snapshot b/tool/make-snapshot index 7a9797d13d2d9f..7d4fce4f153172 100755 --- a/tool/make-snapshot +++ b/tool/make-snapshot @@ -430,7 +430,7 @@ def package(vcs, rev, destdir, tmp = nil) puts "cross.rb:", File.read("cross.rb").gsub(/^/, "> "), "" if $VERBOSE unless File.exist?("configure") print "creating configure..." - unless system([ENV["AUTOCONF"]]*2) + unless system(File.exist?(gen = "./autogen.sh") ? gen : [ENV["AUTOCONF"]]*2) puts $colorize.fail(" failed") return end From 3c1244ab836226c324519d3d77bf712ec9168de0 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Fri, 1 Aug 2025 22:42:23 +0900 Subject: [PATCH 03/28] Define targets for packages also in common.mk --- common.mk | 3 +++ 1 file changed, 3 insertions(+) diff --git a/common.mk b/common.mk index e2b6a2f685b979..f4ea06c2631449 100644 --- a/common.mk +++ b/common.mk @@ -1846,6 +1846,9 @@ clean-gems: CLEAN_CACHE = clean-extlibs +prepare-package: prereq after-update +clean-cache: $(CLEAN_CACHE) + info: info-program info-libruby_a info-libruby_so info-arch info-program: PHONY @echo PROGRAM=$(PROGRAM) From 75a968d88af62dda468b5fb0481279c638483eab Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Fri, 1 Aug 2025 21:42:36 +0900 Subject: [PATCH 04/28] Add the recipe to fix/update depend files --- .github/workflows/check_dependencies.yml | 6 +----- defs/gmake.mk | 3 +++ 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/check_dependencies.yml b/.github/workflows/check_dependencies.yml index 6d85cf8e9c043a..db93e90efb7c10 100644 --- a/.github/workflows/check_dependencies.yml +++ b/.github/workflows/check_dependencies.yml @@ -48,11 +48,7 @@ jobs: - name: Run configure run: ./configure -C --disable-install-doc --disable-rubygems --with-gcc 'optflags=-O0' 'debugflags=-save-temps=obj -g' - - run: make all golf - - - run: ./goruby -veh - - - run: ruby tool/update-deps --fix + - run: make fix-depends - run: git diff --no-ext-diff --ignore-submodules --exit-code diff --git a/defs/gmake.mk b/defs/gmake.mk index 6382e3d0031832..bd4b8b8e39f201 100644 --- a/defs/gmake.mk +++ b/defs/gmake.mk @@ -505,6 +505,9 @@ update-deps: $(GIT) --git-dir=$(GIT_DIR) merge --no-edit --ff-only $(update_deps) $(GIT) --git-dir=$(GIT_DIR) branch --delete $(update_deps) +fix-depends check-depends: all hello + $(BASERUBY) -C $(srcdir) tool/update-deps $(if $(filter fix-%,$@),--fix) + # order-only-prerequisites doesn't work for $(RUBYSPEC_CAPIEXT) # because the same named directory exists in the source tree. $(RUBYSPEC_CAPIEXT)/%.$(DLEXT): $(srcdir)/$(RUBYSPEC_CAPIEXT)/%.c $(RUBYSPEC_CAPIEXT_DEPS) \ From 6e10267714817424049049dadd14e931aa25bf01 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 6 Aug 2025 10:14:48 +0900 Subject: [PATCH 05/28] [rubygems/rubygems] Removed to workaround for Bundler 2.2. The current oldest support Ruby version is 3.2. And Ruby 3.2 bundled Bundler 2.5. It means RG 4.0 can drop to support Bundler 2.2. https://github.com/rubygems/rubygems/commit/592ac09b5c --- lib/rubygems/installer.rb | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/lib/rubygems/installer.rb b/lib/rubygems/installer.rb index 2b3200223a5db7..d0092899a40263 100644 --- a/lib/rubygems/installer.rb +++ b/lib/rubygems/installer.rb @@ -67,23 +67,6 @@ class Gem::Installer attr_reader :package class << self - # - # Changes in rubygems to lazily loading `rubygems/command` (in order to - # lazily load `optparse` as a side effect) affect bundler's custom installer - # which uses `Gem::Command` without requiring it (up until bundler 2.2.29). - # This hook is to compensate for that missing require. - # - # TODO: Remove when rubygems no longer supports running on bundler older - # than 2.2.29. - - def inherited(klass) - if klass.name == "Bundler::RubyGemsGemInstaller" - require "rubygems/command" - end - - super(klass) - end - ## # Overrides the executable format. # From d4bf58b56e7c31b9e838d9ff86e2b13027cb54ea Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Mon, 28 Jul 2025 11:08:21 +1200 Subject: [PATCH 06/28] [rubygems/rubygems] Don't worry about missing Makefile. https://github.com/rubygems/rubygems/commit/0e92346d88 --- lib/rubygems/ext/builder.rb | 6 +++- lib/rubygems/ext/ext_conf_builder.rb | 4 +++ .../rubygems/test_gem_ext_ext_conf_builder.rb | 33 ++++++++----------- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/lib/rubygems/ext/builder.rb b/lib/rubygems/ext/builder.rb index 05cd735bd90d4f..b47996d0920bb3 100644 --- a/lib/rubygems/ext/builder.rb +++ b/lib/rubygems/ext/builder.rb @@ -11,6 +11,9 @@ class Gem::Ext::Builder include Gem::UserInteraction + class NoMakefileError < Gem::InstallError + end + attr_accessor :build_args # :nodoc: def self.class_name @@ -21,7 +24,8 @@ def self.class_name def self.make(dest_path, results, make_dir = Dir.pwd, sitedir = nil, targets = ["clean", "", "install"], target_rbconfig: Gem.target_rbconfig) unless File.exist? File.join(make_dir, "Makefile") - raise Gem::InstallError, "Makefile not found" + # No makefile exists, nothing to do. + raise NoMakefileError, "No Makefile found in #{make_dir}" end # try to find make program from Ruby configure arguments first diff --git a/lib/rubygems/ext/ext_conf_builder.rb b/lib/rubygems/ext/ext_conf_builder.rb index e652a221f83b32..8aa15962a0f307 100644 --- a/lib/rubygems/ext/ext_conf_builder.rb +++ b/lib/rubygems/ext/ext_conf_builder.rb @@ -66,6 +66,10 @@ def self.build(extension, dest_path, results, args=[], lib_dir=nil, extension_di end results + rescue Gem::Ext::Builder::NoMakefileError => error + results << error.message + results << "Skipping make for #{extension} as no Makefile was found." + # We are good, do not re-raise the error. ensure FileUtils.rm_rf tmp_dest if tmp_dest end diff --git a/test/rubygems/test_gem_ext_ext_conf_builder.rb b/test/rubygems/test_gem_ext_ext_conf_builder.rb index 218c6f3d5e3678..bc383e5540a9e3 100644 --- a/test/rubygems/test_gem_ext_ext_conf_builder.rb +++ b/test/rubygems/test_gem_ext_ext_conf_builder.rb @@ -15,15 +15,12 @@ def setup end def test_class_build - if Gem.java_platform? - pend("failing on jruby") - end - if vc_windows? && !nmake_found? pend("test_class_build skipped - nmake not found") end File.open File.join(@ext, "extconf.rb"), "w" do |extconf| + extconf.puts "return if Gem.java_platform?" extconf.puts "require 'mkmf'\ncreate_makefile 'foo'" end @@ -35,20 +32,22 @@ def test_class_build assert_match(/^current directory:/, output[0]) assert_match(/^#{Regexp.quote(Gem.ruby)}.* extconf.rb/, output[1]) - assert_equal "creating Makefile\n", output[2] - assert_match(/^current directory:/, output[3]) - assert_contains_make_command "clean", output[4] - assert_contains_make_command "", output[7] - assert_contains_make_command "install", output[10] + + if Gem.java_platform? + assert_includes(output, "Skipping make for extconf.rb as no Makefile was found.") + else + assert_equal "creating Makefile\n", output[2] + assert_match(/^current directory:/, output[3]) + assert_contains_make_command "clean", output[4] + assert_contains_make_command "", output[7] + assert_contains_make_command "install", output[10] + end + assert_empty Dir.glob(File.join(@ext, "siteconf*.rb")) assert_empty Dir.glob(File.join(@ext, ".gem.*")) end def test_class_build_rbconfig_make_prog - if Gem.java_platform? - pend("failing on jruby") - end - configure_args do File.open File.join(@ext, "extconf.rb"), "w" do |extconf| extconf.puts "require 'mkmf'\ncreate_makefile 'foo'" @@ -72,10 +71,6 @@ def test_class_build_env_make env_large_make = ENV.delete "MAKE" ENV["MAKE"] = "anothermake" - if Gem.java_platform? - pend("failing on jruby") - end - configure_args "" do File.open File.join(@ext, "extconf.rb"), "w" do |extconf| extconf.puts "require 'mkmf'\ncreate_makefile 'foo'" @@ -206,11 +201,11 @@ def test_class_make end def test_class_make_no_Makefile - error = assert_raise Gem::InstallError do + error = assert_raise Gem::Ext::Builder::NoMakefileError do Gem::Ext::ExtConfBuilder.make @ext, ["output"], @ext end - assert_equal "Makefile not found", error.message + assert_match(/No Makefile found/, error.message) end def configure_args(args = nil) From 3c669e2d411d06e0458804f1e1d8bd5e9352172c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 8 Aug 2025 10:56:59 +0200 Subject: [PATCH 07/28] [rubygems/rubygems] Remove unnecessary rubygems filters Since the lowest supported version is now 3.4.1. https://github.com/rubygems/rubygems/commit/d00e03c52e --- spec/bundler/install/gemfile/specific_platform_spec.rb | 4 ++-- spec/bundler/resolver/platform_spec.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/bundler/install/gemfile/specific_platform_spec.rb b/spec/bundler/install/gemfile/specific_platform_spec.rb index 71065c36f33507..62540f0488de62 100644 --- a/spec/bundler/install/gemfile/specific_platform_spec.rb +++ b/spec/bundler/install/gemfile/specific_platform_spec.rb @@ -1432,7 +1432,7 @@ end end - it "does not fail when a platform variant is incompatible with the current ruby and another equivalent platform specific variant is part of the resolution", rubygems: ">= 3.3.21" do + it "does not fail when a platform variant is incompatible with the current ruby and another equivalent platform specific variant is part of the resolution" do build_repo4 do build_gem "nokogiri", "1.15.5" @@ -1578,7 +1578,7 @@ end end - it "adds current musl platform, when there are also gnu variants", rubygems: ">= 3.3.21" do + it "adds current musl platform, when there are also gnu variants" do build_repo4 do build_gem "rcee_precompiled", "0.5.0" do |s| s.platform = "x86_64-linux-gnu" diff --git a/spec/bundler/resolver/platform_spec.rb b/spec/bundler/resolver/platform_spec.rb index 13f3e152828e16..a1d095d024de10 100644 --- a/spec/bundler/resolver/platform_spec.rb +++ b/spec/bundler/resolver/platform_spec.rb @@ -387,7 +387,7 @@ should_resolve_as %w[thin-1.2.7-x64-mingw-ucrt] end - it "finds universal-mingw gems on x64-mingw-ucrt", rubygems: ">= 3.3.18" do + it "finds universal-mingw gems on x64-mingw-ucrt" do platform "x64-mingw-ucrt" dep "win32-api" should_resolve_as %w[win32-api-1.5.1-universal-mingw32] From a6aa8e67f16cafb74cd86d0ba2467755e56bab20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 8 Aug 2025 10:58:13 +0200 Subject: [PATCH 08/28] [rubygems/rubygems] Fix spec no longer run since rubygems timeout was renamed https://github.com/rubygems/rubygems/commit/4d0c058e6a --- spec/bundler/runtime/inline_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/bundler/runtime/inline_spec.rb b/spec/bundler/runtime/inline_spec.rb index 0467d8b14abdcb..0d4c4df08cb237 100644 --- a/spec/bundler/runtime/inline_spec.rb +++ b/spec/bundler/runtime/inline_spec.rb @@ -595,7 +595,7 @@ def confirm(msg, newline = nil) skip "timeout isn't a default gem" if default_timeout_version.empty? # This only works on RubyGems 3.5.0 or higher - ruby "require 'rubygems/timeout'", raise_on_error: false + ruby "require 'rubygems/vendored_timeout'", raise_on_error: false skip "rubygems under test does not yet vendor timeout" unless last_command.success? build_repo4 do From 2e983280e27c6e076546c0444a9489c832e9b32b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 8 Aug 2025 11:00:54 +0200 Subject: [PATCH 09/28] [rubygems/rubygems] Use a rubygems filter for the timeout spec For consistency. https://github.com/rubygems/rubygems/commit/3e3364e19f --- spec/bundler/runtime/inline_spec.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/spec/bundler/runtime/inline_spec.rb b/spec/bundler/runtime/inline_spec.rb index 0d4c4df08cb237..cffaab35799aca 100644 --- a/spec/bundler/runtime/inline_spec.rb +++ b/spec/bundler/runtime/inline_spec.rb @@ -590,14 +590,10 @@ def confirm(msg, newline = nil) expect(err).to be_empty end - it "does not load default timeout" do + it "does not load default timeout", rubygems: ">= 3.5.0" do default_timeout_version = ruby "gem 'timeout', '< 999999'; require 'timeout'; puts Timeout::VERSION", raise_on_error: false skip "timeout isn't a default gem" if default_timeout_version.empty? - # This only works on RubyGems 3.5.0 or higher - ruby "require 'rubygems/vendored_timeout'", raise_on_error: false - skip "rubygems under test does not yet vendor timeout" unless last_command.success? - build_repo4 do build_gem "timeout", "999" end From f074f8260aae2cb541d13f87a990404038c1b6e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 8 Aug 2025 11:07:04 +0200 Subject: [PATCH 10/28] [rubygems/rubygems] Fix `bundle cache --no-all` not printing a deprecation warning Like others, it's a remembered option which we are deprecating in favor of configuration. https://github.com/rubygems/rubygems/commit/9ea55e0df2 --- lib/bundler/cli.rb | 1 + spec/bundler/other/major_deprecation_spec.rb | 22 ++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb index ea85f9af22ab24..23c20fc7b3c307 100644 --- a/lib/bundler/cli.rb +++ b/lib/bundler/cli.rb @@ -412,6 +412,7 @@ def fund D def cache print_remembered_flag_deprecation("--all", "cache_all", "true") if ARGV.include?("--all") + print_remembered_flag_deprecation("--no-all", "cache_all", "false") if ARGV.include?("--no-all") if flag_passed?("--path") message = diff --git a/spec/bundler/other/major_deprecation_spec.rb b/spec/bundler/other/major_deprecation_spec.rb index 51d490ea7247ac..55a30ad157c1e7 100644 --- a/spec/bundler/other/major_deprecation_spec.rb +++ b/spec/bundler/other/major_deprecation_spec.rb @@ -199,6 +199,28 @@ pending "fails with a helpful error", bundler: "4" end + context "bundle cache --no-all" do + before do + install_gemfile <<-G + source "https://gem.repo1" + gem "myrack" + G + + bundle "cache --no-all", raise_on_error: false + end + + it "should print a deprecation warning" do + expect(deprecations).to include( + "The `--no-all` flag is deprecated because it relies on being " \ + "remembered across bundler invocations, which bundler will no " \ + "longer do in future versions. Instead please use `bundle config set " \ + "cache_all false`, and stop using this flag" + ) + end + + pending "fails with a helpful error", bundler: "4" + end + context "bundle cache --path" do before do install_gemfile <<-G From 8d5f00c5371ff71f33ef57b1419fd8d4b1aa9074 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 8 Aug 2025 12:42:16 +0200 Subject: [PATCH 11/28] [rubygems/rubygems] Fix Bundler printing more flags than actually passed in verbose mode This reverts commit https://github.com/rubygems/rubygems/commit/bea87eab0b17 and adds a regression spec for it. https://github.com/rubygems/rubygems/commit/ac98107864 --- lib/bundler/cli.rb | 7 ++++++- spec/bundler/commands/list_spec.rb | 12 ++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb index 23c20fc7b3c307..8c4e3c36a7e059 100644 --- a/lib/bundler/cli.rb +++ b/lib/bundler/cli.rb @@ -714,7 +714,12 @@ def print_command command_name = cmd.name return if PARSEABLE_COMMANDS.include?(command_name) command = ["bundle", command_name] + args - command << Thor::Options.to_switches(options.sort_by(&:first)).strip + options_to_print = options.dup + options_to_print.delete_if do |k, v| + next unless o = cmd.options[k] + o.default == v + end + command << Thor::Options.to_switches(options_to_print.sort_by(&:first)).strip command.reject!(&:empty?) Bundler.ui.info "Running `#{command * " "}` with bundler #{Bundler.verbose_version}" end diff --git a/spec/bundler/commands/list_spec.rb b/spec/bundler/commands/list_spec.rb index cc0db9169d64ad..e8ed863310aa73 100644 --- a/spec/bundler/commands/list_spec.rb +++ b/spec/bundler/commands/list_spec.rb @@ -1,6 +1,18 @@ # frozen_string_literal: true RSpec.describe "bundle list" do + context "in verbose mode" do + it "logs the actual flags passed to the command" do + install_gemfile <<-G + source "https://gem.repo1" + G + + bundle "list --verbose" + + expect(out).to include("Running `bundle list --verbose`") + end + end + context "with name-only and paths option" do it "raises an error" do bundle "list --name-only --paths", raise_on_error: false From 813603994a388ad8f22ab831d2b554671dfd23b6 Mon Sep 17 00:00:00 2001 From: Schneems Date: Thu, 29 May 2025 11:11:48 -0500 Subject: [PATCH 12/28] [rubygems/rubygems] Introduce `bundle list --format=json` The `bundle list` command is a convenient way for human to know what gems and versions are available. By introducing a `--format=json` option, we can provide the same information to machines in a stable format that is robust to UI additions or modifications. It indirectly supports `Gemfile.lock` modifications by discouraging external tools from attempting to parse that format. This addition allows for the scripting of installation tools, such as buildpacks, that wish to branch logic based on gem versions. For example: ```ruby require "json" command = "bundle list --format=json" output = `#{command}` raise "Command `#{command}` errored: #{output}" unless $?.success? railties = JSON.parse(output).find {|gem| gem["name"] == railties } if railties && Gem::Version.new(railties["version"]) >= Gem::Version.new("7") puts "Using Rails greater than 7!" end ``` The top level is an object with a single key, "gems", this structure allows us to add other information in the future (should we desire) without having to change the json schema. https://github.com/rubygems/rubygems/commit/9e081b0689 --- lib/bundler/cli.rb | 1 + lib/bundler/cli/list.rb | 35 +++++++++- lib/bundler/man/bundle-list.1 | 5 ++ lib/bundler/man/bundle-list.1.ronn | 5 ++ spec/bundler/commands/list_spec.rb | 108 +++++++++++++++++++++++++++++ 5 files changed, 152 insertions(+), 2 deletions(-) diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb index 8c4e3c36a7e059..65bf8eee836f67 100644 --- a/lib/bundler/cli.rb +++ b/lib/bundler/cli.rb @@ -299,6 +299,7 @@ def show(gem_name = nil) method_option "name-only", type: :boolean, banner: "print only the gem names" method_option "only-group", type: :array, default: [], banner: "print gems from a given set of groups" method_option "without-group", type: :array, default: [], banner: "print all gems except from a given set of groups" + method_option "format", type: :string, banner: "format output ('json' is the only supported format)" method_option "paths", type: :boolean, banner: "print the path to each gem in the bundle" def list require_relative "cli/list" diff --git a/lib/bundler/cli/list.rb b/lib/bundler/cli/list.rb index f56bf5b86a426a..6a467f45a94ea2 100644 --- a/lib/bundler/cli/list.rb +++ b/lib/bundler/cli/list.rb @@ -1,11 +1,14 @@ # frozen_string_literal: true +require "json" + module Bundler class CLI::List def initialize(options) @options = options @without_group = options["without-group"].map(&:to_sym) @only_group = options["only-group"].map(&:to_sym) + @format = options["format"] end def run @@ -25,6 +28,36 @@ def run end end.reject {|s| s.name == "bundler" }.sort_by(&:name) + case @format + when "json" + print_json(specs: specs) + when nil + print_human(specs: specs) + else + raise InvalidOption, "Unknown option`--format=#{@format}`. Supported formats: `json`" + end + end + + private + + def print_json(specs:) + gems = if @options["name-only"] + specs.map {|s| { name: s.name } } + else + specs.map do |s| + { + name: s.name, + version: s.version.to_s, + git_version: s.git_version&.strip, + }.tap do |h| + h[:path] = s.full_gem_path if @options["paths"] + end + end + end + Bundler.ui.info({ gems: gems }.to_json) + end + + def print_human(specs:) return Bundler.ui.info "No gems in the Gemfile" if specs.empty? return specs.each {|s| Bundler.ui.info s.name } if @options["name-only"] @@ -37,8 +70,6 @@ def run Bundler.ui.info "Use `bundle info` to print more detailed information about a gem" end - private - def verify_group_exists(groups) (@without_group + @only_group).each do |group| raise InvalidOption, "`#{group}` group could not be found." unless groups.include?(group) diff --git a/lib/bundler/man/bundle-list.1 b/lib/bundler/man/bundle-list.1 index 26c2833218093a..7698fe16cc0ea1 100644 --- a/lib/bundler/man/bundle-list.1 +++ b/lib/bundler/man/bundle-list.1 @@ -19,6 +19,8 @@ bundle list \-\-without\-group test bundle list \-\-only\-group dev .P bundle list \-\-only\-group dev test \-\-paths +.P +bundle list \-\-format json .SH "OPTIONS" .TP \fB\-\-name\-only\fR @@ -32,4 +34,7 @@ A space\-separated list of groups of gems to skip during printing\. .TP \fB\-\-only\-group=\fR A space\-separated list of groups of gems to print\. +.TP +\fB\-\-format=FORMAT\fR +Format output ('json' is the only supported format) diff --git a/lib/bundler/man/bundle-list.1.ronn b/lib/bundler/man/bundle-list.1.ronn index 81bee0ac332047..9ec2b132828958 100644 --- a/lib/bundler/man/bundle-list.1.ronn +++ b/lib/bundler/man/bundle-list.1.ronn @@ -21,6 +21,8 @@ bundle list --only-group dev bundle list --only-group dev test --paths +bundle list --format json + ## OPTIONS * `--name-only`: @@ -34,3 +36,6 @@ bundle list --only-group dev test --paths * `--only-group=`: A space-separated list of groups of gems to print. + +* `--format=FORMAT`: + Format output ('json' is the only supported format) diff --git a/spec/bundler/commands/list_spec.rb b/spec/bundler/commands/list_spec.rb index e8ed863310aa73..c890646a816cc4 100644 --- a/spec/bundler/commands/list_spec.rb +++ b/spec/bundler/commands/list_spec.rb @@ -1,6 +1,16 @@ # frozen_string_literal: true +require "json" + RSpec.describe "bundle list" do + def find_gem_name(json:, name:) + parse_json(json)["gems"].detect {|h| h["name"] == name } + end + + def parse_json(json) + JSON.parse(json) + end + context "in verbose mode" do it "logs the actual flags passed to the command" do install_gemfile <<-G @@ -29,6 +39,20 @@ end end + context "with invalid format option" do + before do + install_gemfile <<-G + source "https://gem.repo1" + G + end + + it "raises an error" do + bundle "list --format=nope", raise_on_error: false + + expect(err).to eq "Unknown option`--format=nope`. Supported formats: `json`" + end + end + describe "with without-group option" do before do install_gemfile <<-G @@ -48,6 +72,17 @@ expect(out).to include(" * rails (2.3.2)") expect(out).not_to include(" * rspec (1.2.7)") end + + it "prints the gems not in the specified group with json" do + bundle "list --without-group test --format=json" + + gem = find_gem_name(json: out, name: "myrack") + expect(gem["version"]).to eq("1.0.0") + gem = find_gem_name(json: out, name: "rails") + expect(gem["version"]).to eq("2.3.2") + gem = find_gem_name(json: out, name: "rspec") + expect(gem).to be_nil + end end context "when group is not found" do @@ -66,6 +101,17 @@ expect(out).not_to include(" * rails (2.3.2)") expect(out).not_to include(" * rspec (1.2.7)") end + + it "prints the gems not in the specified groups with json" do + bundle "list --without-group test production --format=json" + + gem = find_gem_name(json: out, name: "myrack") + expect(gem["version"]).to eq("1.0.0") + gem = find_gem_name(json: out, name: "rails") + expect(gem).to be_nil + gem = find_gem_name(json: out, name: "rspec") + expect(gem).to be_nil + end end end @@ -87,6 +133,15 @@ expect(out).to include(" * myrack (1.0.0)") expect(out).not_to include(" * rspec (1.2.7)") end + + it "prints the gems in the specified group with json" do + bundle "list --only-group default --format=json" + + gem = find_gem_name(json: out, name: "myrack") + expect(gem["version"]).to eq("1.0.0") + gem = find_gem_name(json: out, name: "rspec") + expect(gem).to be_nil + end end context "when group is not found" do @@ -105,6 +160,17 @@ expect(out).to include(" * rails (2.3.2)") expect(out).not_to include(" * rspec (1.2.7)") end + + it "prints the gems in the specified groups with json" do + bundle "list --only-group default production --format=json" + + gem = find_gem_name(json: out, name: "myrack") + expect(gem["version"]).to eq("1.0.0") + gem = find_gem_name(json: out, name: "rails") + expect(gem["version"]).to eq("2.3.2") + gem = find_gem_name(json: out, name: "rspec") + expect(gem).to be_nil + end end end @@ -124,6 +190,15 @@ expect(out).to include("myrack") expect(out).to include("rspec") end + + it "prints only the name of the gems in the bundle with json" do + bundle "list --name-only --format=json" + + gem = find_gem_name(json: out, name: "myrack") + expect(gem.keys).to eq(["name"]) + gem = find_gem_name(json: out, name: "rspec") + expect(gem.keys).to eq(["name"]) + end end context "with paths option" do @@ -158,6 +233,27 @@ expect(out).to match(%r{.*\/git_test\-\w}) expect(out).to match(%r{.*\/gemspec_test}) end + + it "prints the path of each gem in the bundle with json" do + bundle "list --paths --format=json" + + gem = find_gem_name(json: out, name: "rails") + expect(gem["path"]).to match(%r{.*\/rails\-2\.3\.2}) + expect(gem["git_version"]).to be_nil + + gem = find_gem_name(json: out, name: "myrack") + expect(gem["path"]).to match(%r{.*\/myrack\-1\.2}) + expect(gem["git_version"]).to be_nil + + gem = find_gem_name(json: out, name: "git_test") + expect(gem["path"]).to match(%r{.*\/git_test\-\w}) + expect(gem["git_version"]).to be_truthy + expect(gem["git_version"].strip).to eq(gem["git_version"]) + + gem = find_gem_name(json: out, name: "gemspec_test") + expect(gem["path"]).to match(%r{.*\/gemspec_test}) + expect(gem["git_version"]).to be_nil + end end context "when no gems are in the gemfile" do @@ -171,6 +267,11 @@ bundle "list" expect(out).to include("No gems in the Gemfile") end + + it "prints empty json" do + bundle "list --format=json" + expect(parse_json(out)["gems"]).to eq([]) + end end context "without options" do @@ -187,6 +288,13 @@ bundle "list" expect(out).to include(" * myrack (1.0.0)") end + + it "lists gems installed in the bundle with json" do + bundle "list --format=json" + + gem = find_gem_name(json: out, name: "myrack") + expect(gem["version"]).to eq("1.0.0") + end end context "when using the ls alias" do From bcc287fc6f33e5680ece7dd737e46fd7894d6ed7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 1 Aug 2025 15:19:39 +0200 Subject: [PATCH 13/28] [rubygems/rubygems] Fix `bundle update foo` not upgrading foo to latest in a specific case If upgrading `foo` needs an indirect dependency to be downgraded, Bundler would not be able to upgrade foo. This is because when calculating the latest resolvable version of foo, Bundler was still adding lower bound requirements on the locked versions of all dependencies to avoid downgrades, effectively pinning foo to a version older than the latest. To fix this, instead of creating a second "unlocked" definition to figure out the latest resolvable version, create a second unlocked resolver, and DO NOT add lower bound requirements to it. https://github.com/rubygems/rubygems/commit/00cc0ecc69 --- lib/bundler/definition.rb | 37 +++++++++++++----------- spec/bundler/commands/update_spec.rb | 43 ++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 17 deletions(-) diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index 6c7a3e9c38a613..7d00c234d671d3 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -492,8 +492,6 @@ def unlocking? @unlocking end - attr_writer :source_requirements - def add_checksums @locked_checksums = true @@ -614,7 +612,7 @@ def write_lock(file, preserve_unknown_sections) end def resolver - @resolver ||= Resolver.new(resolution_base, gem_version_promoter, @most_specific_locked_platform) + @resolver ||= new_resolver(resolution_base) end def expanded_dependencies @@ -632,8 +630,7 @@ def resolution_base @resolution_base ||= begin last_resolve = converge_locked_specs remove_invalid_platforms! - new_resolution_platforms = @current_platform_missing ? @new_platforms + [Bundler.local_platform] : @new_platforms - base = Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, locked_specs: @originally_locked_specs, unlock: @unlocking_all || @gems_to_unlock, prerelease: gem_version_promoter.pre?, prefer_local: @prefer_local, new_platforms: new_resolution_platforms) + base = new_resolution_base(last_resolve: last_resolve, unlock: @unlocking_all || @gems_to_unlock) base = additional_base_requirements_to_prevent_downgrades(base) base = additional_base_requirements_to_force_updates(base) base @@ -1136,7 +1133,7 @@ def additional_base_requirements_to_prevent_downgrades(resolution_base) def additional_base_requirements_to_force_updates(resolution_base) return resolution_base if @explicit_unlocks.empty? - full_update = dup_for_full_unlock.resolve + full_update = SpecSet.new(new_resolver_for_full_update.start) @explicit_unlocks.each do |name| version = full_update.version_for(name) resolution_base.base_requirements[name] = Gem::Requirement.new("= #{version}") if version @@ -1144,17 +1141,6 @@ def additional_base_requirements_to_force_updates(resolution_base) resolution_base end - def dup_for_full_unlock - unlocked_definition = self.class.new(@lockfile, @dependencies, @sources, true, @ruby_version, @optional_groups, @gemfiles) - unlocked_definition.source_requirements = source_requirements - unlocked_definition.gem_version_promoter.tap do |gvp| - gvp.level = gem_version_promoter.level - gvp.strict = gem_version_promoter.strict - gvp.pre = gem_version_promoter.pre - end - unlocked_definition - end - def remove_invalid_platforms! return if Bundler.frozen_bundle? @@ -1173,5 +1159,22 @@ def remove_invalid_platforms! def source_map @source_map ||= SourceMap.new(sources, dependencies, @locked_specs) end + + def new_resolver_for_full_update + new_resolver(unlocked_resolution_base) + end + + def unlocked_resolution_base + new_resolution_base(last_resolve: SpecSet.new([]), unlock: true) + end + + def new_resolution_base(last_resolve:, unlock:) + new_resolution_platforms = @current_platform_missing ? @new_platforms + [Bundler.local_platform] : @new_platforms + Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, locked_specs: @originally_locked_specs, unlock: unlock, prerelease: gem_version_promoter.pre?, prefer_local: @prefer_local, new_platforms: new_resolution_platforms) + end + + def new_resolver(base) + Resolver.new(base, gem_version_promoter, @most_specific_locked_platform) + end end end diff --git a/spec/bundler/commands/update_spec.rb b/spec/bundler/commands/update_spec.rb index 22bb1662e6571c..8b0f28ae6e366e 100644 --- a/spec/bundler/commands/update_spec.rb +++ b/spec/bundler/commands/update_spec.rb @@ -445,6 +445,49 @@ expect(out).to include("Installing sneakers 2.11.0").and include("Installing rake 13.0.6") end + it "downgrades indirect dependencies if required to fulfill an explicit upgrade request" do + build_repo4 do + build_gem "rbs", "3.6.1" + build_gem "rbs", "3.9.4" + + build_gem "solargraph", "0.56.0" do |s| + s.add_dependency "rbs", "~> 3.3" + end + + build_gem "solargraph", "0.56.2" do |s| + s.add_dependency "rbs", "~> 3.6.1" + end + end + + gemfile <<~G + source "https://gem.repo4" + + gem 'solargraph', '~> 0.56.0' + G + + lockfile <<~L + GEM + remote: https://gem.repo4/ + specs: + rbs (3.9.4) + solargraph (0.56.0) + rbs (~> 3.3) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + solargraph (~> 0.56.0) + + BUNDLED WITH + #{Bundler::VERSION} + L + + bundle "lock --update solargraph" + + expect(lockfile).to include("solargraph (0.56.2)") + end + it "does not downgrade direct dependencies unnecessarily" do build_repo4 do build_gem "redis", "4.8.1" From 679e8b1be42b8af2b675815d956eb86479cd1d55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 8 Aug 2025 14:00:22 +0200 Subject: [PATCH 14/28] [rubygems/rubygems] Fix `bundle show --verbose` and recommend it as an alternative to `bundle show --outdated` https://github.com/rubygems/rubygems/commit/7cad1e4947 --- lib/bundler/cli.rb | 4 ++-- lib/bundler/cli/show.rb | 8 ++----- spec/bundler/commands/show_spec.rb | 22 +++++++++++++++++++- spec/bundler/other/major_deprecation_spec.rb | 2 +- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb index 65bf8eee836f67..84e8ca1c535b12 100644 --- a/lib/bundler/cli.rb +++ b/lib/bundler/cli.rb @@ -287,8 +287,8 @@ def update(*gems) method_option "outdated", type: :boolean, banner: "Show verbose output including whether gems are outdated." def show(gem_name = nil) if ARGV.include?("--outdated") - message = "the `--outdated` flag to `bundle show` was undocumented and will be removed without replacement" - removed_message = "the `--outdated` flag to `bundle show` was undocumented and has been removed without replacement" + message = "the `--outdated` flag to `bundle show` will be removed in favor of `bundle show --verbose`" + removed_message = "the `--outdated` flag to `bundle show` has been removed in favor of `bundle show --verbose`" SharedHelpers.major_deprecation(2, message, removed_message: removed_message) end require_relative "cli/show" diff --git a/lib/bundler/cli/show.rb b/lib/bundler/cli/show.rb index 13bb8b774b670d..b55eb7bad5aecc 100644 --- a/lib/bundler/cli/show.rb +++ b/lib/bundler/cli/show.rb @@ -57,12 +57,8 @@ def run def fetch_latest_specs definition = Bundler.definition(true) - if options[:outdated] - Bundler.ui.info "Fetching remote specs for outdated check...\n\n" - Bundler.ui.silence { definition.remotely! } - else - definition.with_cache! - end + Bundler.ui.info "Fetching remote specs for outdated check...\n\n" + Bundler.ui.silence { definition.remotely! } Bundler.reset! definition.specs end diff --git a/spec/bundler/commands/show_spec.rb b/spec/bundler/commands/show_spec.rb index 82ec6e51f2e74e..e5440cdf7fa7c5 100644 --- a/spec/bundler/commands/show_spec.rb +++ b/spec/bundler/commands/show_spec.rb @@ -3,8 +3,10 @@ RSpec.describe "bundle show" do context "with a standard Gemfile" do before :each do + build_repo2 + install_gemfile <<-G - source "https://gem.repo1" + source "https://gem.repo2" gem "rails" G end @@ -86,6 +88,24 @@ \tStatus: Up to date MSG end + + it "includes up to date status in summary of gems" do + update_repo2 do + build_gem "rails", "3.0.0" + end + + bundle "show --verbose" + + expect(out).to include <<~MSG + * rails (2.3.2) + \tSummary: This is just a fake gem for testing + \tHomepage: http://example.com + \tStatus: Outdated - 2.3.2 < 3.0.0 + MSG + + # check lockfile is not accidentally updated + expect(lockfile).to include("actionmailer (2.3.2)") + end end context "with a git repo in the Gemfile" do diff --git a/spec/bundler/other/major_deprecation_spec.rb b/spec/bundler/other/major_deprecation_spec.rb index 55a30ad157c1e7..d57abe45f35259 100644 --- a/spec/bundler/other/major_deprecation_spec.rb +++ b/spec/bundler/other/major_deprecation_spec.rb @@ -614,7 +614,7 @@ end it "prints a deprecation warning informing about its removal" do - expect(deprecations).to include("the `--outdated` flag to `bundle show` was undocumented and will be removed without replacement") + expect(deprecations).to include("the `--outdated` flag to `bundle show` will be removed in favor of `bundle show --verbose`") end pending "fails with a helpful message", bundler: "4" From 9983d2bceed3d50196bc755733c15561821b1409 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 8 Aug 2025 14:00:51 +0200 Subject: [PATCH 15/28] [rubygems/rubygems] Delay pending spec We had actually cancelled this change. After a second look though, it does seem like a reasonable plan since `bundle list` makes more sense for listing gems, and `bundle info` makes more sense for showing info about a particular gem. `bundle show` is a strange mix of both. Let's schedule this for Bundler 5. https://github.com/rubygems/rubygems/commit/7071a1e82e --- spec/bundler/commands/show_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/bundler/commands/show_spec.rb b/spec/bundler/commands/show_spec.rb index e5440cdf7fa7c5..ba903ac4957a5a 100644 --- a/spec/bundler/commands/show_spec.rb +++ b/spec/bundler/commands/show_spec.rb @@ -239,6 +239,6 @@ end end -RSpec.describe "bundle show", bundler: "4" do +RSpec.describe "bundle show", bundler: "5" do pending "shows a friendly error about the command removal" end From 302c5ae28f5627f856a99c2fef9b0bb8f695bbef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 11 Aug 2025 19:40:07 +0200 Subject: [PATCH 16/28] [rubygems/rubygems] Consistently use banner of desc when defining CLI flags https://github.com/rubygems/rubygems/commit/2cbe7ea0a5 --- lib/bundler/cli.rb | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb index 84e8ca1c535b12..47a39069cc1b56 100644 --- a/lib/bundler/cli.rb +++ b/lib/bundler/cli.rb @@ -520,11 +520,11 @@ def licenses Viz requires the ruby-graphviz gem (and its dependencies). The associated gems must also be installed via 'bundle install'. D - method_option :file, type: :string, default: "gem_graph", aliases: "-f", desc: "The name to use for the generated file. see format option" - method_option :format, type: :string, default: "png", aliases: "-F", desc: "This is output format option. Supported format is png, jpg, svg, dot ..." - method_option :requirements, type: :boolean, default: false, aliases: "-R", desc: "Set to show the version of each required dependency." - method_option :version, type: :boolean, default: false, aliases: "-v", desc: "Set to show each gem version." - method_option :without, type: :array, default: [], aliases: "-W", banner: "GROUP[ GROUP...]", desc: "Exclude gems that are part of the specified named group." + method_option :file, type: :string, default: "gem_graph", aliases: "-f", banner: "The name to use for the generated file. see format option" + method_option :format, type: :string, default: "png", aliases: "-F", banner: "This is output format option. Supported format is png, jpg, svg, dot ..." + method_option :requirements, type: :boolean, default: false, aliases: "-R", banner: "Set to show the version of each required dependency." + method_option :version, type: :boolean, default: false, aliases: "-v", banner: "Set to show each gem version." + method_option :without, type: :array, default: [], aliases: "-W", banner: "Exclude gems that are part of the specified named group." def viz SharedHelpers.major_deprecation 2, "The `viz` command has been renamed to `graph` and moved to a plugin. See https://github.com/rubygems/bundler-graph" require_relative "cli/viz" @@ -533,19 +533,19 @@ def viz end desc "gem NAME [OPTIONS]", "Creates a skeleton for creating a rubygem" - method_option :exe, type: :boolean, default: false, aliases: ["--bin", "-b"], desc: "Generate a binary executable for your library." - method_option :coc, type: :boolean, desc: "Generate a code of conduct file. Set a default with `bundle config set --global gem.coc true`." - method_option :edit, type: :string, aliases: "-e", required: false, banner: "EDITOR", lazy_default: [ENV["BUNDLER_EDITOR"], ENV["VISUAL"], ENV["EDITOR"]].find {|e| !e.nil? && !e.empty? }, desc: "Open generated gemspec in the specified editor (defaults to $EDITOR or $BUNDLER_EDITOR)" - method_option :ext, type: :string, desc: "Generate the boilerplate for C extension code.", enum: EXTENSIONS - method_option :git, type: :boolean, default: true, desc: "Initialize a git repo inside your library." - method_option :mit, type: :boolean, desc: "Generate an MIT license file. Set a default with `bundle config set --global gem.mit true`." - method_option :rubocop, type: :boolean, desc: "Add rubocop to the generated Rakefile and gemspec. Set a default with `bundle config set --global gem.rubocop true`." - method_option :changelog, type: :boolean, desc: "Generate changelog file. Set a default with `bundle config set --global gem.changelog true`." + method_option :exe, type: :boolean, default: false, aliases: ["--bin", "-b"], banner: "Generate a binary executable for your library." + method_option :coc, type: :boolean, banner: "Generate a code of conduct file. Set a default with `bundle config set --global gem.coc true`." + method_option :edit, type: :string, aliases: "-e", required: false, lazy_default: [ENV["BUNDLER_EDITOR"], ENV["VISUAL"], ENV["EDITOR"]].find {|e| !e.nil? && !e.empty? }, banner: "Open generated gemspec in the specified editor (defaults to $EDITOR or $BUNDLER_EDITOR)" + method_option :ext, type: :string, banner: "Generate the boilerplate for C extension code.", enum: EXTENSIONS + method_option :git, type: :boolean, default: true, banner: "Initialize a git repo inside your library." + method_option :mit, type: :boolean, banner: "Generate an MIT license file. Set a default with `bundle config set --global gem.mit true`." + method_option :rubocop, type: :boolean, banner: "Add rubocop to the generated Rakefile and gemspec. Set a default with `bundle config set --global gem.rubocop true`." + method_option :changelog, type: :boolean, banner: "Generate changelog file. Set a default with `bundle config set --global gem.changelog true`." method_option :test, type: :string, lazy_default: Bundler.settings["gem.test"] || "", aliases: "-t", banner: "Use the specified test framework for your library", enum: %w[rspec minitest test-unit], desc: "Generate a test directory for your library, either rspec, minitest or test-unit. Set a default with `bundle config set --global gem.test (rspec|minitest|test-unit)`." - method_option :ci, type: :string, lazy_default: Bundler.settings["gem.ci"] || "", enum: %w[github gitlab circle], desc: "Generate CI configuration, either GitHub Actions, GitLab CI or CircleCI. Set a default with `bundle config set --global gem.ci (github|gitlab|circle)`" - method_option :linter, type: :string, lazy_default: Bundler.settings["gem.linter"] || "", enum: %w[rubocop standard], desc: "Add a linter and code formatter, either RuboCop or Standard. Set a default with `bundle config set --global gem.linter (rubocop|standard)`" + method_option :ci, type: :string, lazy_default: Bundler.settings["gem.ci"] || "", enum: %w[github gitlab circle], banner: "Generate CI configuration, either GitHub Actions, GitLab CI or CircleCI. Set a default with `bundle config set --global gem.ci (github|gitlab|circle)`" + method_option :linter, type: :string, lazy_default: Bundler.settings["gem.linter"] || "", enum: %w[rubocop standard], banner: "Add a linter and code formatter, either RuboCop or Standard. Set a default with `bundle config set --global gem.linter (rubocop|standard)`" method_option :github_username, type: :string, default: Bundler.settings["gem.github_username"], banner: "Set your username on GitHub", desc: "Fill in GitHub username on README so that you don't have to do it manually. Set a default with `bundle config set --global gem.github_username `." - method_option :bundle, type: :boolean, default: Bundler.settings["gem.bundle"], desc: "Automatically run `bundle install` after creation. Set a default with `bundle config set --global gem.bundle true`" + method_option :bundle, type: :boolean, default: Bundler.settings["gem.bundle"], banner: "Automatically run `bundle install` after creation. Set a default with `bundle config set --global gem.bundle true`" def gem(name) require_relative "cli/gem" From 12c200a78fa525375b3695c7cad97e3013a7de66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 11 Aug 2025 19:56:37 +0200 Subject: [PATCH 17/28] [rubygems/rubygems] Improve `bundle config` documentation For synopsis, subcommand and flag documentation like other commands do. https://github.com/rubygems/rubygems/commit/f528029756 --- lib/bundler/man/bundle-add.1 | 2 +- lib/bundler/man/bundle-binstubs.1 | 2 +- lib/bundler/man/bundle-cache.1 | 2 +- lib/bundler/man/bundle-check.1 | 2 +- lib/bundler/man/bundle-clean.1 | 2 +- lib/bundler/man/bundle-config.1 | 45 ++++++++++++------ lib/bundler/man/bundle-config.1.ronn | 69 ++++++++++++++++++++-------- lib/bundler/man/bundle-console.1 | 2 +- lib/bundler/man/bundle-doctor.1 | 2 +- lib/bundler/man/bundle-env.1 | 2 +- lib/bundler/man/bundle-exec.1 | 2 +- lib/bundler/man/bundle-fund.1 | 2 +- lib/bundler/man/bundle-gem.1 | 2 +- lib/bundler/man/bundle-help.1 | 2 +- lib/bundler/man/bundle-info.1 | 2 +- lib/bundler/man/bundle-init.1 | 2 +- lib/bundler/man/bundle-inject.1 | 2 +- lib/bundler/man/bundle-install.1 | 2 +- lib/bundler/man/bundle-issue.1 | 2 +- lib/bundler/man/bundle-licenses.1 | 2 +- lib/bundler/man/bundle-list.1 | 2 +- lib/bundler/man/bundle-lock.1 | 2 +- lib/bundler/man/bundle-open.1 | 2 +- lib/bundler/man/bundle-outdated.1 | 2 +- lib/bundler/man/bundle-platform.1 | 2 +- lib/bundler/man/bundle-plugin.1 | 2 +- lib/bundler/man/bundle-pristine.1 | 2 +- lib/bundler/man/bundle-remove.1 | 2 +- lib/bundler/man/bundle-show.1 | 2 +- lib/bundler/man/bundle-update.1 | 2 +- lib/bundler/man/bundle-version.1 | 2 +- lib/bundler/man/bundle-viz.1 | 2 +- lib/bundler/man/bundle.1 | 2 +- lib/bundler/man/gemfile.5 | 2 +- 34 files changed, 112 insertions(+), 66 deletions(-) diff --git a/lib/bundler/man/bundle-add.1 b/lib/bundler/man/bundle-add.1 index baa4a376c83b4c..74422cbd313ddf 100644 --- a/lib/bundler/man/bundle-add.1 +++ b/lib/bundler/man/bundle-add.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-ADD" "1" "July 2025" "" +.TH "BUNDLE\-ADD" "1" "August 2025" "" .SH "NAME" \fBbundle\-add\fR \- Add gem to the Gemfile and run bundle install .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-binstubs.1 b/lib/bundler/man/bundle-binstubs.1 index 0131dd663ea38e..be9c6d0d097390 100644 --- a/lib/bundler/man/bundle-binstubs.1 +++ b/lib/bundler/man/bundle-binstubs.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-BINSTUBS" "1" "July 2025" "" +.TH "BUNDLE\-BINSTUBS" "1" "August 2025" "" .SH "NAME" \fBbundle\-binstubs\fR \- Install the binstubs of the listed gems .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-cache.1 b/lib/bundler/man/bundle-cache.1 index 4c5dcff052bc42..1d16b164fa2806 100644 --- a/lib/bundler/man/bundle-cache.1 +++ b/lib/bundler/man/bundle-cache.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-CACHE" "1" "July 2025" "" +.TH "BUNDLE\-CACHE" "1" "August 2025" "" .SH "NAME" \fBbundle\-cache\fR \- Package your needed \fB\.gem\fR files into your application .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-check.1 b/lib/bundler/man/bundle-check.1 index 376becdbe47d5b..4f0d51bb71472e 100644 --- a/lib/bundler/man/bundle-check.1 +++ b/lib/bundler/man/bundle-check.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-CHECK" "1" "July 2025" "" +.TH "BUNDLE\-CHECK" "1" "August 2025" "" .SH "NAME" \fBbundle\-check\fR \- Verifies if dependencies are satisfied by installed gems .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-clean.1 b/lib/bundler/man/bundle-clean.1 index 85e6186f49cf2e..df66523829d35e 100644 --- a/lib/bundler/man/bundle-clean.1 +++ b/lib/bundler/man/bundle-clean.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-CLEAN" "1" "July 2025" "" +.TH "BUNDLE\-CLEAN" "1" "August 2025" "" .SH "NAME" \fBbundle\-clean\fR \- Cleans up unused gems in your bundler directory .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-config.1 b/lib/bundler/man/bundle-config.1 index 6f12696ab6961f..5157e514531238 100644 --- a/lib/bundler/man/bundle-config.1 +++ b/lib/bundler/man/bundle-config.1 @@ -1,16 +1,16 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-CONFIG" "1" "July 2025" "" +.TH "BUNDLE\-CONFIG" "1" "August 2025" "" .SH "NAME" \fBbundle\-config\fR \- Set bundler configuration options .SH "SYNOPSIS" -\fBbundle config\fR list +\fBbundle config\fR [list] .br -\fBbundle config\fR [get] NAME +\fBbundle config\fR [get [\-\-local|\-\-global]] NAME .br -\fBbundle config\fR [set] NAME VALUE +\fBbundle config\fR [set [\-\-local|\-\-global]] NAME VALUE .br -\fBbundle config\fR unset NAME +\fBbundle config\fR unset [\-\-local|\-\-global] NAME .SH "DESCRIPTION" This command allows you to interact with Bundler's configuration system\. .P @@ -25,23 +25,40 @@ Global config (\fB~/\.bundle/config\fR) Bundler default config .IP "" 0 .P +Executing \fBbundle\fR with the \fBBUNDLE_IGNORE_CONFIG\fR environment variable set will cause it to ignore all configuration\. +.SH "SUB\-COMMANDS" +.SS "list (default command)" Executing \fBbundle config list\fR will print a list of all bundler configuration for the current bundle, and where that configuration was set\. +.SS "get" +Executing \fBbundle config get \fR will print the value of that configuration setting, and all locations where it was set\. .P -Executing \fBbundle config get \fR will print the value of that configuration setting, and where it was set\. -.P -Executing \fBbundle config set \fR defaults to setting \fBlocal\fR configuration if executing from within a local application, otherwise it will set \fBglobal\fR configuration\. See \fB\-\-local\fR and \fB\-\-global\fR options below\. +\fBOPTIONS\fR +.TP +\fB\-\-local\fR +Get configuration from configuration file for the local application, namely, \fB/\.bundle/config\fR, or \fB$BUNDLE_APP_CONFIG/config\fR if \fBBUNDLE_APP_CONFIG\fR is set\. +.TP +\fB\-\-global\fR +Get configuration from configuration file global to all bundles executed as the current user, namely, from \fB~/\.bundle/config\fR\. +.SS "set" +Executing \fBbundle config set \fR defaults to setting \fBlocal\fR configuration if executing from within a local application, otherwise it will set \fBglobal\fR configuration\. .P +\fBOPTIONS\fR +.TP +\fB\-\-local\fR Executing \fBbundle config set \-\-local \fR will set that configuration in the directory for the local application\. The configuration will be stored in \fB/\.bundle/config\fR\. If \fBBUNDLE_APP_CONFIG\fR is set, the configuration will be stored in \fB$BUNDLE_APP_CONFIG/config\fR\. -.P +.TP +\fB\-\-global\fR Executing \fBbundle config set \-\-global \fR will set that configuration to the value specified for all bundles executed as the current user\. The configuration will be stored in \fB~/\.bundle/config\fR\. If \fIname\fR already is set, \fIname\fR will be overridden and user will be warned\. -.P +.SS "unset" Executing \fBbundle config unset \fR will delete the configuration in both local and global sources\. .P -Executing \fBbundle config unset \-\-global \fR will delete the configuration only from the user configuration\. -.P +\fBOPTIONS\fR +.TP +\fB\-\-local\fR Executing \fBbundle config unset \-\-local \fR will delete the configuration only from the local application\. -.P -Executing bundle with the \fBBUNDLE_IGNORE_CONFIG\fR environment variable set will cause it to ignore all configuration\. +.TP +\fB\-\-global\fR +Executing \fBbundle config unset \-\-global \fR will delete the configuration only from the user configuration\. .SH "CONFIGURATION KEYS" Configuration keys in bundler have two forms: the canonical form and the environment variable form\. .P diff --git a/lib/bundler/man/bundle-config.1.ronn b/lib/bundler/man/bundle-config.1.ronn index 7f31eb4c39a0ad..2b2e39f03eb7f0 100644 --- a/lib/bundler/man/bundle-config.1.ronn +++ b/lib/bundler/man/bundle-config.1.ronn @@ -3,10 +3,10 @@ bundle-config(1) -- Set bundler configuration options ## SYNOPSIS -`bundle config` list
-`bundle config` [get] NAME
-`bundle config` [set] NAME VALUE
-`bundle config` unset NAME +`bundle config` [list]
+`bundle config` [get [--local|--global]] NAME
+`bundle config` [set [--local|--global]] NAME VALUE
+`bundle config` unset [--local|--global] NAME ## DESCRIPTION @@ -19,38 +19,67 @@ Bundler loads configuration settings in this order: 3. Global config (`~/.bundle/config`) 4. Bundler default config +Executing `bundle` with the `BUNDLE_IGNORE_CONFIG` environment variable set will +cause it to ignore all configuration. + +## SUB-COMMANDS + +### list (default command) + Executing `bundle config list` will print a list of all bundler configuration for the current bundle, and where that configuration was set. +### get + Executing `bundle config get ` will print the value of that configuration -setting, and where it was set. +setting, and all locations where it was set. + +**OPTIONS** + +* `--local`: + Get configuration from configuration file for the local application, namely, + `/.bundle/config`, or `$BUNDLE_APP_CONFIG/config` if + `BUNDLE_APP_CONFIG` is set. + +* `--global`: + Get configuration from configuration file global to all bundles executed as + the current user, namely, from `~/.bundle/config`. + +### set Executing `bundle config set ` defaults to setting `local` configuration if executing from within a local application, otherwise it will -set `global` configuration. See `--local` and `--global` options below. +set `global` configuration. -Executing `bundle config set --local ` will set that configuration -in the directory for the local application. The configuration will be stored in -`/.bundle/config`. If `BUNDLE_APP_CONFIG` is set, the configuration -will be stored in `$BUNDLE_APP_CONFIG/config`. +**OPTIONS** -Executing `bundle config set --global ` will set that -configuration to the value specified for all bundles executed as the current -user. The configuration will be stored in `~/.bundle/config`. If already -is set, will be overridden and user will be warned. +* `--local`: + Executing `bundle config set --local ` will set that configuration + in the directory for the local application. The configuration will be stored in + `/.bundle/config`. If `BUNDLE_APP_CONFIG` is set, the configuration + will be stored in `$BUNDLE_APP_CONFIG/config`. + +* `--global`: + Executing `bundle config set --global ` will set that + configuration to the value specified for all bundles executed as the current + user. The configuration will be stored in `~/.bundle/config`. If already + is set, will be overridden and user will be warned. + +### unset Executing `bundle config unset ` will delete the configuration in both local and global sources. -Executing `bundle config unset --global ` will delete the configuration -only from the user configuration. +**OPTIONS** -Executing `bundle config unset --local ` will delete the configuration -only from the local application. +* `--local`: + Executing `bundle config unset --local ` will delete the configuration + only from the local application. -Executing bundle with the `BUNDLE_IGNORE_CONFIG` environment variable set will -cause it to ignore all configuration. +* `--global`: + Executing `bundle config unset --global ` will delete the configuration + only from the user configuration. ## CONFIGURATION KEYS diff --git a/lib/bundler/man/bundle-console.1 b/lib/bundler/man/bundle-console.1 index a263fef37640ae..18c765372b4230 100644 --- a/lib/bundler/man/bundle-console.1 +++ b/lib/bundler/man/bundle-console.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-CONSOLE" "1" "July 2025" "" +.TH "BUNDLE\-CONSOLE" "1" "August 2025" "" .SH "NAME" \fBbundle\-console\fR \- Open an IRB session with the bundle pre\-loaded .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-doctor.1 b/lib/bundler/man/bundle-doctor.1 index 2b695dc2eef2ec..aa5e8ea2e336bf 100644 --- a/lib/bundler/man/bundle-doctor.1 +++ b/lib/bundler/man/bundle-doctor.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-DOCTOR" "1" "July 2025" "" +.TH "BUNDLE\-DOCTOR" "1" "August 2025" "" .SH "NAME" \fBbundle\-doctor\fR \- Checks the bundle for common problems .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-env.1 b/lib/bundler/man/bundle-env.1 index 3e6c9f6e171de8..28ccc17f03aa9f 100644 --- a/lib/bundler/man/bundle-env.1 +++ b/lib/bundler/man/bundle-env.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-ENV" "1" "July 2025" "" +.TH "BUNDLE\-ENV" "1" "August 2025" "" .SH "NAME" \fBbundle\-env\fR \- Print information about the environment Bundler is running under .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-exec.1 b/lib/bundler/man/bundle-exec.1 index 79cdad0288f498..cd53916cffcc34 100644 --- a/lib/bundler/man/bundle-exec.1 +++ b/lib/bundler/man/bundle-exec.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-EXEC" "1" "July 2025" "" +.TH "BUNDLE\-EXEC" "1" "August 2025" "" .SH "NAME" \fBbundle\-exec\fR \- Execute a command in the context of the bundle .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-fund.1 b/lib/bundler/man/bundle-fund.1 index 3f6e3a46dfec80..a91c1809514aee 100644 --- a/lib/bundler/man/bundle-fund.1 +++ b/lib/bundler/man/bundle-fund.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-FUND" "1" "July 2025" "" +.TH "BUNDLE\-FUND" "1" "August 2025" "" .SH "NAME" \fBbundle\-fund\fR \- Lists information about gems seeking funding assistance .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-gem.1 b/lib/bundler/man/bundle-gem.1 index 44a02c033c70af..5fe27772306930 100644 --- a/lib/bundler/man/bundle-gem.1 +++ b/lib/bundler/man/bundle-gem.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-GEM" "1" "July 2025" "" +.TH "BUNDLE\-GEM" "1" "August 2025" "" .SH "NAME" \fBbundle\-gem\fR \- Generate a project skeleton for creating a rubygem .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-help.1 b/lib/bundler/man/bundle-help.1 index e6bbea6dadbf39..9ea28bef14d082 100644 --- a/lib/bundler/man/bundle-help.1 +++ b/lib/bundler/man/bundle-help.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-HELP" "1" "July 2025" "" +.TH "BUNDLE\-HELP" "1" "August 2025" "" .SH "NAME" \fBbundle\-help\fR \- Displays detailed help for each subcommand .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-info.1 b/lib/bundler/man/bundle-info.1 index 435518e120fe73..29d649d342cc42 100644 --- a/lib/bundler/man/bundle-info.1 +++ b/lib/bundler/man/bundle-info.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-INFO" "1" "July 2025" "" +.TH "BUNDLE\-INFO" "1" "August 2025" "" .SH "NAME" \fBbundle\-info\fR \- Show information for the given gem in your bundle .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-init.1 b/lib/bundler/man/bundle-init.1 index 48b3232b8cba2a..be9399c20f2367 100644 --- a/lib/bundler/man/bundle-init.1 +++ b/lib/bundler/man/bundle-init.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-INIT" "1" "July 2025" "" +.TH "BUNDLE\-INIT" "1" "August 2025" "" .SH "NAME" \fBbundle\-init\fR \- Generates a Gemfile into the current working directory .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-inject.1 b/lib/bundler/man/bundle-inject.1 index abc63c392e525c..7e30e26a4e4637 100644 --- a/lib/bundler/man/bundle-inject.1 +++ b/lib/bundler/man/bundle-inject.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-INJECT" "1" "July 2025" "" +.TH "BUNDLE\-INJECT" "1" "August 2025" "" .SH "NAME" \fBbundle\-inject\fR \- Add named gem(s) with version requirements to Gemfile .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-install.1 b/lib/bundler/man/bundle-install.1 index bf067475584a03..f9bbade2fd59fb 100644 --- a/lib/bundler/man/bundle-install.1 +++ b/lib/bundler/man/bundle-install.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-INSTALL" "1" "July 2025" "" +.TH "BUNDLE\-INSTALL" "1" "August 2025" "" .SH "NAME" \fBbundle\-install\fR \- Install the dependencies specified in your Gemfile .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-issue.1 b/lib/bundler/man/bundle-issue.1 index 668da5712f7cd9..3c7e5305f3721a 100644 --- a/lib/bundler/man/bundle-issue.1 +++ b/lib/bundler/man/bundle-issue.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-ISSUE" "1" "July 2025" "" +.TH "BUNDLE\-ISSUE" "1" "August 2025" "" .SH "NAME" \fBbundle\-issue\fR \- Get help reporting Bundler issues .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-licenses.1 b/lib/bundler/man/bundle-licenses.1 index cccb860854819b..eb0ad5ae405cd3 100644 --- a/lib/bundler/man/bundle-licenses.1 +++ b/lib/bundler/man/bundle-licenses.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-LICENSES" "1" "July 2025" "" +.TH "BUNDLE\-LICENSES" "1" "August 2025" "" .SH "NAME" \fBbundle\-licenses\fR \- Print the license of all gems in the bundle .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-list.1 b/lib/bundler/man/bundle-list.1 index 7698fe16cc0ea1..a345787a5e9ee0 100644 --- a/lib/bundler/man/bundle-list.1 +++ b/lib/bundler/man/bundle-list.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-LIST" "1" "July 2025" "" +.TH "BUNDLE\-LIST" "1" "August 2025" "" .SH "NAME" \fBbundle\-list\fR \- List all the gems in the bundle .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-lock.1 b/lib/bundler/man/bundle-lock.1 index 5faa46da180afb..79aa1e2452f6d3 100644 --- a/lib/bundler/man/bundle-lock.1 +++ b/lib/bundler/man/bundle-lock.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-LOCK" "1" "July 2025" "" +.TH "BUNDLE\-LOCK" "1" "August 2025" "" .SH "NAME" \fBbundle\-lock\fR \- Creates / Updates a lockfile without installing .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-open.1 b/lib/bundler/man/bundle-open.1 index e8a24f35414207..b1c2022f40195b 100644 --- a/lib/bundler/man/bundle-open.1 +++ b/lib/bundler/man/bundle-open.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-OPEN" "1" "July 2025" "" +.TH "BUNDLE\-OPEN" "1" "August 2025" "" .SH "NAME" \fBbundle\-open\fR \- Opens the source directory for a gem in your bundle .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-outdated.1 b/lib/bundler/man/bundle-outdated.1 index 3259b0f0233fa3..d4790f8876a54d 100644 --- a/lib/bundler/man/bundle-outdated.1 +++ b/lib/bundler/man/bundle-outdated.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-OUTDATED" "1" "July 2025" "" +.TH "BUNDLE\-OUTDATED" "1" "August 2025" "" .SH "NAME" \fBbundle\-outdated\fR \- List installed gems with newer versions available .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-platform.1 b/lib/bundler/man/bundle-platform.1 index 1032acc4e6405c..78de506b57b838 100644 --- a/lib/bundler/man/bundle-platform.1 +++ b/lib/bundler/man/bundle-platform.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-PLATFORM" "1" "July 2025" "" +.TH "BUNDLE\-PLATFORM" "1" "August 2025" "" .SH "NAME" \fBbundle\-platform\fR \- Displays platform compatibility information .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-plugin.1 b/lib/bundler/man/bundle-plugin.1 index 5803b7a5549917..9285f128c1b10b 100644 --- a/lib/bundler/man/bundle-plugin.1 +++ b/lib/bundler/man/bundle-plugin.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-PLUGIN" "1" "July 2025" "" +.TH "BUNDLE\-PLUGIN" "1" "August 2025" "" .SH "NAME" \fBbundle\-plugin\fR \- Manage Bundler plugins .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-pristine.1 b/lib/bundler/man/bundle-pristine.1 index 5c7871069c0940..e39f264ceff298 100644 --- a/lib/bundler/man/bundle-pristine.1 +++ b/lib/bundler/man/bundle-pristine.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-PRISTINE" "1" "July 2025" "" +.TH "BUNDLE\-PRISTINE" "1" "August 2025" "" .SH "NAME" \fBbundle\-pristine\fR \- Restores installed gems to their pristine condition .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-remove.1 b/lib/bundler/man/bundle-remove.1 index df8ce3232ab8dc..67508176802bf4 100644 --- a/lib/bundler/man/bundle-remove.1 +++ b/lib/bundler/man/bundle-remove.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-REMOVE" "1" "July 2025" "" +.TH "BUNDLE\-REMOVE" "1" "August 2025" "" .SH "NAME" \fBbundle\-remove\fR \- Removes gems from the Gemfile .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-show.1 b/lib/bundler/man/bundle-show.1 index ca10c00701e85d..67b387559d7ca5 100644 --- a/lib/bundler/man/bundle-show.1 +++ b/lib/bundler/man/bundle-show.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-SHOW" "1" "July 2025" "" +.TH "BUNDLE\-SHOW" "1" "August 2025" "" .SH "NAME" \fBbundle\-show\fR \- Shows all the gems in your bundle, or the path to a gem .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-update.1 b/lib/bundler/man/bundle-update.1 index 8655aa5cd3545e..fbcabb69a8d61f 100644 --- a/lib/bundler/man/bundle-update.1 +++ b/lib/bundler/man/bundle-update.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-UPDATE" "1" "July 2025" "" +.TH "BUNDLE\-UPDATE" "1" "August 2025" "" .SH "NAME" \fBbundle\-update\fR \- Update your gems to the latest available versions .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-version.1 b/lib/bundler/man/bundle-version.1 index e591f597664636..261140ff3816f5 100644 --- a/lib/bundler/man/bundle-version.1 +++ b/lib/bundler/man/bundle-version.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-VERSION" "1" "July 2025" "" +.TH "BUNDLE\-VERSION" "1" "August 2025" "" .SH "NAME" \fBbundle\-version\fR \- Prints Bundler version information .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-viz.1 b/lib/bundler/man/bundle-viz.1 index b5dd1db7b7f05a..f2570103dcc546 100644 --- a/lib/bundler/man/bundle-viz.1 +++ b/lib/bundler/man/bundle-viz.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-VIZ" "1" "July 2025" "" +.TH "BUNDLE\-VIZ" "1" "August 2025" "" .SH "NAME" \fBbundle\-viz\fR \- Generates a visual dependency graph for your Gemfile .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle.1 b/lib/bundler/man/bundle.1 index 269e28141d3101..f87a98150da609 100644 --- a/lib/bundler/man/bundle.1 +++ b/lib/bundler/man/bundle.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE" "1" "July 2025" "" +.TH "BUNDLE" "1" "August 2025" "" .SH "NAME" \fBbundle\fR \- Ruby Dependency Management .SH "SYNOPSIS" diff --git a/lib/bundler/man/gemfile.5 b/lib/bundler/man/gemfile.5 index c926e1ff2d30da..cd04d3d1983d37 100644 --- a/lib/bundler/man/gemfile.5 +++ b/lib/bundler/man/gemfile.5 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "GEMFILE" "5" "July 2025" "" +.TH "GEMFILE" "5" "August 2025" "" .SH "NAME" \fBGemfile\fR \- A format for describing gem dependencies for Ruby programs .SH "SYNOPSIS" From f3d62db05a36e4182a6ac9a0d6b1a88477275d08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 11 Aug 2025 19:57:44 +0200 Subject: [PATCH 18/28] [rubygems/rubygems] Improve `doctor` CLI flag documentation Name default value placeholders in a more standard way. That's what our specs check, but they don't yet work for subcommand flags. https://github.com/rubygems/rubygems/commit/c589899cb8 --- lib/bundler/man/bundle-doctor.1 | 6 +++--- lib/bundler/man/bundle-doctor.1.ronn | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/bundler/man/bundle-doctor.1 b/lib/bundler/man/bundle-doctor.1 index aa5e8ea2e336bf..6d4b0376a68ad8 100644 --- a/lib/bundler/man/bundle-doctor.1 +++ b/lib/bundler/man/bundle-doctor.1 @@ -6,7 +6,7 @@ .SH "SYNOPSIS" \fBbundle doctor [diagnose]\fR [\-\-quiet] [\-\-gemfile=GEMFILE] [\-\-ssl] .br -\fBbundle doctor ssl\fR [\-\-host=HOST] [\-\-tls\-version=VERSION] [\-\-verify\-mode=MODE] +\fBbundle doctor ssl\fR [\-\-host=HOST] [\-\-tls\-version=TLS\-VERSION] [\-\-verify\-mode=VERIFY\-MODE] .br \fBbundle doctor\fR help [COMMAND] .SH "DESCRIPTION" @@ -57,12 +57,12 @@ Open a TLS connection and verify the outcome\. \fB\-\-host=HOST\fR Perform the diagnostic on HOST\. Defaults to \fBrubygems\.org\fR\. .TP -\fB\-\-tls\-version=VERSION\fR +\fB\-\-tls\-version=TLS\-VERSION\fR Specify the TLS version when opening the connection to HOST\. .IP Accepted values are: \fB1\.1\fR or \fB1\.2\fR\. .TP -\fB\-\-verify\-mode=MODE\fR +\fB\-\-verify\-mode=VERIFY\-MODE\fR Specify the TLS verify mode when opening the connection to HOST\. Defaults to \fBSSL_VERIFY_PEER\fR\. .IP Accepted values are: \fBCLIENT_ONCE\fR, \fBFAIL_IF_NO_PEER_CERT\fR, \fBNONE\fR, \fBPEER\fR\. diff --git a/lib/bundler/man/bundle-doctor.1.ronn b/lib/bundler/man/bundle-doctor.1.ronn index 7e8a21b1c58968..7495099ff546bc 100644 --- a/lib/bundler/man/bundle-doctor.1.ronn +++ b/lib/bundler/man/bundle-doctor.1.ronn @@ -7,8 +7,8 @@ bundle-doctor(1) -- Checks the bundle for common problems [--gemfile=GEMFILE] [--ssl]
`bundle doctor ssl` [--host=HOST] - [--tls-version=VERSION] - [--verify-mode=MODE]
+ [--tls-version=TLS-VERSION] + [--verify-mode=VERIFY-MODE]
`bundle doctor` help [COMMAND] ## DESCRIPTION @@ -65,12 +65,12 @@ The diagnostic will perform a few checks such as: * `--host=HOST`: Perform the diagnostic on HOST. Defaults to `rubygems.org`. -* `--tls-version=VERSION`: +* `--tls-version=TLS-VERSION`: Specify the TLS version when opening the connection to HOST. Accepted values are: `1.1` or `1.2`. -* `--verify-mode=MODE`: +* `--verify-mode=VERIFY-MODE`: Specify the TLS verify mode when opening the connection to HOST. Defaults to `SSL_VERIFY_PEER`. From 4a3a544d53a4058339787b7e11138d29d3c900a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 11 Aug 2025 20:00:49 +0200 Subject: [PATCH 19/28] [rubygems/rubygems] Improve `bundle plugin` documentation Make synopsis, subcommands, and CLI flags use a format consistent with the other docs, and also reword some sentences for clarify. https://github.com/rubygems/rubygems/commit/9272169ad0 --- lib/bundler/man/bundle-plugin.1 | 45 ++++++++++++++++-------- lib/bundler/man/bundle-plugin.1.ronn | 51 ++++++++++++++++++++-------- 2 files changed, 67 insertions(+), 29 deletions(-) diff --git a/lib/bundler/man/bundle-plugin.1 b/lib/bundler/man/bundle-plugin.1 index 9285f128c1b10b..5fcc88b50df308 100644 --- a/lib/bundler/man/bundle-plugin.1 +++ b/lib/bundler/man/bundle-plugin.1 @@ -4,7 +4,7 @@ .SH "NAME" \fBbundle\-plugin\fR \- Manage Bundler plugins .SH "SYNOPSIS" -\fBbundle plugin\fR install PLUGINS [\-\-source=\fISOURCE\fR] [\-\-version=\fIversion\fR] [\-\-git=\fIgit\-url\fR] [\-\-branch=\fIbranch\fR|\-\-ref=\fIrev\fR] [\-\-path=\fIpath\fR] +\fBbundle plugin\fR install PLUGINS [\-\-source=SOURCE] [\-\-version=VERSION] [\-\-git=GIT] [\-\-branch=BRANCH|\-\-ref=REF] [\-\-local\-git=LOCAL_GIT] [\-\-path=PATH] .br \fBbundle plugin\fR uninstall PLUGINS [\-\-all] .br @@ -16,18 +16,23 @@ You can install, uninstall, and list plugin(s) with this command to extend funct .SH "SUB\-COMMANDS" .SS "install" Install the given plugin(s)\. +.P +For example, \fBbundle plugin install bundler\-graph\fR will install bundler\-graph gem from globally configured sources (defaults to RubyGems\.org)\. Note that the global source specified in Gemfile is ignored\. +.P +\fBOPTIONS\fR .TP -\fBbundle plugin install bundler\-graph\fR -Install bundler\-graph gem from globally configured sources (defaults to RubyGems\.org)\. The global source, specified in source in Gemfile is ignored\. -.TP -\fBbundle plugin install bundler\-graph \-\-source https://example\.com\fR -Install bundler\-graph gem from example\.com\. The global source, specified in source in Gemfile is not considered\. +\fB\-\-source=SOURCE\fR +Install the plugin gem from a specific source, rather than from globally configured sources\. +.IP +Example: \fBbundle plugin install bundler\-graph \-\-source https://example\.com\fR .TP -\fBbundle plugin install bundler\-graph \-\-version 0\.2\.1\fR -You can specify the version of the gem via \fB\-\-version\fR\. +\fB\-\-version=VERSION\fR +Specify a version of the plugin gem to install via \fB\-\-version\fR\. +.IP +Example: \fBbundle plugin install bundler\-graph \-\-version 0\.2\.1\fR .TP -\fBbundle plugin install bundler\-graph \-\-git https://github\.com/rubygems/bundler\-graph\fR -Install bundler\-graph gem from Git repository\. You can use standard Git URLs like: +\fB\-\-git=GIT\fR +Install the plugin gem from a Git repository\. You can use standard Git URLs like: .IP \fBssh://[user@]host\.xz[:port]/path/to/repo\.git\fR .br @@ -37,12 +42,24 @@ Install bundler\-graph gem from Git repository\. You can use standard Git URLs l .br \fBfile:///path/to/repo\fR .IP -When you specify \fB\-\-git\fR, you can use \fB\-\-branch\fR or \fB\-\-ref\fR to specify any branch, tag, or commit hash (revision) to use\. +Example: \fBbundle plugin install bundler\-graph \-\-git https://github\.com/rubygems/bundler\-graph\fR .TP -\fBbundle plugin install bundler\-graph \-\-path \.\./bundler\-graph\fR -Install bundler\-graph gem from a local path\. +\fB\-\-branch=BRANCH\fR +When you specify \fB\-\-git\fR, you can use \fB\-\-branch\fR to use\. .TP -\fBbundle plugin install bundler\-graph \-\-local\-git \.\./bundler\-graph\fR +\fB\-\-ref=REF\fR +When you specify \fB\-\-git\fR, you can use \fB\-\-ref\fR to specify any tag, or commit hash (revision) to use\. +.TP +\fB\-\-path=PATH\fR +Install the plugin gem from a local path\. +.IP +Example: \fBbundle plugin install bundler\-graph \-\-path \.\./bundler\-graph\fR +.TP +\fB\-\-local\-git=LOCAL_GIT\fR +Install the plugin gem from a local Git repository\. +.IP +Example: \fBbundle plugin install bundler\-graph \-\-local\-git \.\./bundler\-graph\fR\. +.IP This option is deprecated in favor of \fB\-\-git\fR\. .SS "uninstall" Uninstall the plugin(s) specified in PLUGINS\. diff --git a/lib/bundler/man/bundle-plugin.1.ronn b/lib/bundler/man/bundle-plugin.1.ronn index 74879aa6812d63..efb42407611836 100644 --- a/lib/bundler/man/bundle-plugin.1.ronn +++ b/lib/bundler/man/bundle-plugin.1.ronn @@ -3,9 +3,10 @@ bundle-plugin(1) -- Manage Bundler plugins ## SYNOPSIS -`bundle plugin` install PLUGINS [--source=] [--version=] - [--git=] [--branch=|--ref=] - [--path=]
+`bundle plugin` install PLUGINS [--source=SOURCE] [--version=VERSION] + [--git=GIT] [--branch=BRANCH|--ref=REF] + [--local-git=LOCAL_GIT] + [--path=PATH]
`bundle plugin` uninstall PLUGINS [--all]
`bundle plugin` list
`bundle plugin` help [COMMAND] @@ -20,29 +21,49 @@ You can install, uninstall, and list plugin(s) with this command to extend funct Install the given plugin(s). -* `bundle plugin install bundler-graph`: - Install bundler-graph gem from globally configured sources (defaults to RubyGems.org). The global source, specified in source in Gemfile is ignored. +For example, `bundle plugin install bundler-graph` will install bundler-graph +gem from globally configured sources (defaults to RubyGems.org). Note that the +global source specified in Gemfile is ignored. -* `bundle plugin install bundler-graph --source https://example.com`: - Install bundler-graph gem from example.com. The global source, specified in source in Gemfile is not considered. +**OPTIONS** + +* `--source=SOURCE`: + Install the plugin gem from a specific source, rather than from globally configured sources. + + Example: `bundle plugin install bundler-graph --source https://example.com` -* `bundle plugin install bundler-graph --version 0.2.1`: - You can specify the version of the gem via `--version`. +* `--version=VERSION`: + Specify a version of the plugin gem to install via `--version`. -* `bundle plugin install bundler-graph --git https://github.com/rubygems/bundler-graph`: - Install bundler-graph gem from Git repository. You can use standard Git URLs like: + Example: `bundle plugin install bundler-graph --version 0.2.1` + +* `--git=GIT`: + Install the plugin gem from a Git repository. You can use standard Git URLs like: `ssh://[user@]host.xz[:port]/path/to/repo.git`
`http[s]://host.xz[:port]/path/to/repo.git`
`/path/to/repo`
`file:///path/to/repo` - When you specify `--git`, you can use `--branch` or `--ref` to specify any branch, tag, or commit hash (revision) to use. + Example: `bundle plugin install bundler-graph --git https://github.com/rubygems/bundler-graph` + +* `--branch=BRANCH`: + When you specify `--git`, you can use `--branch` to use. + +* `--ref=REF`: + When you specify `--git`, you can use `--ref` to specify any tag, or commit + hash (revision) to use. + +* `--path=PATH`: + Install the plugin gem from a local path. + + Example: `bundle plugin install bundler-graph --path ../bundler-graph` + +* `--local-git=LOCAL_GIT`: + Install the plugin gem from a local Git repository. -* `bundle plugin install bundler-graph --path ../bundler-graph`: - Install bundler-graph gem from a local path. + Example: `bundle plugin install bundler-graph --local-git ../bundler-graph`. -* `bundle plugin install bundler-graph --local-git ../bundler-graph`: This option is deprecated in favor of `--git`. ### uninstall From d04f1874692b7d731533a9f65d037b2880c30f5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 30 Jul 2025 11:25:26 +0200 Subject: [PATCH 20/28] [rubygems/rubygems] Refactor git specs To save some unnecessary `bundle install` commands. https://github.com/rubygems/rubygems/commit/61e7d9d09a --- spec/bundler/install/gemfile/git_spec.rb | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/spec/bundler/install/gemfile/git_spec.rb b/spec/bundler/install/gemfile/git_spec.rb index cd83ad71c07e63..4658dce9c001ed 100644 --- a/spec/bundler/install/gemfile/git_spec.rb +++ b/spec/bundler/install/gemfile/git_spec.rb @@ -2,7 +2,7 @@ RSpec.describe "bundle install with git sources" do describe "when floating on main" do - before :each do + let(:install_base_gemfile) do build_git "foo" do |s| s.executables = "foobar" end @@ -16,6 +16,7 @@ end it "fetches gems" do + install_base_gemfile expect(the_bundle).to include_gems("foo 1.0") run <<-RUBY @@ -27,16 +28,19 @@ end it "caches the git repo" do + install_base_gemfile expect(Dir["#{default_bundle_path}/cache/bundler/git/foo-1.0-*"]).to have_attributes size: 1 end it "does not write to cache on bundler/setup" do + install_base_gemfile FileUtils.rm_r(default_cache_path) ruby "require 'bundler/setup'" expect(default_cache_path).not_to exist end it "caches the git repo globally and properly uses the cached repo on the next invocation" do + install_base_gemfile pristine_system_gems bundle "config set global_gem_cache true" bundle :install @@ -48,6 +52,7 @@ end it "caches the evaluated gemspec" do + install_base_gemfile git = update_git "foo" do |s| s.executables = ["foobar"] # we added this the first time, so keep it now s.files = ["bin/foobar"] # updating git nukes the files list @@ -66,6 +71,7 @@ end it "does not update the git source implicitly" do + install_base_gemfile update_git "foo" install_gemfile bundled_app2("Gemfile"), <<-G, dir: bundled_app2 @@ -84,6 +90,7 @@ end it "sets up git gem executables on the path" do + install_base_gemfile bundle "exec foobar" expect(out).to eq("1.0") end @@ -136,7 +143,7 @@ it "still works after moving the application directory" do bundle "config set --local path vendor/bundle" - bundle "install" + install_base_gemfile FileUtils.mv bundled_app, tmp("bundled_app.bck") @@ -145,7 +152,7 @@ it "can still install after moving the application directory" do bundle "config set --local path vendor/bundle" - bundle "install" + install_base_gemfile FileUtils.mv bundled_app, tmp("bundled_app.bck") From 50c1faedebf6b8d779e05811398f25bbdf769f0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 30 Jul 2025 11:26:01 +0200 Subject: [PATCH 21/28] [rubygems/rubygems] Fix incorrect error message capitalization https://github.com/rubygems/rubygems/commit/d41b8d303c --- lib/bundler/definition.rb | 2 +- spec/bundler/commands/update_spec.rb | 2 +- spec/bundler/lock/lockfile_spec.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index 7d00c234d671d3..2313e467bc00b2 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -531,7 +531,7 @@ def lockfile_changes_summary(update_refused_reason) return unless added.any? || deleted.any? || changed.any? || resolve_needed? - msg = String.new("#{change_reason.capitalize.strip}, but ") + msg = String.new("#{change_reason[0].upcase}#{change_reason[1..-1].strip}, but ") msg << "the lockfile " unless msg.start_with?("Your lockfile") msg << "can't be updated because #{update_refused_reason}" msg << "\n\nYou have added to the Gemfile:\n" << added.join("\n") if added.any? diff --git a/spec/bundler/commands/update_spec.rb b/spec/bundler/commands/update_spec.rb index 8b0f28ae6e366e..7702c723977559 100644 --- a/spec/bundler/commands/update_spec.rb +++ b/spec/bundler/commands/update_spec.rb @@ -1852,7 +1852,7 @@ system_gems "bundler-9.9.9", path: local_gem_path bundle "update --bundler=9.9.9", env: { "BUNDLE_FROZEN" => "true" }, raise_on_error: false - expect(err).to include("An update to the version of bundler itself was requested, but the lockfile can't be updated because frozen mode is set") + expect(err).to include("An update to the version of Bundler itself was requested, but the lockfile can't be updated because frozen mode is set") end end diff --git a/spec/bundler/lock/lockfile_spec.rb b/spec/bundler/lock/lockfile_spec.rb index e1fbe6934a1b6e..d0bee11e7fc82c 100644 --- a/spec/bundler/lock/lockfile_spec.rb +++ b/spec/bundler/lock/lockfile_spec.rb @@ -1638,7 +1638,7 @@ G expect(err).to eq <<~L.strip - Your lockfile is missing a checksums entry for \"myrack_middleware\", but can't be updated because frozen mode is set + Your lockfile is missing a CHECKSUMS entry for \"myrack_middleware\", but can't be updated because frozen mode is set Run `bundle install` elsewhere and add the updated Gemfile.lock to version control. L From 8576da4eb4d7dc7a1afb26126192971e787d7c5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 30 Jul 2025 11:48:10 +0200 Subject: [PATCH 22/28] [rubygems/rubygems] Enforce checksums strictly for registry gems https://github.com/rubygems/rubygems/commit/05199ae0c1 --- lib/bundler/checksum.rb | 6 +++ lib/bundler/definition.rb | 15 ++++++- spec/bundler/install/gemfile/git_spec.rb | 53 +++++++++++++++++++++--- spec/bundler/lock/lockfile_spec.rb | 34 +++++++++++++++ 4 files changed, 101 insertions(+), 7 deletions(-) diff --git a/lib/bundler/checksum.rb b/lib/bundler/checksum.rb index 356f4a48bcd11a..ce05818bb07992 100644 --- a/lib/bundler/checksum.rb +++ b/lib/bundler/checksum.rb @@ -205,6 +205,12 @@ def missing?(spec) @store[spec.lock_name].nil? end + def empty?(spec) + return false unless spec.source.is_a?(Bundler::Source::Rubygems) + + @store[spec.lock_name].empty? + end + def register(spec, checksum) register_checksum(spec.lock_name, checksum) end diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index 2313e467bc00b2..52f9c6e1255c36 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -557,6 +557,7 @@ def something_changed? @missing_lockfile_dep || @unlocking_bundler || @locked_spec_with_missing_checksums || + @locked_spec_with_empty_checksums || @locked_spec_with_missing_deps || @locked_spec_with_invalid_deps end @@ -836,6 +837,7 @@ def lockfile_changed_reason [@missing_lockfile_dep, "your lockfile is missing \"#{@missing_lockfile_dep}\""], [@unlocking_bundler, "an update to the version of Bundler itself was requested"], [@locked_spec_with_missing_checksums, "your lockfile is missing a CHECKSUMS entry for \"#{@locked_spec_with_missing_checksums}\""], + [@locked_spec_with_empty_checksums, "your lockfile has an empty CHECKSUMS entry for \"#{@locked_spec_with_empty_checksums}\""], [@locked_spec_with_missing_deps, "your lockfile includes \"#{@locked_spec_with_missing_deps}\" but not some of its dependencies"], [@locked_spec_with_invalid_deps, "your lockfile does not satisfy dependencies of \"#{@locked_spec_with_invalid_deps}\""], ].select(&:first).map(&:last).join(", ") @@ -895,13 +897,23 @@ def check_lockfile @locked_spec_with_invalid_deps = nil @locked_spec_with_missing_deps = nil @locked_spec_with_missing_checksums = nil + @locked_spec_with_empty_checksums = nil missing_deps = [] missing_checksums = [] + empty_checksums = [] invalid = [] @locked_specs.each do |s| - missing_checksums << s if @locked_checksums && s.source.checksum_store.missing?(s) + if @locked_checksums + checksum_store = s.source.checksum_store + + if checksum_store.missing?(s) + missing_checksums << s + elsif checksum_store.empty?(s) + empty_checksums << s + end + end validation = @locked_specs.validate_deps(s) @@ -910,6 +922,7 @@ def check_lockfile end @locked_spec_with_missing_checksums = missing_checksums.first.name if missing_checksums.any? + @locked_spec_with_empty_checksums = empty_checksums.first.name if empty_checksums.any? if missing_deps.any? @locked_specs.delete(missing_deps) diff --git a/spec/bundler/install/gemfile/git_spec.rb b/spec/bundler/install/gemfile/git_spec.rb index 4658dce9c001ed..216548cf27ccee 100644 --- a/spec/bundler/install/gemfile/git_spec.rb +++ b/spec/bundler/install/gemfile/git_spec.rb @@ -2,12 +2,8 @@ RSpec.describe "bundle install with git sources" do describe "when floating on main" do - let(:install_base_gemfile) do - build_git "foo" do |s| - s.executables = "foobar" - end - - install_gemfile <<-G + let(:base_gemfile) do + <<-G source "https://gem.repo1" git "#{lib_path("foo-1.0")}" do gem 'foo' @@ -15,6 +11,14 @@ G end + let(:install_base_gemfile) do + build_git "foo" do |s| + s.executables = "foobar" + end + + install_gemfile base_gemfile + end + it "fetches gems" do install_base_gemfile expect(the_bundle).to include_gems("foo 1.0") @@ -27,6 +31,43 @@ expect(out).to eq("WIN") end + it "does not (yet?) enforce CHECKSUMS" do + build_git "foo" + revision = revision_for(lib_path("foo-1.0")) + + bundle "config set lockfile_checksums true" + gemfile base_gemfile + + lockfile <<~L + GIT + remote: #{lib_path("foo-1.0")} + revision: #{revision} + specs: + foo (1.0) + + GEM + remote: https://gem.repo1/ + specs: + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + foo! + + CHECKSUMS + foo (1.0) + + BUNDLED WITH + #{Bundler::VERSION} + L + + bundle "config set frozen true" + + bundle "install" + expect(the_bundle).to include_gems("foo 1.0") + end + it "caches the git repo" do install_base_gemfile expect(Dir["#{default_bundle_path}/cache/bundler/git/foo-1.0-*"]).to have_attributes size: 1 diff --git a/spec/bundler/lock/lockfile_spec.rb b/spec/bundler/lock/lockfile_spec.rb index d0bee11e7fc82c..6b98e0924e41d8 100644 --- a/spec/bundler/lock/lockfile_spec.rb +++ b/spec/bundler/lock/lockfile_spec.rb @@ -1646,6 +1646,40 @@ expect(the_bundle).not_to include_gems "myrack_middleware 1.0" end + it "raises a clear error when frozen mode is set and lockfile has empty checksums in CHECKSUMS section, and does not install any gems" do + lockfile <<-L + GEM + remote: https://gem.repo2/ + specs: + myrack (0.9.1) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + myrack + + CHECKSUMS + myrack (0.9.1) + + BUNDLED WITH + #{Bundler::VERSION} + L + + install_gemfile <<-G, env: { "BUNDLE_FROZEN" => "true" }, raise_on_error: false + source "https://gem.repo2" + gem "myrack" + G + + expect(err).to eq <<~L.strip + Your lockfile has an empty CHECKSUMS entry for \"myrack\", but can't be updated because frozen mode is set + + Run `bundle install` elsewhere and add the updated Gemfile.lock to version control. + L + + expect(the_bundle).not_to include_gems "myrack 0.9.1" + end + it "automatically fixes the lockfile when it's missing deps, they conflict with other locked deps, but conflicts are fixable" do build_repo4 do build_gem "other_dep", "0.9" From 7125f7635d43f67b1664bf85e72a34d868259822 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 11 Aug 2025 22:02:10 +0200 Subject: [PATCH 23/28] [rubygems/rubygems] Use spaces around optional parameter values https://github.com/rubygems/rubygems/commit/b58829a868 --- lib/bundler/resolver.rb | 2 +- lib/bundler/rubygems_ext.rb | 2 +- lib/rubygems.rb | 10 +++++----- lib/rubygems/command.rb | 2 +- lib/rubygems/command_manager.rb | 6 +++--- lib/rubygems/dependency.rb | 2 +- lib/rubygems/dependency_installer.rb | 2 +- lib/rubygems/dependency_list.rb | 2 +- lib/rubygems/deprecate.rb | 2 +- lib/rubygems/errors.rb | 2 +- lib/rubygems/exceptions.rb | 4 ++-- lib/rubygems/ext/cargo_builder.rb | 2 +- lib/rubygems/ext/cmake_builder.rb | 4 ++-- lib/rubygems/ext/configure_builder.rb | 4 ++-- lib/rubygems/ext/ext_conf_builder.rb | 4 ++-- lib/rubygems/ext/rake_builder.rb | 4 ++-- lib/rubygems/installer.rb | 2 +- lib/rubygems/name_tuple.rb | 2 +- lib/rubygems/package/tar_writer.rb | 2 +- lib/rubygems/remote_fetcher.rb | 2 +- lib/rubygems/resolver.rb | 2 +- lib/rubygems/resolver/conflict.rb | 2 +- lib/rubygems/source.rb | 4 ++-- lib/rubygems/spec_fetcher.rb | 8 ++++---- lib/rubygems/specification.rb | 2 +- lib/rubygems/text.rb | 2 +- lib/rubygems/user_interaction.rb | 12 ++++++------ lib/rubygems/validator.rb | 2 +- test/rubygems/helper.rb | 6 +++--- test/rubygems/installer_test_case.rb | 2 +- test/rubygems/mock_gem_ui.rb | 2 +- test/rubygems/test_gem_remote_fetcher.rb | 2 +- 32 files changed, 54 insertions(+), 54 deletions(-) diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb index fba9badec727ba..1dbf565d4676e8 100644 --- a/lib/bundler/resolver.rb +++ b/lib/bundler/resolver.rb @@ -165,7 +165,7 @@ def parse_dependency(package, dependency) PubGrub::VersionConstraint.new(package, range: range) end - def versions_for(package, range=VersionRange.any) + def versions_for(package, range = VersionRange.any) range.select_versions(@sorted_versions[package]) end diff --git a/lib/bundler/rubygems_ext.rb b/lib/bundler/rubygems_ext.rb index 8cf3b56b831f0f..fedf44b0e69b14 100644 --- a/lib/bundler/rubygems_ext.rb +++ b/lib/bundler/rubygems_ext.rb @@ -417,7 +417,7 @@ class NameTuple unless Gem::NameTuple.new("a", Gem::Version.new("1"), Gem::Platform.new("x86_64-linux")).platform.is_a?(String) alias_method :initialize_with_platform, :initialize - def initialize(name, version, platform=Gem::Platform::RUBY) + def initialize(name, version, platform = Gem::Platform::RUBY) if Gem::Platform === platform initialize_with_platform(name, version, platform.to_s) else diff --git a/lib/rubygems.rb b/lib/rubygems.rb index d4e88579e823db..f8f1451ee661a7 100644 --- a/lib/rubygems.rb +++ b/lib/rubygems.rb @@ -224,7 +224,7 @@ def self.needs finish_resolve rs end - def self.finish_resolve(request_set=Gem::RequestSet.new) + def self.finish_resolve(request_set = Gem::RequestSet.new) request_set.import Gem::Specification.unresolved_deps.values request_set.import Gem.loaded_specs.values.map {|s| Gem::Dependency.new(s.name, s.version) } @@ -341,7 +341,7 @@ def self.binary_mode ## # The path where gem executables are to be installed. - def self.bindir(install_dir=Gem.dir) + def self.bindir(install_dir = Gem.dir) return File.join install_dir, "bin" unless install_dir.to_s == Gem.default_dir.to_s Gem.default_bindir @@ -350,7 +350,7 @@ def self.bindir(install_dir=Gem.dir) ## # The path were rubygems plugins are to be installed. - def self.plugindir(install_dir=Gem.dir) + def self.plugindir(install_dir = Gem.dir) File.join install_dir, "plugins" end @@ -534,7 +534,7 @@ def self.extension_api_version # :nodoc: # Note that find_files will return all files even if they are from different # versions of the same gem. See also find_latest_files - def self.find_files(glob, check_load_path=true) + def self.find_files(glob, check_load_path = true) files = [] files = find_files_from_load_path glob if check_load_path @@ -571,7 +571,7 @@ def self.find_files_from_load_path(glob) # :nodoc: # Unlike find_files, find_latest_files will return only files from the # latest version of a gem. - def self.find_latest_files(glob, check_load_path=true) + def self.find_latest_files(glob, check_load_path = true) files = [] files = find_files_from_load_path glob if check_load_path diff --git a/lib/rubygems/command.rb b/lib/rubygems/command.rb index 3a149ea38e23e2..d38363f293c79c 100644 --- a/lib/rubygems/command.rb +++ b/lib/rubygems/command.rb @@ -117,7 +117,7 @@ def self.specific_extra_args_hash # Unhandled arguments (gem names, files, etc.) are left in # options[:args]. - def initialize(command, summary=nil, defaults={}) + def initialize(command, summary = nil, defaults = {}) @command = command @summary = summary @program_name = "gem #{command}" diff --git a/lib/rubygems/command_manager.rb b/lib/rubygems/command_manager.rb index 15834ce4dd0c09..8521517a24ef93 100644 --- a/lib/rubygems/command_manager.rb +++ b/lib/rubygems/command_manager.rb @@ -118,7 +118,7 @@ def initialize ## # Register the Symbol +command+ as a gem command. - def register_command(command, obj=false) + def register_command(command, obj = false) @commands[command] = obj end @@ -148,7 +148,7 @@ def command_names ## # Run the command specified by +args+. - def run(args, build_args=nil) + def run(args, build_args = nil) process_args(args, build_args) rescue StandardError, Gem::Timeout::Error => ex if ex.respond_to?(:detailed_message) @@ -165,7 +165,7 @@ def run(args, build_args=nil) terminate_interaction(1) end - def process_args(args, build_args=nil) + def process_args(args, build_args = nil) if args.empty? say Gem::Command::HELP terminate_interaction 1 diff --git a/lib/rubygems/dependency.rb b/lib/rubygems/dependency.rb index d1ec9222af1a89..1e91f493a64eb5 100644 --- a/lib/rubygems/dependency.rb +++ b/lib/rubygems/dependency.rb @@ -217,7 +217,7 @@ def =~(other) # NOTE: Unlike #matches_spec? this method does not return true when the # version is a prerelease version unless this is a prerelease dependency. - def match?(obj, version=nil, allow_prerelease=false) + def match?(obj, version = nil, allow_prerelease = false) if !version name = obj.name version = obj.version diff --git a/lib/rubygems/dependency_installer.rb b/lib/rubygems/dependency_installer.rb index b119dca1cf2912..b4152e83e913b4 100644 --- a/lib/rubygems/dependency_installer.rb +++ b/lib/rubygems/dependency_installer.rb @@ -127,7 +127,7 @@ def consider_remote? # sources. Gems are sorted with newer gems preferred over older gems, and # local gems preferred over remote gems. - def find_gems_with_sources(dep, best_only=false) # :nodoc: + def find_gems_with_sources(dep, best_only = false) # :nodoc: set = Gem::AvailableSet.new if consider_local? diff --git a/lib/rubygems/dependency_list.rb b/lib/rubygems/dependency_list.rb index ad5e59e8c173f1..99643a426d423a 100644 --- a/lib/rubygems/dependency_list.rb +++ b/lib/rubygems/dependency_list.rb @@ -140,7 +140,7 @@ def why_not_ok?(quick = false) # If removing the gemspec creates breaks a currently ok dependency, then it # is NOT ok to remove the gemspec. - def ok_to_remove?(full_name, check_dev=true) + def ok_to_remove?(full_name, check_dev = true) gem_to_remove = find_name full_name # If the state is inconsistent, at least don't crash diff --git a/lib/rubygems/deprecate.rb b/lib/rubygems/deprecate.rb index a20649cbdab166..303b344d42c838 100644 --- a/lib/rubygems/deprecate.rb +++ b/lib/rubygems/deprecate.rb @@ -126,7 +126,7 @@ def deprecate(name, repl, year, month) # telling the user of +repl+ (unless +repl+ is :none) and the # Rubygems version that it is planned to go away. - def rubygems_deprecate(name, replacement=:none, version=nil) + def rubygems_deprecate(name, replacement = :none, version = nil) class_eval do old = "_deprecated_#{name}" alias_method old, name diff --git a/lib/rubygems/errors.rb b/lib/rubygems/errors.rb index 57fb3eb12008a1..4bbc5217e0e639 100644 --- a/lib/rubygems/errors.rb +++ b/lib/rubygems/errors.rb @@ -26,7 +26,7 @@ class LoadError < ::LoadError # system. Instead of rescuing from this class, make sure to rescue from the # superclass Gem::LoadError to catch all types of load errors. class MissingSpecError < Gem::LoadError - def initialize(name, requirement, extra_message=nil) + def initialize(name, requirement, extra_message = nil) @name = name @requirement = requirement @extra_message = extra_message diff --git a/lib/rubygems/exceptions.rb b/lib/rubygems/exceptions.rb index 793324b875c754..adf7ad6d7d05ac 100644 --- a/lib/rubygems/exceptions.rb +++ b/lib/rubygems/exceptions.rb @@ -110,7 +110,7 @@ class Gem::SpecificGemNotFoundException < Gem::GemNotFoundException # and +version+. Any +errors+ encountered when attempting to find the gem # are also stored. - def initialize(name, version, errors=nil) + def initialize(name, version, errors = nil) super "Could not find a valid gem '#{name}' (#{version}) locally or in a repository" @name = name @@ -261,7 +261,7 @@ class Gem::UnsatisfiableDependencyError < Gem::DependencyError # Creates a new UnsatisfiableDependencyError for the unsatisfiable # Gem::Resolver::DependencyRequest +dep+ - def initialize(dep, platform_mismatch=nil) + def initialize(dep, platform_mismatch = nil) if platform_mismatch && !platform_mismatch.empty? plats = platform_mismatch.map {|x| x.platform.to_s }.sort.uniq super "Unable to resolve dependency: No match for '#{dep}' on this platform. Found: #{plats.join(", ")}" diff --git a/lib/rubygems/ext/cargo_builder.rb b/lib/rubygems/ext/cargo_builder.rb index 21b50f394d552d..e58d0bb75ccb9d 100644 --- a/lib/rubygems/ext/cargo_builder.rb +++ b/lib/rubygems/ext/cargo_builder.rb @@ -15,7 +15,7 @@ def initialize end def build(extension, dest_path, results, args = [], lib_dir = nil, cargo_dir = Dir.pwd, - target_rbconfig=Gem.target_rbconfig) + target_rbconfig = Gem.target_rbconfig) require "tempfile" require "fileutils" diff --git a/lib/rubygems/ext/cmake_builder.rb b/lib/rubygems/ext/cmake_builder.rb index 34564f668da87d..c7bfbb8a57ad27 100644 --- a/lib/rubygems/ext/cmake_builder.rb +++ b/lib/rubygems/ext/cmake_builder.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true class Gem::Ext::CmakeBuilder < Gem::Ext::Builder - def self.build(extension, dest_path, results, args=[], lib_dir=nil, cmake_dir=Dir.pwd, - target_rbconfig=Gem.target_rbconfig) + def self.build(extension, dest_path, results, args = [], lib_dir = nil, cmake_dir = Dir.pwd, + target_rbconfig = Gem.target_rbconfig) if target_rbconfig.path warn "--target-rbconfig is not yet supported for CMake extensions. Ignoring" end diff --git a/lib/rubygems/ext/configure_builder.rb b/lib/rubygems/ext/configure_builder.rb index d91b1ec5e82a17..76c1cd8b197548 100644 --- a/lib/rubygems/ext/configure_builder.rb +++ b/lib/rubygems/ext/configure_builder.rb @@ -7,8 +7,8 @@ #++ class Gem::Ext::ConfigureBuilder < Gem::Ext::Builder - def self.build(extension, dest_path, results, args=[], lib_dir=nil, configure_dir=Dir.pwd, - target_rbconfig=Gem.target_rbconfig) + def self.build(extension, dest_path, results, args = [], lib_dir = nil, configure_dir = Dir.pwd, + target_rbconfig = Gem.target_rbconfig) if target_rbconfig.path warn "--target-rbconfig is not yet supported for configure-based extensions. Ignoring" end diff --git a/lib/rubygems/ext/ext_conf_builder.rb b/lib/rubygems/ext/ext_conf_builder.rb index 8aa15962a0f307..ec2fa59412df64 100644 --- a/lib/rubygems/ext/ext_conf_builder.rb +++ b/lib/rubygems/ext/ext_conf_builder.rb @@ -7,8 +7,8 @@ #++ class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder - def self.build(extension, dest_path, results, args=[], lib_dir=nil, extension_dir=Dir.pwd, - target_rbconfig=Gem.target_rbconfig) + def self.build(extension, dest_path, results, args = [], lib_dir = nil, extension_dir = Dir.pwd, + target_rbconfig = Gem.target_rbconfig) require "fileutils" require "tempfile" diff --git a/lib/rubygems/ext/rake_builder.rb b/lib/rubygems/ext/rake_builder.rb index 8edd8d1373768f..0eac5a180ca3ca 100644 --- a/lib/rubygems/ext/rake_builder.rb +++ b/lib/rubygems/ext/rake_builder.rb @@ -7,8 +7,8 @@ #++ class Gem::Ext::RakeBuilder < Gem::Ext::Builder - def self.build(extension, dest_path, results, args=[], lib_dir=nil, extension_dir=Dir.pwd, - target_rbconfig=Gem.target_rbconfig) + def self.build(extension, dest_path, results, args = [], lib_dir = nil, extension_dir = Dir.pwd, + target_rbconfig = Gem.target_rbconfig) if target_rbconfig.path warn "--target-rbconfig is not yet supported for Rake extensions. Ignoring" end diff --git a/lib/rubygems/installer.rb b/lib/rubygems/installer.rb index d0092899a40263..0cfe59b5bb5be3 100644 --- a/lib/rubygems/installer.rb +++ b/lib/rubygems/installer.rb @@ -153,7 +153,7 @@ def self.for_spec(spec, options = {}) # process. If not set, then Gem::Command.build_args is used # :post_install_message:: Print gem post install message if true - def initialize(package, options={}) + def initialize(package, options = {}) require "fileutils" @options = options diff --git a/lib/rubygems/name_tuple.rb b/lib/rubygems/name_tuple.rb index 3f4a6fcf3dfbb1..67c6f30a3dfff4 100644 --- a/lib/rubygems/name_tuple.rb +++ b/lib/rubygems/name_tuple.rb @@ -6,7 +6,7 @@ # wrap the data returned from the indexes. class Gem::NameTuple - def initialize(name, version, platform=Gem::Platform::RUBY) + def initialize(name, version, platform = Gem::Platform::RUBY) @name = name @version = version diff --git a/lib/rubygems/package/tar_writer.rb b/lib/rubygems/package/tar_writer.rb index 7dcb9737c06620..39fed9e2afe74b 100644 --- a/lib/rubygems/package/tar_writer.rb +++ b/lib/rubygems/package/tar_writer.rb @@ -99,7 +99,7 @@ def initialize(io) # Gem.source_date_epoch if not specified), and yields an IO for # writing the file to - def add_file(name, mode, mtime=nil) # :yields: io + def add_file(name, mode, mtime = nil) # :yields: io check_closed name, prefix = split_name name diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb index 355a668b39f81e..6ed0842963e6f0 100644 --- a/lib/rubygems/remote_fetcher.rb +++ b/lib/rubygems/remote_fetcher.rb @@ -72,7 +72,7 @@ def self.fetcher # +headers+: A set of additional HTTP headers to be sent to the server when # fetching the gem. - def initialize(proxy=nil, dns=nil, headers={}) + def initialize(proxy = nil, dns = nil, headers = {}) require_relative "core_ext/tcpsocket_init" if Gem.configuration.ipv4_fallback_enabled require_relative "vendored_net_http" require_relative "vendor/uri/lib/uri" diff --git a/lib/rubygems/resolver.rb b/lib/rubygems/resolver.rb index 9bf5f8093041d7..ed4cbde3bab12c 100644 --- a/lib/rubygems/resolver.rb +++ b/lib/rubygems/resolver.rb @@ -144,7 +144,7 @@ def activation_request(dep, possible) # :nodoc: [spec, activation_request] end - def requests(s, act, reqs=[]) # :nodoc: + def requests(s, act, reqs = []) # :nodoc: return reqs if @ignore_dependencies s.fetch_development_dependencies if @development diff --git a/lib/rubygems/resolver/conflict.rb b/lib/rubygems/resolver/conflict.rb index 367a36b43d7fe5..77c3add4b32d21 100644 --- a/lib/rubygems/resolver/conflict.rb +++ b/lib/rubygems/resolver/conflict.rb @@ -21,7 +21,7 @@ class Gem::Resolver::Conflict # Creates a new resolver conflict when +dependency+ is in conflict with an # already +activated+ specification. - def initialize(dependency, activated, failed_dep=dependency) + def initialize(dependency, activated, failed_dep = dependency) @dependency = dependency @activated = activated @failed_dep = failed_dep diff --git a/lib/rubygems/source.rb b/lib/rubygems/source.rb index 772ad04bc92575..8b031e27a8d611 100644 --- a/lib/rubygems/source.rb +++ b/lib/rubygems/source.rb @@ -190,7 +190,7 @@ def load_specs(type) # Downloads +spec+ and writes it to +dir+. See also # Gem::RemoteFetcher#download. - def download(spec, dir=Dir.pwd) + def download(spec, dir = Dir.pwd) fetcher = Gem::RemoteFetcher.fetcher fetcher.download spec, uri.to_s, dir end @@ -210,7 +210,7 @@ def pretty_print(q) # :nodoc: end end - def typo_squatting?(host, distance_threshold=4) + def typo_squatting?(host, distance_threshold = 4) return if @uri.host.nil? levenshtein_distance(@uri.host, host).between? 1, distance_threshold end diff --git a/lib/rubygems/spec_fetcher.rb b/lib/rubygems/spec_fetcher.rb index 285f117b393269..835dedf9489a2c 100644 --- a/lib/rubygems/spec_fetcher.rb +++ b/lib/rubygems/spec_fetcher.rb @@ -83,7 +83,7 @@ def initialize(sources = nil) # # If +matching_platform+ is false, gems for all platforms are returned. - def search_for_dependency(dependency, matching_platform=true) + def search_for_dependency(dependency, matching_platform = true) found = {} rejected_specs = {} @@ -130,7 +130,7 @@ def search_for_dependency(dependency, matching_platform=true) ## # Return all gem name tuples who's names match +obj+ - def detect(type=:complete) + def detect(type = :complete) tuples = [] list, _ = available_specs(type) @@ -150,7 +150,7 @@ def detect(type=:complete) # # If +matching_platform+ is false, gems for all platforms are returned. - def spec_for_dependency(dependency, matching_platform=true) + def spec_for_dependency(dependency, matching_platform = true) tuples, errors = search_for_dependency(dependency, matching_platform) specs = [] @@ -280,7 +280,7 @@ def available_specs(type) # Retrieves NameTuples from +source+ of the given +type+ (:prerelease, # etc.). If +gracefully_ignore+ is true, errors are ignored. - def tuples_for(source, type, gracefully_ignore=false) # :nodoc: + def tuples_for(source, type, gracefully_ignore = false) # :nodoc: @caches[type][source.uri] ||= source.load_specs(type).sort_by(&:name) rescue Gem::RemoteFetcher::FetchError diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb index 68ebbf8bc31454..1d351f8aff9746 100644 --- a/lib/rubygems/specification.rb +++ b/lib/rubygems/specification.rb @@ -1757,7 +1757,7 @@ def dependencies # # [depending_gem, dependency, [list_of_gems_that_satisfy_dependency]] - def dependent_gems(check_dev=true) + def dependent_gems(check_dev = true) out = [] Gem::Specification.each do |spec| deps = check_dev ? spec.dependencies : spec.runtime_dependencies diff --git a/lib/rubygems/text.rb b/lib/rubygems/text.rb index da0795b771b350..88d4ce59b4b9ae 100644 --- a/lib/rubygems/text.rb +++ b/lib/rubygems/text.rb @@ -21,7 +21,7 @@ def truncate_text(text, description, max_length = 100_000) # Wraps +text+ to +wrap+ characters and optionally indents by +indent+ # characters - def format_text(text, wrap, indent=0) + def format_text(text, wrap, indent = 0) result = [] work = clean_text(text) diff --git a/lib/rubygems/user_interaction.rb b/lib/rubygems/user_interaction.rb index 0172c4ee897a40..571137629406fb 100644 --- a/lib/rubygems/user_interaction.rb +++ b/lib/rubygems/user_interaction.rb @@ -193,7 +193,7 @@ class Gem::StreamUI # then special operations (like asking for passwords) will use the TTY # commands to disable character echo. - def initialize(in_stream, out_stream, err_stream=$stderr, usetty=true) + def initialize(in_stream, out_stream, err_stream = $stderr, usetty = true) @ins = in_stream @outs = out_stream @errs = err_stream @@ -246,7 +246,7 @@ def choose_from_list(question, list) # to a tty, raises an exception if default is nil, otherwise returns # default. - def ask_yes_no(question, default=nil) + def ask_yes_no(question, default = nil) unless tty? if default.nil? raise Gem::OperationNotSupportedError, @@ -325,14 +325,14 @@ def _gets_noecho ## # Display a statement. - def say(statement="") + def say(statement = "") @outs.puts statement end ## # Display an informational alert. Will ask +question+ if it is not nil. - def alert(statement, question=nil) + def alert(statement, question = nil) @outs.puts "INFO: #{statement}" ask(question) if question end @@ -340,7 +340,7 @@ def alert(statement, question=nil) ## # Display a warning on stderr. Will ask +question+ if it is not nil. - def alert_warning(statement, question=nil) + def alert_warning(statement, question = nil) @errs.puts "WARNING: #{statement}" ask(question) if question end @@ -349,7 +349,7 @@ def alert_warning(statement, question=nil) # Display an error message in a location expected to get error messages. # Will ask +question+ if it is not nil. - def alert_error(statement, question=nil) + def alert_error(statement, question = nil) @errs.puts "ERROR: #{statement}" ask(question) if question end diff --git a/lib/rubygems/validator.rb b/lib/rubygems/validator.rb index 57e0747eb4a7d5..eb5b513570778e 100644 --- a/lib/rubygems/validator.rb +++ b/lib/rubygems/validator.rb @@ -59,7 +59,7 @@ def <=>(other) # :nodoc: #-- # TODO needs further cleanup - def alien(gems=[]) + def alien(gems = []) errors = Hash.new {|h,k| h[k] = {} } Gem::Specification.each do |spec| diff --git a/test/rubygems/helper.rb b/test/rubygems/helper.rb index 2f4abff1e84ca9..51c99a1bc5e211 100644 --- a/test/rubygems/helper.rb +++ b/test/rubygems/helper.rb @@ -724,7 +724,7 @@ def all_spec_names # # Use this with #write_file to build an installed gem. - def quick_gem(name, version="2") + def quick_gem(name, version = "2") require "rubygems/specification" spec = Gem::Specification.new do |s| @@ -1033,7 +1033,7 @@ def util_set_arch(arch) # Add +spec+ to +@fetcher+ serving the data in the file +path+. # +repo+ indicates which repo to make +spec+ appear to be in. - def add_to_fetcher(spec, path=nil, repo=@gem_repo) + def add_to_fetcher(spec, path = nil, repo = @gem_repo) path ||= spec.cache_file @fetcher.data["#{@gem_repo}gems/#{spec.file_name}"] = read_binary(path) end @@ -1206,7 +1206,7 @@ def wait_for_child_process_to_exit ## # Allows the proper version of +rake+ to be used for the test. - def build_rake_in(good=true) + def build_rake_in(good = true) gem_ruby = Gem.ruby Gem.ruby = self.class.rubybin env_rake = ENV["rake"] diff --git a/test/rubygems/installer_test_case.rb b/test/rubygems/installer_test_case.rb index 7a719843207c82..ded205c5f56273 100644 --- a/test/rubygems/installer_test_case.rb +++ b/test/rubygems/installer_test_case.rb @@ -215,7 +215,7 @@ def util_setup_gem(ui = @ui, force = true) ## # Creates an installer for +spec+ that will install into +gem_home+. - def util_installer(spec, gem_home, force=true) + def util_installer(spec, gem_home, force = true) Gem::Installer.at(spec.cache_file, install_dir: gem_home, force: force) diff --git a/test/rubygems/mock_gem_ui.rb b/test/rubygems/mock_gem_ui.rb index 218d4b6965d1eb..fb804c5555cf6d 100644 --- a/test/rubygems/mock_gem_ui.rb +++ b/test/rubygems/mock_gem_ui.rb @@ -77,7 +77,7 @@ def terminated? @terminated end - def terminate_interaction(status=0) + def terminate_interaction(status = 0) @terminated = true raise TermError, status if status != 0 diff --git a/test/rubygems/test_gem_remote_fetcher.rb b/test/rubygems/test_gem_remote_fetcher.rb index ca858cfda5d33d..5c1d89fad6934a 100644 --- a/test/rubygems/test_gem_remote_fetcher.rb +++ b/test/rubygems/test_gem_remote_fetcher.rb @@ -592,7 +592,7 @@ def test_yaml_error_on_size end end - def assert_error(exception_class=Exception) + def assert_error(exception_class = Exception) got_exception = false begin From f0ee7630ed8993ef80cd11b12330c78616819ff0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 11 Aug 2025 20:01:45 +0200 Subject: [PATCH 24/28] Merge specs checking CLI flags and subcommands are documented We had them duplicated, but with slightly different features: * The ones in `other/cli_man_pages.rb` enforced a specific structure to document CLI options, so were less likely to have false positives. * The ones in `quality_spec.rb` were able to check subcommands and their flags. This commit merges both and preserves the best of both. --- spec/bundler/other/cli_man_pages_spec.rb | 85 ++++++++++++++++-------- spec/bundler/quality_spec.rb | 49 -------------- 2 files changed, 56 insertions(+), 78 deletions(-) diff --git a/spec/bundler/other/cli_man_pages_spec.rb b/spec/bundler/other/cli_man_pages_spec.rb index 84ffca14e62379..6efd2904d6497a 100644 --- a/spec/bundler/other/cli_man_pages_spec.rb +++ b/spec/bundler/other/cli_man_pages_spec.rb @@ -1,49 +1,72 @@ # frozen_string_literal: true RSpec.describe "bundle commands" do - it "expects all commands to have a man page" do - Bundler::CLI.all_commands.each_key do |command_name| - next if command_name == "cli_help" + it "expects all commands to have all options and subcommands documented" do + check_commands!(Bundler::CLI) - expect(man_page(command_name)).to exist + Bundler::CLI.subcommand_classes.each_value do |klass| + check_commands!(klass) end end - it "expects all commands to have all options documented" do - Bundler::CLI.all_commands.each do |command_name, command| - next if command_name == "cli_help" + private + + def check_commands!(command_class) + command_class.commands.each do |command_name, command| + next if command.is_a?(Bundler::Thor::HiddenCommand) + + if command_class == Bundler::CLI + man_page = man_page(command_name) + expect(man_page).to exist + + check_options!(command, man_page) + else + man_page = man_page(command.ancestor_name) + expect(man_page).to exist - man_page_content = man_page(command_name).read + check_options!(command, man_page) + check_subcommand!(command_name, man_page) + end + end + end - command.options.each do |_, option| - aliases = option.aliases - formatted_aliases = aliases.sort.map {|name| "`#{name}`" }.join(", ") if aliases + def check_options!(command, man_page) + command.options.each do |_, option| + check_option!(option, man_page) + end + end - help = if option.type == :boolean - "* #{append_aliases("`#{option.switch_name}`", formatted_aliases)}:" - elsif option.enum - formatted_aliases = "`#{option.switch_name}`" if aliases.empty? && option.lazy_default - "* #{prepend_aliases(option.enum.sort.map {|enum| "`#{option.switch_name}=#{enum}`" }.join(", "), formatted_aliases)}:" - else - names = [option.switch_name, *aliases] - value = - case option.type - when :array then "" - when :numeric then "" - else option.name.upcase - end + def check_option!(option, man_page) + man_page_content = man_page.read - value = option.type != :numeric && option.lazy_default ? "[=#{value}]" : "=#{value}" + aliases = option.aliases + formatted_aliases = aliases.sort.map {|name| "`#{name}`" }.join(", ") if aliases - "* #{names.map {|name| "`#{name}#{value}`" }.join(", ")}:" + help = if option.type == :boolean + "* #{append_aliases("`#{option.switch_name}`", formatted_aliases)}:" + elsif option.enum + formatted_aliases = "`#{option.switch_name}`" if aliases.empty? && option.lazy_default + "* #{prepend_aliases(option.enum.sort.map {|enum| "`#{option.switch_name}=#{enum}`" }.join(", "), formatted_aliases)}:" + else + names = [option.switch_name, *aliases] + value = + case option.type + when :array then "" + when :numeric then "" + else option.name.upcase end - expect(man_page_content).to include(help) - end + value = option.type != :numeric && option.lazy_default ? "[=#{value}]" : "=#{value}" + + "* #{names.map {|name| "`#{name}#{value}`" }.join(", ")}:" end + + expect(man_page_content).to include(help) end - private + def check_subcommand!(name, man_page) + expect(man_page.read).to match(name) + end def append_aliases(text, aliases) return text if aliases.empty? @@ -57,6 +80,10 @@ def prepend_aliases(text, aliases) "#{aliases}, #{text}" end + def man_page_content(command_name) + man_page(command_name).read + end + def man_page(command_name) source_root.join("lib/bundler/man/bundle-#{command_name}.1.ronn") end diff --git a/spec/bundler/quality_spec.rb b/spec/bundler/quality_spec.rb index 18d8e20030ce1a..3e5a960a960f2e 100644 --- a/spec/bundler/quality_spec.rb +++ b/spec/bundler/quality_spec.rb @@ -251,58 +251,9 @@ def check_for_specific_pronouns(filename) expect(lib_code).to eq(spec_code) end - it "documents all cli command options in their associated man pages" do - commands = normalize_commands_and_options(Bundler::CLI) - cli_and_man_pages_in_sync!(commands) - - Bundler::CLI.subcommand_classes.each do |_, klass| - subcommands = normalize_commands_and_options(klass) - - cli_and_man_pages_in_sync!(subcommands) - end - end - private def each_line(filename, &block) File.readlines(filename, encoding: "UTF-8").each_with_index(&block) end - - def normalize_commands_and_options(command_class) - commands = {} - - command_class.commands.each do |command_name, command| - next if command.is_a?(Bundler::Thor::HiddenCommand) - - key = command.ancestor_name || command_name - commands[key] ||= [] - # Verify that all subcommands are documented in the main command's man page. - commands[key] << command_name unless command_class == Bundler::CLI - - command.options.each do |_, option| - commands[key] << option.switch_name - end - end - - commands - end - - def cli_and_man_pages_in_sync!(commands) - commands.each do |command_name, opts| - man_page_path = man_tracked_files.find {|f| File.basename(f) == "bundle-#{command_name}.1.ronn" } - expect(man_page_path).to_not be_nil, "The command #{command_name} has no associated man page." - - next if opts.empty? - - man_page_content = File.read(man_page_path) - opts.each do |option_name| - error_msg = <<~EOM - The command #{command_name} has no mention of the option or subcommand `#{option_name}` in its man page. - Document the `#{option_name}` in the man page to discard this error. - EOM - - expect(man_page_content).to match(option_name), error_msg - end - end - end end From 5be3ebb0fdc67d0340c84af7f1086333f23b4240 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 7 Aug 2025 16:30:48 +0900 Subject: [PATCH 25/28] [ruby/json] Remove trailing spaces [ci skip] https://github.com/ruby/json/commit/2d2e0d403d --- ext/json/lib/json/add/string.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/json/lib/json/add/string.rb b/ext/json/lib/json/add/string.rb index 46f07967cd624d..64b1c217f86be2 100644 --- a/ext/json/lib/json/add/string.rb +++ b/ext/json/lib/json/add/string.rb @@ -5,7 +5,7 @@ class String # call-seq: json_create(o) - # + # # Raw Strings are JSON Objects (the raw bytes are stored in an array for the # key "raw"). The Ruby String can be created by this class method. def self.json_create(object) @@ -13,7 +13,7 @@ def self.json_create(object) end # call-seq: to_json_raw_object() - # + # # This method creates a raw object hash, that can be nested into # other data structures and will be generated as a raw string. This # method should be used, if you want to convert raw strings to JSON @@ -26,7 +26,7 @@ def to_json_raw_object end # call-seq: to_json_raw(*args) - # + # # This method creates a JSON text from the result of a call to # to_json_raw_object of this String. def to_json_raw(...) From 0de695e23c9fbfe5d8d363282a592787254def30 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Fri, 8 Aug 2025 19:48:29 +0900 Subject: [PATCH 26/28] [ruby/json] Append newline at EOF [ci skip] https://github.com/ruby/json/commit/72e231f929 --- ext/json/lib/json/add/string.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/json/lib/json/add/string.rb b/ext/json/lib/json/add/string.rb index 64b1c217f86be2..9c3bde27fbcf37 100644 --- a/ext/json/lib/json/add/string.rb +++ b/ext/json/lib/json/add/string.rb @@ -32,4 +32,4 @@ def to_json_raw_object def to_json_raw(...) to_json_raw_object.to_json(...) end -end \ No newline at end of file +end From e3ce56c9dc40d0eeb6d9de453e94621503afd9e6 Mon Sep 17 00:00:00 2001 From: Douglas Eichelberger Date: Wed, 13 Aug 2025 13:52:40 -0700 Subject: [PATCH 27/28] Fix typos --- ext/json/generator/generator.c | 4 ++-- ext/json/lib/json.rb | 2 +- ext/json/lib/json/common.rb | 2 +- ext/json/parser/parser.c | 2 +- test/json/ractor_test.rb | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ext/json/generator/generator.c b/ext/json/generator/generator.c index 5248a9e26aae3e..9c6ed930495a51 100644 --- a/ext/json/generator/generator.c +++ b/ext/json/generator/generator.c @@ -137,8 +137,8 @@ static inline FORCE_INLINE void search_flush(search_state *search) { // Do not remove this conditional without profiling, specifically escape-heavy text. // escape_UTF8_char_basic will advance search->ptr and search->cursor (effectively a search_flush). - // For back-to-back characters that need to be escaped, specifcally for the SIMD code paths, this method - // will be called just before calling escape_UTF8_char_basic. There will be no characers to append for the + // For back-to-back characters that need to be escaped, specifically for the SIMD code paths, this method + // will be called just before calling escape_UTF8_char_basic. There will be no characters to append for the // consecutive characters that need to be escaped. While the fbuffer_append is a no-op if // nothing needs to be flushed, we can save a few memory references with this conditional. if (search->ptr > search->cursor) { diff --git a/ext/json/lib/json.rb b/ext/json/lib/json.rb index 735f2380667daa..0ebff2f948af56 100644 --- a/ext/json/lib/json.rb +++ b/ext/json/lib/json.rb @@ -133,7 +133,7 @@ # When not specified: # # The last value is used and a deprecation warning emitted. # JSON.parse('{"a": 1, "a":2}') => {"a" => 2} -# # waring: detected duplicate keys in JSON object. +# # warning: detected duplicate keys in JSON object. # # This will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true` # # When set to `+true+` diff --git a/ext/json/lib/json/common.rb b/ext/json/lib/json/common.rb index 9a878cead9f6a3..e99d152a884898 100644 --- a/ext/json/lib/json/common.rb +++ b/ext/json/lib/json/common.rb @@ -1002,7 +1002,7 @@ class Coder # See {Parsing Options}[#module-JSON-label-Parsing+Options], and {Generating Options}[#module-JSON-label-Generating+Options]. # # For generation, the strict: true option is always set. When a Ruby object with no native \JSON counterpart is - # encoutered, the block provided to the initialize method is invoked, and must return a Ruby object that has a native + # encountered, the block provided to the initialize method is invoked, and must return a Ruby object that has a native # \JSON counterpart: # # module MyApp diff --git a/ext/json/parser/parser.c b/ext/json/parser/parser.c index ab9d6c205e69b2..1e6ee753f0cf4b 100644 --- a/ext/json/parser/parser.c +++ b/ext/json/parser/parser.c @@ -1265,7 +1265,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config) break; } - raise_parse_error("unreacheable: %s", state); + raise_parse_error("unreachable: %s", state); } static void json_ensure_eof(JSON_ParserState *state) diff --git a/test/json/ractor_test.rb b/test/json/ractor_test.rb index dda34c64c08520..0ebdb0e91a1cfc 100644 --- a/test/json/ractor_test.rb +++ b/test/json/ractor_test.rb @@ -42,7 +42,7 @@ def test_generate else puts "Expected:" puts expected_json - puts "Acutual:" + puts "Actual:" puts actual_json puts exit 1 From 7ddc53bc0c57b1c079e40a74d233f537111b3e92 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 18 Aug 2025 11:39:30 +0900 Subject: [PATCH 28/28] Exclude prism/generate-srcs.mk.rb from sync targets of prism --- tool/sync_default_gems.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/tool/sync_default_gems.rb b/tool/sync_default_gems.rb index 5794edaa83145a..029a27c8292b79 100755 --- a/tool/sync_default_gems.rb +++ b/tool/sync_default_gems.rb @@ -330,6 +330,7 @@ def sync_default_gems(gem) rm_rf("test/prism/snapshots") rm("prism/extconf.rb") + `git checkout prism/generate-srcs.mk.rb` when "resolv" rm_rf(%w[lib/resolv.* ext/win32/resolv test/resolv ext/win32/lib/win32/resolv.rb]) cp_r("#{upstream}/lib/resolv.rb", "lib")