From d77e6e653d32fa6287286cc68300abc0d1a299da Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Thu, 6 Oct 2022 15:43:48 +0900 Subject: [PATCH] Merge RubyGems-3.3.23 and Bundler-2.3.23 --- lib/bundler/cli/init.rb | 6 +- lib/bundler/definition.rb | 14 +- lib/bundler/dsl.rb | 1 - lib/bundler/gem_version_promoter.rb | 13 +- lib/bundler/index.rb | 29 +- lib/bundler/resolver.rb | 18 +- lib/bundler/rubygems_ext.rb | 13 +- lib/bundler/spec_set.rb | 2 +- lib/bundler/templates/newgem/gitlab-ci.yml.tt | 9 +- lib/bundler/version.rb | 2 +- lib/rubygems.rb | 2 +- lib/rubygems/gemcutter_utilities.rb | 9 +- lib/rubygems/package.rb | 13 +- lib/rubygems/platform.rb | 18 +- lib/rubygems/resolver.rb | 2 +- spec/bundler/commands/init_spec.rb | 23 + spec/bundler/spec_helper.rb | 2 + spec/bundler/support/path.rb | 4 + test/rubygems/helper.rb | 40 +- test/rubygems/packages/Bluebie-legs-0.6.2.gem | Bin 0 -> 14336 bytes test/rubygems/test_gem.rb | 502 ++++++++++-------- .../test_gem_commands_owner_command.rb | 129 ++++- .../test_gem_commands_push_command.rb | 67 ++- .../test_gem_commands_signin_command.rb | 31 +- .../test_gem_commands_yank_command.rb | 18 +- test/rubygems/test_gem_gemcutter_utilities.rb | 28 +- test/rubygems/test_gem_package.rb | 15 + test/rubygems/test_gem_platform.rb | 35 ++ test/rubygems/test_gem_resolver.rb | 33 ++ test/rubygems/test_require.rb | 10 +- test/rubygems/utilities.rb | 50 +- tool/bundler/dev_gems.rb.lock | 2 +- tool/bundler/rubocop_gems.rb.lock | 4 +- tool/bundler/standard_gems.rb.lock | 4 +- tool/bundler/test_gems.rb.lock | 2 +- 35 files changed, 736 insertions(+), 414 deletions(-) create mode 100644 test/rubygems/packages/Bluebie-legs-0.6.2.gem diff --git a/lib/bundler/cli/init.rb b/lib/bundler/cli/init.rb index e4f8229c48..bc96507c29 100644 --- a/lib/bundler/cli/init.rb +++ b/lib/bundler/cli/init.rb @@ -32,7 +32,11 @@ module Bundler file << spec.to_gemfile end else - FileUtils.cp(File.expand_path("../templates/#{gemfile}", __dir__), gemfile) + File.open(File.expand_path("../templates/#{gemfile}", __dir__), "r") do |template| + File.open(gemfile, "wb") do |destination| + IO.copy_stream(template, destination) + end + end end puts "Writing new #{gemfile} to #{SharedHelpers.pwd}/#{gemfile}" diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index 79369ec374..a46d7387de 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -106,6 +106,7 @@ module Bundler @locked_gems = nil @locked_deps = {} @locked_specs = SpecSet.new([]) + @originally_locked_specs = @locked_specs @locked_sources = [] @locked_platforms = [] end @@ -149,18 +150,7 @@ module Bundler end def gem_version_promoter - @gem_version_promoter ||= begin - locked_specs = - if unlocking? && @locked_specs.empty? && !@lockfile_contents.empty? - # Definition uses an empty set of locked_specs to indicate all gems - # are unlocked, but GemVersionPromoter needs the locked_specs - # for conservative comparison. - Bundler::SpecSet.new(@locked_gems.specs) - else - @locked_specs - end - GemVersionPromoter.new(locked_specs, @unlock[:gems]) - end + @gem_version_promoter ||= GemVersionPromoter.new(@originally_locked_specs, @unlock[:gems]) end def resolve_only_locally! diff --git a/lib/bundler/dsl.rb b/lib/bundler/dsl.rb index 385fdd4383..547db16190 100644 --- a/lib/bundler/dsl.rb +++ b/lib/bundler/dsl.rb @@ -67,7 +67,6 @@ module Bundler gemspecs = Gem::Util.glob_files_in_dir("{,*}.gemspec", expanded_path).map {|g| Bundler.load_gemspec(g) }.compact gemspecs.reject! {|s| s.name != name } if name - Index.sort_specs(gemspecs) specs_by_name_and_version = gemspecs.group_by {|s| [s.name, s.version] } case specs_by_name_and_version.size diff --git a/lib/bundler/gem_version_promoter.rb b/lib/bundler/gem_version_promoter.rb index 1ae41e2928..ee2c38a6ec 100644 --- a/lib/bundler/gem_version_promoter.rb +++ b/lib/bundler/gem_version_promoter.rb @@ -116,15 +116,14 @@ module Bundler end def sort_dep_specs(spec_groups, locked_spec) - return spec_groups unless locked_spec - @gem_name = locked_spec.name - @locked_version = locked_spec.version + @locked_version = locked_spec&.version + @gem_name = locked_spec&.name result = spec_groups.sort do |a, b| @a_ver = a.version @b_ver = b.version - unless @prerelease_specified[@gem_name] + unless @gem_name && @prerelease_specified[@gem_name] a_pre = @a_ver.prerelease? b_pre = @b_ver.prerelease? @@ -148,7 +147,7 @@ module Bundler end def either_version_older_than_locked - @a_ver < @locked_version || @b_ver < @locked_version + @locked_version && (@a_ver < @locked_version || @b_ver < @locked_version) end def segments_do_not_match(level) @@ -157,7 +156,7 @@ module Bundler end def unlocking_gem? - unlock_gems.empty? || unlock_gems.include?(@gem_name) + unlock_gems.empty? || (@gem_name && unlock_gems.include?(@gem_name)) end # Specific version moves can't always reliably be done during sorting @@ -165,7 +164,7 @@ module Bundler def post_sort(result) # default :major behavior in Bundler does not do this return result if major? - if unlocking_gem? + if unlocking_gem? || @locked_version.nil? result else move_version_to_end(result, @locked_version) diff --git a/lib/bundler/index.rb b/lib/bundler/index.rb index 00c7a9e00d..d3743adb68 100644 --- a/lib/bundler/index.rb +++ b/lib/bundler/index.rb @@ -57,36 +57,13 @@ module Bundler # Search this index's specs, and any source indexes that this index knows # about, returning all of the results. def search(query) - sort_specs(unsorted_search(query)) - end - - def unsorted_search(query) results = local_search(query) - - seen = results.map(&:full_name).uniq unless @sources.empty? + return results unless @sources.any? @sources.each do |source| - source.unsorted_search(query).each do |spec| - next if seen.include?(spec.full_name) - - seen << spec.full_name - results << spec - end + results.concat(source.search(query)) end - - results - end - protected :unsorted_search - - def self.sort_specs(specs) - specs.sort_by do |s| - platform_string = s.platform.to_s - [s.version, platform_string == RUBY ? NULL : platform_string] - end - end - - def sort_specs(specs) - self.class.sort_specs(specs) + results.uniq(&:full_name) end def local_search(query) diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb index fcb3812c5a..161a3c0518 100644 --- a/lib/bundler/resolver.rb +++ b/lib/bundler/resolver.rb @@ -42,8 +42,7 @@ module Bundler remove_from_candidates(spec) end - @gem_version_promoter.prerelease_specified = @prerelease_specified = {} - requirements.each {|dep| @prerelease_specified[dep.name] ||= dep.prerelease? } + requirements.each {|dep| prerelease_specified[dep.name] ||= dep.prerelease? } verify_gemfile_dependencies_are_found!(requirements) result = @resolver.resolve(requirements). @@ -127,13 +126,6 @@ module Bundler results = results_for(dependency) + locked_results results = results.select {|spec| requirement_satisfied_by?(locked_requirement, nil, spec) } if locked_requirement - if !@prerelease_specified[name] && locked_results.empty? - # Move prereleases to the beginning of the list, so they're considered - # last during resolution. - pre, results = results.partition {|spec| spec.version.prerelease? } - results = pre + results - end - if results.any? results = @gem_version_promoter.sort_versions(dependency, results) @@ -221,6 +213,10 @@ module Bundler @base.base_requirements end + def prerelease_specified + @gem_version_promoter.prerelease_specified + end + def remove_from_candidates(spec) @base.delete(spec) @@ -255,7 +251,7 @@ module Bundler all - 1_000_000 else search = search_for(dependency) - search = @prerelease_specified[dependency.name] ? search.count : search.count {|s| !s.version.prerelease? } + search = prerelease_specified[dependency.name] ? search.count : search.count {|s| !s.version.prerelease? } search - all end end @@ -284,7 +280,7 @@ module Bundler end def gem_not_found_message(name, requirement, source, extra_message = "") - specs = source.specs.search(name) + specs = source.specs.search(name).sort_by {|s| [s.version, s.platform.to_s] } matching_part = name requirement_label = SharedHelpers.pretty_dependency(requirement) cache_message = begin diff --git a/lib/bundler/rubygems_ext.rb b/lib/bundler/rubygems_ext.rb index 8b46d7ece4..d53d688009 100644 --- a/lib/bundler/rubygems_ext.rb +++ b/lib/bundler/rubygems_ext.rb @@ -261,10 +261,21 @@ module Gem # version ( (@os != "linux" && (@version.nil? || other.version.nil?)) || - (@os == "linux" && (other.version == "gnu#{@version}" || other.version == "musl#{@version}" || @version == "gnu#{other.version}")) || + (@os == "linux" && (normalized_linux_version_ext == other.normalized_linux_version_ext || ["musl#{@version}", "musleabi#{@version}", "musleabihf#{@version}"].include?(other.version))) || @version == other.version ) end + + # This is a copy of RubyGems 3.3.23 or higher `normalized_linux_method`. + # Once only 3.3.23 is supported, we can use the method in RubyGems. + def normalized_linux_version_ext + return nil unless @version + + without_gnu_nor_abi_modifiers = @version.sub(/\Agnu/, "").sub(/eabi(hf)?\Z/, "") + return nil if without_gnu_nor_abi_modifiers.empty? + + without_gnu_nor_abi_modifiers + end end end diff --git a/lib/bundler/spec_set.rb b/lib/bundler/spec_set.rb index 1d0b7a460d..21d57fdab4 100644 --- a/lib/bundler/spec_set.rb +++ b/lib/bundler/spec_set.rb @@ -176,7 +176,7 @@ module Bundler def lookup @lookup ||= begin lookup = Hash.new {|h, k| h[k] = [] } - Index.sort_specs(@specs).reverse_each do |s| + @specs.each do |s| lookup[s.name] << s end lookup diff --git a/lib/bundler/templates/newgem/gitlab-ci.yml.tt b/lib/bundler/templates/newgem/gitlab-ci.yml.tt index 0e71ff26a4..42e00392de 100644 --- a/lib/bundler/templates/newgem/gitlab-ci.yml.tt +++ b/lib/bundler/templates/newgem/gitlab-ci.yml.tt @@ -1,8 +1,9 @@ -image: ruby:<%= RUBY_VERSION %> +default: + image: ruby:<%= RUBY_VERSION %> -before_script: - - gem install bundler -v <%= Bundler::VERSION %> - - bundle install + before_script: + - gem install bundler -v <%= Bundler::VERSION %> + - bundle install example_job: script: diff --git a/lib/bundler/version.rb b/lib/bundler/version.rb index 75760528fe..22ce7daab9 100644 --- a/lib/bundler/version.rb +++ b/lib/bundler/version.rb @@ -1,7 +1,7 @@ # frozen_string_literal: false module Bundler - VERSION = "2.3.22".freeze + VERSION = "2.3.23".freeze def self.bundler_major_version @bundler_major_version ||= VERSION.split(".").first.to_i diff --git a/lib/rubygems.rb b/lib/rubygems.rb index d3a32b773f..e2e78a41ac 100644 --- a/lib/rubygems.rb +++ b/lib/rubygems.rb @@ -8,7 +8,7 @@ require "rbconfig" module Gem - VERSION = "3.3.22".freeze + VERSION = "3.3.23".freeze end # Must be first since it unloads the prelude from 1.9.2 diff --git a/lib/rubygems/gemcutter_utilities.rb b/lib/rubygems/gemcutter_utilities.rb index a785159196..3477422b79 100644 --- a/lib/rubygems/gemcutter_utilities.rb +++ b/lib/rubygems/gemcutter_utilities.rb @@ -201,7 +201,8 @@ module Gem::GemcutterUtilities # block was given or shows the response body to the user. # # If the response was not successful, shows an error to the user including - # the +error_prefix+ and the response body. + # the +error_prefix+ and the response body. If the response was a permanent redirect, + # shows an error to the user including the redirect location. def with_response(response, error_prefix = nil) case response @@ -211,6 +212,12 @@ module Gem::GemcutterUtilities else say clean_text(response.body) end + when Net::HTTPPermanentRedirect, Net::HTTPRedirection then + message = "The request has redirected permanently to #{response['location']}. Please check your defined push host URL." + message = "#{error_prefix}: #{message}" if error_prefix + + say clean_text(message) + terminate_interaction(ERROR_CODE) else message = response.body message = "#{error_prefix}: #{message}" if error_prefix diff --git a/lib/rubygems/package.rb b/lib/rubygems/package.rb index 084dc5d2d9..4672866985 100644 --- a/lib/rubygems/package.rb +++ b/lib/rubygems/package.rb @@ -444,10 +444,10 @@ EOM directories << mkdir end - File.open destination, "wb" do |out| - out.write entry.read + if entry.file? + File.open(destination, "wb") {|out| out.write entry.read } FileUtils.chmod file_mode(entry.header.mode), destination - end if entry.file? + end verbose destination end @@ -467,7 +467,12 @@ EOM end def file_mode(mode) # :nodoc: - ((mode & 0111).zero? ? data_mode : prog_mode) || mode + ((mode & 0111).zero? ? data_mode : prog_mode) || + # If we're not using one of the default modes, then we're going to fall + # back to the mode from the tarball. In this case we need to mask it down + # to fit into 2^16 bits (the maximum value for a mode in CRuby since it + # gets put into an unsigned short). + (mode & ((1 << 16) - 1)) end ## diff --git a/lib/rubygems/platform.rb b/lib/rubygems/platform.rb index 06de5ded8d..6f4ead1af8 100644 --- a/lib/rubygems/platform.rb +++ b/lib/rubygems/platform.rb @@ -22,6 +22,7 @@ class Gem::Platform end def self.match_platforms?(platform, platforms) + platform = Gem::Platform.new(platform) unless platform.is_a?(Gem::Platform) platforms.any? do |local_platform| platform.nil? || local_platform == platform || @@ -162,6 +163,9 @@ class Gem::Platform # runtime platform "no version" stands for 'gnu'. To be able to disinguish # these, the method receiver is the gem platform, while the argument is # the runtime platform. + # + #-- + # NOTE: Until it can be removed, changes to this method must also be reflected in `bundler/lib/bundler/rubygems_ext.rb` def ===(other) return nil unless Gem::Platform === other @@ -180,11 +184,23 @@ class Gem::Platform # version ( (@os != "linux" && (@version.nil? || other.version.nil?)) || - (@os == "linux" && (other.version == "gnu#{@version}" || other.version == "musl#{@version}" || @version == "gnu#{other.version}")) || + (@os == "linux" && (normalized_linux_version == other.normalized_linux_version || ["musl#{@version}", "musleabi#{@version}", "musleabihf#{@version}"].include?(other.version))) || @version == other.version ) end + #-- + # NOTE: Until it can be removed, changes to this method must also be reflected in `bundler/lib/bundler/rubygems_ext.rb` + + def normalized_linux_version + return nil unless @version + + without_gnu_nor_abi_modifiers = @version.sub(/\Agnu/, "").sub(/eabi(hf)?\Z/, "") + return nil if without_gnu_nor_abi_modifiers.empty? + + without_gnu_nor_abi_modifiers + end + ## # Does +other+ match this platform? If +other+ is a String it will be # converted to a Gem::Platform first. See #=== for matching rules. diff --git a/lib/rubygems/resolver.rb b/lib/rubygems/resolver.rb index bf7d6d943b..76d1e9d0cc 100644 --- a/lib/rubygems/resolver.rb +++ b/lib/rubygems/resolver.rb @@ -246,7 +246,7 @@ class Gem::Resolver sources.each do |source| groups[source]. - sort_by {|spec| [spec.version, Gem::Platform.local =~ spec.platform ? 1 : 0] }. + sort_by {|spec| [spec.version, spec.platform =~ Gem::Platform.local ? 1 : 0] }. map {|spec| ActivationRequest.new spec, dependency }. each {|activation_request| activation_requests << activation_request } end diff --git a/spec/bundler/commands/init_spec.rb b/spec/bundler/commands/init_spec.rb index eaf8fa170a..9c499b99a1 100644 --- a/spec/bundler/commands/init_spec.rb +++ b/spec/bundler/commands/init_spec.rb @@ -7,6 +7,29 @@ RSpec.describe "bundle init" do expect(bundled_app_gemfile).to be_file end + context "with a template with permission flags not matching current process umask" do + let(:template_file) do + gemfile = Bundler.preferred_gemfile_name + templates_dir.join(gemfile) + end + + let(:target_dir) { bundled_app("init_permissions_test") } + + around do |example| + old_chmod = File.stat(template_file).mode + FileUtils.chmod(old_chmod | 0o111, template_file) # chmod +x + example.run + FileUtils.chmod(old_chmod, template_file) + end + + it "honours the current process umask when generating from a template" do + FileUtils.mkdir(target_dir) + bundle :init, :dir => target_dir + generated_mode = File.stat(File.join(target_dir, "Gemfile")).mode & 0o111 + expect(generated_mode).to be_zero + end + end + context "when a Gemfile already exists" do before do create_file "Gemfile", <<-G diff --git a/spec/bundler/spec_helper.rb b/spec/bundler/spec_helper.rb index 892ad10e98..d606220dc4 100644 --- a/spec/bundler/spec_helper.rb +++ b/spec/bundler/spec_helper.rb @@ -60,6 +60,8 @@ RSpec.configure do |config| config.expect_with :rspec do |c| c.syntax = :expect + + c.max_formatted_output_length = 1000 end config.mock_with :rspec do |mocks| diff --git a/spec/bundler/support/path.rb b/spec/bundler/support/path.rb index a39e46c78a..7443e78d52 100644 --- a/spec/bundler/support/path.rb +++ b/spec/bundler/support/path.rb @@ -312,6 +312,10 @@ module Spec source_root.join("tool/bundler") end + def templates_dir + lib_dir.join("bundler", "templates") + end + extend self end end diff --git a/test/rubygems/helper.rb b/test/rubygems/helper.rb index 970ba09c10..1ed1523f73 100644 --- a/test/rubygems/helper.rb +++ b/test/rubygems/helper.rb @@ -2,26 +2,11 @@ require "rubygems" -# If bundler gemspec exists, add to stubs -bundler_gemspec = File.expand_path("../../bundler/bundler.gemspec", __dir__) -if File.exist?(bundler_gemspec) - Gem::Specification.dirs.unshift File.dirname(bundler_gemspec) - Gem::Specification.class_variable_set :@@stubs, nil - Gem::Specification.stubs - Gem::Specification.dirs.shift -end - begin gem "test-unit", "~> 3.0" rescue Gem::LoadError end -if File.exist?(bundler_gemspec) - require_relative "../../bundler/lib/bundler" -else - require "bundler" -end - require "test/unit" ENV["JARS_SKIP"] = "true" if Gem.java_platform? # avoid unnecessary and noisy `jar-dependencies` post install hook @@ -409,7 +394,6 @@ class Gem::TestCase < Test::Unit::TestCase Gem.loaded_specs.clear Gem.instance_variable_set(:@activated_gem_paths, 0) Gem.clear_default_specs - Bundler.reset! Gem.configuration.verbose = true Gem.configuration.update_sources = true @@ -465,7 +449,7 @@ class Gem::TestCase < Test::Unit::TestCase FileUtils.rm_rf @tempdir - ENV.replace(@orig_env) + restore_env Gem::ConfigFile.send :remove_const, :SYSTEM_WIDE_CONFIG_FILE Gem::ConfigFile.send :const_set, :SYSTEM_WIDE_CONFIG_FILE, @@ -575,6 +559,7 @@ class Gem::TestCase < Test::Unit::TestCase Dir.chdir directory do unless File.exist? ".git" system @git, "init", "--quiet" + system @git, "checkout", "-b", "master", "--quiet" system @git, "config", "user.name", "RubyGems Tests" system @git, "config", "user.email", "rubygems@example" end @@ -1301,6 +1286,10 @@ Also, a list: $LOAD_PATH.find {|p| p == File.dirname($LOADED_FEATURES.find {|f| f.end_with?("/rubygems.rb") }) } end + def bundler_path + $LOAD_PATH.find {|p| p == File.dirname($LOADED_FEATURES.find {|f| f.end_with?("/bundler.rb") }) } + end + def with_clean_path_to_ruby orig_ruby = Gem.ruby @@ -1581,6 +1570,23 @@ Also, a list: PUBLIC_KEY = nil PUBLIC_CERT = nil end if Gem::HAVE_OPENSSL + + private + + def restore_env + unless Gem.win_platform? + ENV.replace(@orig_env) + return + end + + # Fallback logic for Windows below to workaround + # https://bugs.ruby-lang.org/issues/16798. Can be dropped once all + # supported rubies include the fix for that. + + ENV.clear + + @orig_env.each {|k, v| ENV[k] = v } + end end # https://github.com/seattlerb/minitest/blob/13c48a03d84a2a87855a4de0c959f96800100357/lib/minitest/mock.rb#L192 diff --git a/test/rubygems/packages/Bluebie-legs-0.6.2.gem b/test/rubygems/packages/Bluebie-legs-0.6.2.gem new file mode 100644 index 0000000000000000000000000000000000000000..60918f3bc53abc47d783d04e26a33bdba0d51bfe GIT binary patch literal 14336 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 literal 0 HcmV?d00001 diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index bbb3e6dd0a..1b8527cce9 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -617,20 +617,22 @@ class TestGem < Gem::TestCase end def test_self_use_gemdeps - with_rubygems_gemdeps("-") do - FileUtils.mkdir_p "detect/a/b" - FileUtils.mkdir_p "detect/a/Isolate" + with_local_bundler_at(Gem.dir) do + with_rubygems_gemdeps("-") do + FileUtils.mkdir_p "detect/a/b" + FileUtils.mkdir_p "detect/a/Isolate" - FileUtils.touch "detect/Isolate" + FileUtils.touch "detect/Isolate" - begin - Dir.chdir "detect/a/b" + begin + Dir.chdir "detect/a/b" - Gem.use_gemdeps + Gem.use_gemdeps - assert_equal add_bundler_full_name([]), loaded_spec_names - ensure - Dir.chdir @tempdir + assert_equal add_bundler_full_name([]), loaded_spec_names + ensure + Dir.chdir @tempdir + end end end end @@ -775,39 +777,40 @@ class TestGem < Gem::TestCase end def test_self_find_files_with_gemfile - cwd = File.expand_path("test/rubygems", PROJECT_DIR) - actual_load_path = $LOAD_PATH.unshift(cwd).dup + with_local_bundler_at(Gem.dir) do + cwd = File.expand_path("test/rubygems", PROJECT_DIR) + actual_load_path = $LOAD_PATH.unshift(cwd).dup - discover_path = File.join "lib", "sff", "discover.rb" + discover_path = File.join "lib", "sff", "discover.rb" - foo1, _ = %w[1 2].map do |version| - spec = quick_gem "sff", version do |s| - s.files << discover_path + foo1, _ = %w[1 2].map do |version| + spec = quick_gem "sff", version do |s| + s.files << discover_path + end + + write_file(File.join "gems", spec.full_name, discover_path) do |fp| + fp.puts "# #{spec.full_name}" + end + + spec end + Gem.refresh - write_file(File.join "gems", spec.full_name, discover_path) do |fp| - fp.puts "# #{spec.full_name}" + write_file(File.join Dir.pwd, "Gemfile") do |fp| + fp.puts "source 'https://rubygems.org'" + fp.puts "gem '#{foo1.name}', '#{foo1.version}'" end + Gem.use_gemdeps(File.join Dir.pwd, "Gemfile") - spec + expected = [ + File.expand_path("test/rubygems/sff/discover.rb", PROJECT_DIR), + File.join(foo1.full_gem_path, discover_path), + ].sort + + assert_equal expected, Gem.find_files("sff/discover").sort + assert_equal expected, Gem.find_files("sff/**.rb").sort, "[ruby-core:31730]" + assert_equal cwd, actual_load_path.shift end - Gem.refresh - - write_file(File.join Dir.pwd, "Gemfile") do |fp| - fp.puts "source 'https://rubygems.org'" - fp.puts "gem '#{foo1.name}', '#{foo1.version}'" - end - Gem.use_gemdeps(File.join Dir.pwd, "Gemfile") - - expected = [ - File.expand_path("test/rubygems/sff/discover.rb", PROJECT_DIR), - File.join(foo1.full_gem_path, discover_path), - ].sort - - assert_equal expected, Gem.find_files("sff/discover").sort - assert_equal expected, Gem.find_files("sff/**.rb").sort, "[ruby-core:31730]" - ensure - assert_equal cwd, actual_load_path.shift unless Gem.java_platform? end def test_self_find_latest_files @@ -1335,12 +1338,10 @@ class TestGem < Gem::TestCase refute Gem.try_activate "nonexistent" end - unless Gem.java_platform? - expected = "Ignoring ext-1 because its extensions are not built. " + - "Try: gem pristine ext --version 1\n" + expected = "Ignoring ext-1 because its extensions are not built. " + + "Try: gem pristine ext --version 1\n" - assert_equal expected, err - end + assert_equal expected, err end def test_self_use_paths_with_nils @@ -1640,159 +1641,164 @@ class TestGem < Gem::TestCase end def test_auto_activation_of_specific_gemdeps_file - a = util_spec "a", "1", nil, "lib/a.rb" - b = util_spec "b", "1", nil, "lib/b.rb" - c = util_spec "c", "1", nil, "lib/c.rb" + with_local_bundler_at(Gem.dir) do + a = util_spec "a", "1", nil, "lib/a.rb" + b = util_spec "b", "1", nil, "lib/b.rb" + c = util_spec "c", "1", nil, "lib/c.rb" - install_specs a, b, c + install_specs a, b, c - path = File.join @tempdir, "gem.deps.rb" + path = File.join @tempdir, "gem.deps.rb" - File.open path, "w" do |f| - f.puts "gem 'a'" - f.puts "gem 'b'" - f.puts "gem 'c'" - end + File.open path, "w" do |f| + f.puts "gem 'a'" + f.puts "gem 'b'" + f.puts "gem 'c'" + end - with_rubygems_gemdeps(path) do - Gem.use_gemdeps + with_rubygems_gemdeps(path) do + Gem.use_gemdeps - assert_equal add_bundler_full_name(%W[a-1 b-1 c-1]), loaded_spec_names + assert_equal add_bundler_full_name(%W[a-1 b-1 c-1]), loaded_spec_names + end end end def test_auto_activation_of_used_gemdeps_file - a = util_spec "a", "1", nil, "lib/a.rb" - b = util_spec "b", "1", nil, "lib/b.rb" - c = util_spec "c", "1", nil, "lib/c.rb" + with_local_bundler_at(Gem.dir) do + a = util_spec "a", "1", nil, "lib/a.rb" + b = util_spec "b", "1", nil, "lib/b.rb" + c = util_spec "c", "1", nil, "lib/c.rb" - install_specs a, b, c + install_specs a, b, c - path = File.join @tempdir, "gem.deps.rb" + path = File.join @tempdir, "gem.deps.rb" - File.open path, "w" do |f| - f.puts "gem 'a'" - f.puts "gem 'b'" - f.puts "gem 'c'" - end + File.open path, "w" do |f| + f.puts "gem 'a'" + f.puts "gem 'b'" + f.puts "gem 'c'" + end - with_rubygems_gemdeps("-") do - expected_specs = [a, b, util_spec("bundler", Bundler::VERSION), c].compact.map(&:full_name) + with_rubygems_gemdeps("-") do + expected_specs = [a, b, util_spec("bundler", Bundler::VERSION), c].compact.map(&:full_name) - Gem.use_gemdeps + Gem.use_gemdeps - assert_equal expected_specs, loaded_spec_names + assert_equal expected_specs, loaded_spec_names + end end end - BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) } - BUNDLER_FULL_NAME = "bundler-#{Bundler::VERSION}".freeze - def add_bundler_full_name(names) - names << BUNDLER_FULL_NAME + names << "bundler-#{Bundler::VERSION}".freeze names.sort! names end def test_looks_for_gemdeps_files_automatically_from_binstubs - pend "Requiring bundler messes things up" if Gem.java_platform? - - a = util_spec "a", "1" do |s| - s.executables = %w[foo] - s.bindir = "exe" - end - - write_file File.join(@tempdir, "exe", "foo") do |fp| - fp.puts "puts Gem.loaded_specs.values.map(&:full_name).sort" - end - - b = util_spec "b", "1", nil, "lib/b.rb" - c = util_spec "c", "1", nil, "lib/c.rb" - - install_specs a, b, c - path = File.join(@tempdir, "gd-tmp") - install_gem a, :install_dir => path - install_gem b, :install_dir => path - install_gem c, :install_dir => path - ENV["GEM_PATH"] = path - - with_rubygems_gemdeps("-") do - new_PATH = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR) - new_RUBYOPT = "-I#{rubygems_path} -I#{BUNDLER_LIB_PATH}" - - path = File.join @tempdir, "gem.deps.rb" - - File.open path, "w" do |f| - f.puts "gem 'a'" - end - out0 = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do - IO.popen("foo", &:read).split(/\n/) + with_local_bundler_at(path) do + a = util_spec "a", "1" do |s| + s.executables = %w[foo] + s.bindir = "exe" end - File.open path, "a" do |f| - f.puts "gem 'b'" - f.puts "gem 'c'" - end - out = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do - IO.popen("foo", &:read).split(/\n/) + write_file File.join(@tempdir, "exe", "foo") do |fp| + fp.puts "puts Gem.loaded_specs.values.map(&:full_name).sort" end - assert_equal ["b-1", "c-1"], out - out0 + b = util_spec "b", "1", nil, "lib/b.rb" + c = util_spec "c", "1", nil, "lib/c.rb" + + install_specs a, b, c + + install_gem a, :install_dir => path + install_gem b, :install_dir => path + install_gem c, :install_dir => path + + ENV["GEM_PATH"] = path + + with_rubygems_gemdeps("-") do + new_PATH = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR) + new_RUBYOPT = "-I#{rubygems_path} -I#{bundler_path}" + + path = File.join @tempdir, "gem.deps.rb" + + File.open path, "w" do |f| + f.puts "gem 'a'" + end + out0 = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do + IO.popen("foo", &:read).split(/\n/) + end + + File.open path, "a" do |f| + f.puts "gem 'b'" + f.puts "gem 'c'" + end + out = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do + IO.popen("foo", &:read).split(/\n/) + end + + assert_equal ["b-1", "c-1"], out - out0 + end end end def test_looks_for_gemdeps_files_automatically_from_binstubs_in_parent_dir - pend "Requiring bundler messes things up" if Gem.java_platform? - - a = util_spec "a", "1" do |s| - s.executables = %w[foo] - s.bindir = "exe" - end - - write_file File.join(@tempdir, "exe", "foo") do |fp| - fp.puts "puts Gem.loaded_specs.values.map(&:full_name).sort" - end - - b = util_spec "b", "1", nil, "lib/b.rb" - c = util_spec "c", "1", nil, "lib/c.rb" - - install_specs a, b, c - path = File.join(@tempdir, "gd-tmp") - install_gem a, :install_dir => path - install_gem b, :install_dir => path - install_gem c, :install_dir => path - ENV["GEM_PATH"] = path + with_local_bundler_at(path) do + pend "IO.popen has issues on JRuby when passed :chdir" if Gem.java_platform? - with_rubygems_gemdeps("-") do - Dir.mkdir "sub1" - - new_PATH = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR) - new_RUBYOPT = "-I#{rubygems_path} -I#{BUNDLER_LIB_PATH}" - - path = File.join @tempdir, "gem.deps.rb" - - File.open path, "w" do |f| - f.puts "gem 'a'" - end - out0 = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do - IO.popen("foo", :chdir => "sub1", &:read).split(/\n/) + a = util_spec "a", "1" do |s| + s.executables = %w[foo] + s.bindir = "exe" end - File.open path, "a" do |f| - f.puts "gem 'b'" - f.puts "gem 'c'" - end - out = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do - IO.popen("foo", :chdir => "sub1", &:read).split(/\n/) + write_file File.join(@tempdir, "exe", "foo") do |fp| + fp.puts "puts Gem.loaded_specs.values.map(&:full_name).sort" end - Dir.rmdir "sub1" + b = util_spec "b", "1", nil, "lib/b.rb" + c = util_spec "c", "1", nil, "lib/c.rb" - assert_equal ["b-1", "c-1"], out - out0 + install_specs a, b, c + + install_gem a, :install_dir => path + install_gem b, :install_dir => path + install_gem c, :install_dir => path + + ENV["GEM_PATH"] = path + + with_rubygems_gemdeps("-") do + Dir.mkdir "sub1" + + new_PATH = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR) + new_RUBYOPT = "-I#{rubygems_path} -I#{bundler_path}" + + path = File.join @tempdir, "gem.deps.rb" + + File.open path, "w" do |f| + f.puts "gem 'a'" + end + out0 = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do + IO.popen("foo", :chdir => "sub1", &:read).split(/\n/) + end + + File.open path, "a" do |f| + f.puts "gem 'b'" + f.puts "gem 'c'" + end + out = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do + IO.popen("foo", :chdir => "sub1", &:read).split(/\n/) + end + + Dir.rmdir "sub1" + + assert_equal ["b-1", "c-1"], out - out0 + end end end @@ -1837,52 +1843,47 @@ class TestGem < Gem::TestCase end def test_use_gemdeps - gem_deps_file = "gem.deps.rb".tap(&Gem::UNTAINT) - spec = util_spec "a", 1 - install_specs spec - - spec = Gem::Specification.find {|s| s == spec } - refute spec.activated? - - File.open gem_deps_file, "w" do |io| - io.write 'gem "a"' - end - - assert_nil Gem.gemdeps - - Gem.use_gemdeps gem_deps_file - - assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names - refute_nil Gem.gemdeps - end - - def test_use_gemdeps_ENV - with_rubygems_gemdeps(nil) do + with_local_bundler_at(Gem.dir) do + gem_deps_file = "gem.deps.rb".tap(&Gem::UNTAINT) spec = util_spec "a", 1 + install_specs spec + spec = Gem::Specification.find {|s| s == spec } refute spec.activated? - File.open "gem.deps.rb", "w" do |io| + File.open gem_deps_file, "w" do |io| io.write 'gem "a"' end - Gem.use_gemdeps + assert_nil Gem.gemdeps - refute spec.activated? + Gem.use_gemdeps gem_deps_file + + assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names + refute_nil Gem.gemdeps + end + end + + def test_use_gemdeps_ENV + with_local_bundler_at(Gem.dir) do + with_rubygems_gemdeps(nil) do + spec = util_spec "a", 1 + + refute spec.activated? + + File.open "gem.deps.rb", "w" do |io| + io.write 'gem "a"' + end + + Gem.use_gemdeps + + refute spec.activated? + end end end def test_use_gemdeps_argument_missing - e = assert_raise ArgumentError do - Gem.use_gemdeps "gem.deps.rb" - end - - assert_equal "Unable to find gem dependencies file at gem.deps.rb", - e.message - end - - def test_use_gemdeps_argument_missing_match_ENV - with_rubygems_gemdeps("gem.deps.rb") do + with_local_bundler_at(Gem.dir) do e = assert_raise ArgumentError do Gem.use_gemdeps "gem.deps.rb" end @@ -1892,85 +1893,108 @@ class TestGem < Gem::TestCase end end - def test_use_gemdeps_automatic - with_rubygems_gemdeps("-") do - spec = util_spec "a", 1 - install_specs spec - spec = Gem::Specification.find {|s| s == spec } + def test_use_gemdeps_argument_missing_match_ENV + with_local_bundler_at(Gem.dir) do + with_rubygems_gemdeps("gem.deps.rb") do + e = assert_raise ArgumentError do + Gem.use_gemdeps "gem.deps.rb" + end - refute spec.activated? - - File.open "Gemfile", "w" do |io| - io.write 'gem "a"' + assert_equal "Unable to find gem dependencies file at gem.deps.rb", + e.message end + end + end - Gem.use_gemdeps + def test_use_gemdeps_automatic + with_local_bundler_at(Gem.dir) do + with_rubygems_gemdeps("-") do + spec = util_spec "a", 1 + install_specs spec + spec = Gem::Specification.find {|s| s == spec } - assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names + refute spec.activated? + + File.open "Gemfile", "w" do |io| + io.write 'gem "a"' + end + + Gem.use_gemdeps + + assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names + end end end def test_use_gemdeps_automatic_missing - with_rubygems_gemdeps("-") do - Gem.use_gemdeps + with_local_bundler_at(Gem.dir) do + with_rubygems_gemdeps("-") do + Gem.use_gemdeps - assert true # count + assert true # count + end end end def test_use_gemdeps_disabled - with_rubygems_gemdeps("") do - spec = util_spec "a", 1 + with_local_bundler_at(Gem.dir) do + with_rubygems_gemdeps("") do + spec = util_spec "a", 1 - refute spec.activated? + refute spec.activated? - File.open "gem.deps.rb", "w" do |io| - io.write 'gem "a"' + File.open "gem.deps.rb", "w" do |io| + io.write 'gem "a"' + end + + Gem.use_gemdeps + + refute spec.activated? end - - Gem.use_gemdeps - - refute spec.activated? end end def test_use_gemdeps_missing_gem - with_rubygems_gemdeps("x") do - File.open "x", "w" do |io| - io.write 'gem "a"' - end + with_local_bundler_at(Gem.dir) do + with_rubygems_gemdeps("x") do + File.open "x", "w" do |io| + io.write 'gem "a"' + end - expected = <<-EXPECTED + expected = <<-EXPECTED Could not find gem 'a' in locally installed gems. You may need to `bundle install` to install missing gems EXPECTED - Gem::Deprecate.skip_during do - actual_stdout, actual_stderr = capture_output do - Gem.use_gemdeps + Gem::Deprecate.skip_during do + actual_stdout, actual_stderr = capture_output do + Gem.use_gemdeps + end + assert_empty actual_stdout + assert_equal(expected, actual_stderr) end - assert_empty actual_stdout - assert_equal(expected, actual_stderr) end end end def test_use_gemdeps_specific - with_rubygems_gemdeps("x") do - spec = util_spec "a", 1 - install_specs spec + with_local_bundler_at(Gem.dir) do + with_rubygems_gemdeps("x") do + spec = util_spec "a", 1 + install_specs spec - spec = Gem::Specification.find {|s| s == spec } - refute spec.activated? + spec = Gem::Specification.find {|s| s == spec } + refute spec.activated? - File.open "x", "w" do |io| - io.write 'gem "a"' + File.open "x", "w" do |io| + io.write 'gem "a"' + end + + Gem.use_gemdeps + + assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names end - - Gem.use_gemdeps - - assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names end end @@ -2109,4 +2133,22 @@ You may need to `bundle install` to install missing gems ensure ENV["RUBYGEMS_GEMDEPS"] = rubygems_gemdeps end + + def with_local_bundler_at(path) + require "bundler" + + # If bundler gemspec exists, pretend it's installed + bundler_gemspec = File.expand_path("../../bundler/bundler.gemspec", __dir__) + if File.exist?(bundler_gemspec) + target_gemspec_location = "#{path}/specifications/bundler-#{Bundler::VERSION}.gemspec" + + FileUtils.mkdir_p File.dirname(target_gemspec_location) + + File.write target_gemspec_location, Gem::Specification.load(bundler_gemspec).to_ruby_for_cache + end + + yield + ensure + Bundler.reset! + end end diff --git a/test/rubygems/test_gem_commands_owner_command.rb b/test/rubygems/test_gem_commands_owner_command.rb index ca77041000..32bfbb7a66 100644 --- a/test/rubygems/test_gem_commands_owner_command.rb +++ b/test/rubygems/test_gem_commands_owner_command.rb @@ -36,7 +36,7 @@ class TestGemCommandsOwnerCommand < Gem::TestCase - id: 4 EOF - @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, "OK"] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK") use_ui @stub_ui do @cmd.show_owners("freewill") @@ -66,7 +66,7 @@ EOF - id: 4 EOF - @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, "OK"] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK") assert_raise Psych::DisallowedClass do use_ui @ui do @@ -80,7 +80,7 @@ EOF host = "http://rubygems.example" ENV["RUBYGEMS_HOST"] = host - @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, "OK"] + @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK") use_ui @stub_ui do @cmd.show_owners("freewill") @@ -95,7 +95,7 @@ EOF host = "http://rubygems.example" @cmd.host = host - @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, "OK"] + @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK") use_ui @stub_ui do @cmd.show_owners("freewill") @@ -107,7 +107,7 @@ EOF def test_show_owners_denied response = "You don't have permission to push to this gem" - @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 403, "Forbidden"] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = HTTPResponseFactory.create(body: response, code: 403, msg: "Forbidden") assert_raise Gem::MockGemUi::TermError do use_ui @stub_ui do @@ -118,9 +118,32 @@ EOF assert_match response, @stub_ui.output end + def test_show_owners_permanent_redirect + host = "http://rubygems.example" + ENV["RUBYGEMS_HOST"] = host + path = "/api/v1/gems/freewill/owners.yaml" + redirected_uri = "https://rubygems.example#{path}" + + @stub_fetcher.data["#{host}#{path}"] = HTTPResponseFactory.create( + body: "", + code: "301", + msg: "Moved Permanently", + headers: { "location" => redirected_uri } + ) + + assert_raise Gem::MockGemUi::TermError do + use_ui @stub_ui do + @cmd.show_owners("freewill") + end + end + + response = "The request has redirected permanently to #{redirected_uri}. Please check your defined push host URL." + assert_match response, @stub_ui.output + end + def test_show_owners_key response = "- email: user1@example.com\n" - @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, "OK"] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK") File.open Gem.configuration.credentials_path, "a" do |f| f.write ":other: 701229f217cdf23b1344c7b4b54ca97" end @@ -134,7 +157,7 @@ EOF def test_add_owners response = "Owner added successfully." - @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 200, "OK"] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK") use_ui @stub_ui do @cmd.add_owners("freewill", ["user-new1@example.com"]) @@ -149,7 +172,7 @@ EOF def test_add_owners_denied response = "You don't have permission to push to this gem" - @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 403, "Forbidden"] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 403, msg: "Forbidden") use_ui @stub_ui do @cmd.add_owners("freewill", ["user-new1@example.com"]) @@ -158,12 +181,33 @@ EOF assert_match response, @stub_ui.output end + def test_add_owners_permanent_redirect + host = "http://rubygems.example" + ENV["RUBYGEMS_HOST"] = host + path = "/api/v1/gems/freewill/owners" + redirected_uri = "https://rubygems.example#{path}" + + @stub_fetcher.data["#{host}#{path}"] = HTTPResponseFactory.create( + body: "", + code: "308", + msg: "Permanent Redirect", + headers: { "location" => redirected_uri } + ) + + use_ui @stub_ui do + @cmd.add_owners("freewill", ["user-new1@example.com"]) + end + + response = "The request has redirected permanently to #{redirected_uri}. Please check your defined push host URL." + assert_match response, @stub_ui.output + end + def test_add_owner_with_host_option_through_execute host = "http://rubygems.example" add_owner_response = "Owner added successfully." show_owners_response = "- email: user1@example.com\n" - @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners"] = [add_owner_response, 200, "OK"] - @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = [show_owners_response, 200, "OK"] + @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: add_owner_response, code: 200, msg: "OK") + @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = HTTPResponseFactory.create(body: show_owners_response, code: 200, msg: "OK") @cmd.handle_options %W[--host #{host} --add user-new1@example.com freewill] @@ -178,7 +222,7 @@ EOF def test_add_owners_key response = "Owner added successfully." - @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 200, "OK"] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK") File.open Gem.configuration.credentials_path, "a" do |f| f.write ":other: 701229f217cdf23b1344c7b4b54ca97" end @@ -192,7 +236,7 @@ EOF def test_remove_owners response = "Owner removed successfully." - @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 200, "OK"] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK") use_ui @stub_ui do @cmd.remove_owners("freewill", ["user-remove1@example.com"]) @@ -207,7 +251,7 @@ EOF def test_remove_owners_denied response = "You don't have permission to push to this gem" - @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 403, "Forbidden"] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 403, msg: "Forbidden") use_ui @stub_ui do @cmd.remove_owners("freewill", ["user-remove1@example.com"]) @@ -216,9 +260,46 @@ EOF assert_match response, @stub_ui.output end + def test_remove_owners_permanent_redirect + host = "http://rubygems.example" + ENV["RUBYGEMS_HOST"] = host + path = "/api/v1/gems/freewill/owners" + redirected_uri = "https://rubygems.example#{path}" + @stub_fetcher.data["#{host}#{path}"] = HTTPResponseFactory.create( + body: "", + code: "308", + msg: "Permanent Redirect", + headers: { "location" => redirected_uri } + ) + + use_ui @stub_ui do + @cmd.remove_owners("freewill", ["user-remove1@example.com"]) + end + + response = "The request has redirected permanently to #{redirected_uri}. Please check your defined push host URL." + assert_match response, @stub_ui.output + + path = "/api/v1/gems/freewill/owners" + redirected_uri = "https://rubygems.example#{path}" + + @stub_fetcher.data["#{host}#{path}"] = HTTPResponseFactory.create( + body: "", + code: "308", + msg: "Permanent Redirect", + headers: { "location" => redirected_uri } + ) + + use_ui @stub_ui do + @cmd.add_owners("freewill", ["user-new1@example.com"]) + end + + response = "The request has redirected permanently to #{redirected_uri}. Please check your defined push host URL." + assert_match response, @stub_ui.output + end + def test_remove_owners_key response = "Owner removed successfully." - @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 200, "OK"] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK") File.open Gem.configuration.credentials_path, "a" do |f| f.write ":other: 701229f217cdf23b1344c7b4b54ca97" end @@ -232,7 +313,7 @@ EOF def test_remove_owners_missing response = "Owner could not be found." - @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 404, "Not Found"] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 404, msg: "Not Found") use_ui @stub_ui do @cmd.remove_owners("freewill", ["missing@example"]) @@ -246,8 +327,8 @@ EOF response_success = "Owner added successfully." @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [ - [response_fail, 401, "Unauthorized"], - [response_success, 200, "OK"], + HTTPResponseFactory.create(body: response_fail, code: 401, msg: "Unauthorized"), + HTTPResponseFactory.create(body: response_success, code: 200, msg: "OK"), ] @otp_ui = Gem::MockGemUi.new "111111\n" @@ -263,7 +344,7 @@ EOF def test_otp_verified_failure response = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." - @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 401, "Unauthorized"] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 401, msg: "Unauthorized") @otp_ui = Gem::MockGemUi.new "111111\n" use_ui @otp_ui do @@ -281,10 +362,10 @@ EOF response_success = "Owner removed successfully." @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [ - [response_forbidden, 403, "Forbidden"], - [response_success, 200, "OK"], + HTTPResponseFactory.create(body: response_forbidden, code: 403, msg: "Forbidden"), + HTTPResponseFactory.create(body: response_success, code: 200, msg: "OK"), ] - @stub_fetcher.data["#{Gem.host}/api/v1/api_key"] = ["", 200, "OK"] + @stub_fetcher.data["#{Gem.host}/api/v1/api_key"] = HTTPResponseFactory.create(body: "", code: 200, msg: "OK") @cmd.instance_variable_set :@scope, :remove_owner @stub_ui = Gem::MockGemUi.new "some@mail.com\npass\n" @@ -305,10 +386,10 @@ EOF response_success = "Owner added successfully." @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [ - [response_forbidden, 403, "Forbidden"], - [response_success, 200, "OK"], + HTTPResponseFactory.create(body: response_forbidden, code: 403, msg: "Forbidden"), + HTTPResponseFactory.create(body: response_success, code: 200, msg: "OK"), ] - @stub_fetcher.data["#{Gem.host}/api/v1/api_key"] = ["", 200, "OK"] + @stub_fetcher.data["#{Gem.host}/api/v1/api_key"] = HTTPResponseFactory.create(body: "", code: 200, msg: "OK") @cmd.instance_variable_set :@scope, :add_owner @stub_ui = Gem::MockGemUi.new "some@mail.com\npass\n" diff --git a/test/rubygems/test_gem_commands_push_command.rb b/test/rubygems/test_gem_commands_push_command.rb index f38a2ae7a1..ef7730558d 100644 --- a/test/rubygems/test_gem_commands_push_command.rb +++ b/test/rubygems/test_gem_commands_push_command.rb @@ -68,7 +68,7 @@ class TestGemCommandsPushCommand < Gem::TestCase def test_execute @response = "Successfully registered gem: freewill (1.0.0)" - @fetcher.data["#{Gem.host}/api/v1/gems"] = [@response, 200, "OK"] + @fetcher.data["#{Gem.host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK") @cmd.options[:args] = [@path] @@ -84,7 +84,7 @@ class TestGemCommandsPushCommand < Gem::TestCase host = "https://other.example" @response = "Successfully registered gem: freewill (1.0.0)" - @fetcher.data["#{host}/api/v1/gems"] = [@response, 200, "OK"] + @fetcher.data["#{host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK") @fetcher.data["#{Gem.host}/api/v1/gems"] = ["fail", 500, "Internal Server Error"] @@ -105,7 +105,7 @@ class TestGemCommandsPushCommand < Gem::TestCase end @response = "Successfully registered gem: freewill (1.0.0)" - @fetcher.data["#{@spec.metadata['allowed_push_host']}/api/v1/gems"] = [@response, 200, "OK"] + @fetcher.data["#{@spec.metadata['allowed_push_host']}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK") @fetcher.data["#{Gem.host}/api/v1/gems"] = ["fail", 500, "Internal Server Error"] @@ -136,7 +136,7 @@ class TestGemCommandsPushCommand < Gem::TestCase ENV["RUBYGEMS_HOST"] = @host Gem.configuration.disable_default_gem_server = true @response = "Successfully registered gem: freewill (1.0.0)" - @fetcher.data["#{@host}/api/v1/gems"] = [@response, 200, "OK"] + @fetcher.data["#{@host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK") send_battery end @@ -163,14 +163,14 @@ class TestGemCommandsPushCommand < Gem::TestCase FileUtils.rm Gem.configuration.credentials_path @response = "Successfully registered gem: freebird (1.0.1)" - @fetcher.data["#{@host}/api/v1/gems"] = [@response, 200, "OK"] + @fetcher.data["#{@host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK") send_battery end def test_sending_gem @response = "Successfully registered gem: freewill (1.0.0)" - @fetcher.data["#{@host}/api/v1/gems"] = [@response, 200, "OK"] + @fetcher.data["#{@host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK") send_battery end @@ -197,7 +197,7 @@ class TestGemCommandsPushCommand < Gem::TestCase FileUtils.rm Gem.configuration.credentials_path @response = "Successfully registered gem: freebird (1.0.1)" - @fetcher.data["#{@host}/api/v1/gems"] = [@response, 200, "OK"] + @fetcher.data["#{@host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK") send_battery end @@ -212,7 +212,7 @@ class TestGemCommandsPushCommand < Gem::TestCase ENV["GEM_HOST_API_KEY"] = "PRIVKEY" @response = "Successfully registered gem: freebird (1.0.1)" - @fetcher.data["#{@host}/api/v1/gems"] = [@response, 200, "OK"] + @fetcher.data["#{@host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK") send_battery end @@ -238,7 +238,7 @@ class TestGemCommandsPushCommand < Gem::TestCase FileUtils.rm Gem.configuration.credentials_path @response = "Successfully registered gem: freebird (1.0.1)" - @fetcher.data["#{@host}/api/v1/gems"] = [@response, 200, "OK"] + @fetcher.data["#{@host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK") send_battery end @@ -309,7 +309,7 @@ class TestGemCommandsPushCommand < Gem::TestCase FileUtils.rm Gem.configuration.credentials_path @response = "Successfully registered gem: freebird (1.0.1)" - @fetcher.data["#{host}/api/v1/gems"] = [@response, 200, "OK"] + @fetcher.data["#{host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK") # do not set @host use_ui(@ui) { @cmd.send_gem(@path) } @@ -325,6 +325,27 @@ class TestGemCommandsPushCommand < Gem::TestCase assert_match @response, @ui.output end + def test_sending_gem_to_host_permanent_redirect + @host = "http://rubygems.example" + redirected_uri = "https://rubygems.example/api/v1/gems" + @fetcher.data["#{@host}/api/v1/gems"] = HTTPResponseFactory.create( + body: "", + code: 308, + msg: "Permanent Redirect", + headers: { "Location" => redirected_uri } + ) + + assert_raise Gem::MockGemUi::TermError do + use_ui @ui do + @cmd.instance_variable_set :@host, @host + @cmd.send_gem(@path) + end + end + + response = "The request has redirected permanently to #{redirected_uri}. Please check your defined push host URL." + assert_match response, @ui.output + end + def test_raises_error_with_no_arguments def @cmd.sign_in(*); end assert_raise Gem::CommandLineError do @@ -334,7 +355,7 @@ class TestGemCommandsPushCommand < Gem::TestCase def test_sending_gem_denied response = "You don't have permission to push to this gem" - @fetcher.data["#{@host}/api/v1/gems"] = [response, 403, "Forbidden"] + @fetcher.data["#{@host}/api/v1/gems"] = HTTPResponseFactory.create(body: response, code: 403, msg: "Forbidden") @cmd.instance_variable_set :@host, @host assert_raise Gem::MockGemUi::TermError do @@ -348,7 +369,7 @@ class TestGemCommandsPushCommand < Gem::TestCase def test_sending_gem_key @response = "Successfully registered gem: freewill (1.0.0)" - @fetcher.data["#{@host}/api/v1/gems"] = [@response, 200, "OK"] + @fetcher.data["#{@host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK") File.open Gem.configuration.credentials_path, "a" do |f| f.write ":other: 701229f217cdf23b1344c7b4b54ca97" end @@ -367,8 +388,8 @@ class TestGemCommandsPushCommand < Gem::TestCase response_success = "Successfully registered gem: freewill (1.0.0)" @fetcher.data["#{Gem.host}/api/v1/gems"] = [ - [response_fail, 401, "Unauthorized"], - [response_success, 200, "OK"], + HTTPResponseFactory.create(body: response_fail, code: 401, msg: "Unauthorized"), + HTTPResponseFactory.create(body: response_success, code: 200, msg: "OK"), ] @otp_ui = Gem::MockGemUi.new "111111\n" @@ -384,7 +405,7 @@ class TestGemCommandsPushCommand < Gem::TestCase def test_otp_verified_failure response = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." - @fetcher.data["#{Gem.host}/api/v1/gems"] = [response, 401, "Unauthorized"] + @fetcher.data["#{Gem.host}/api/v1/gems"] = HTTPResponseFactory.create(body: response, code: 401, msg: "Unauthorized") @otp_ui = Gem::MockGemUi.new "111111\n" assert_raise Gem::MockGemUi::TermError do @@ -405,12 +426,12 @@ class TestGemCommandsPushCommand < Gem::TestCase response_success = "Successfully registered gem: freewill (1.0.0)" @fetcher.data["#{@host}/api/v1/gems"] = [ - [response_mfa_enabled, 401, "Unauthorized"], - [response_forbidden, 403, "Forbidden"], - [response_success, 200, "OK"], + HTTPResponseFactory.create(body: response_mfa_enabled, code: 401, msg: "Unauthorized"), + HTTPResponseFactory.create(body: response_forbidden, code: 403, msg: "Forbidden"), + HTTPResponseFactory.create(body: response_success, code: 200, msg: "OK"), ] - @fetcher.data["#{@host}/api/v1/api_key"] = ["", 200, "OK"] + @fetcher.data["#{@host}/api/v1/api_key"] = HTTPResponseFactory.create(body: "", code: 200, msg: "OK") @cmd.instance_variable_set :@host, @host @cmd.instance_variable_set :@scope, :push_rubygem @@ -438,16 +459,16 @@ class TestGemCommandsPushCommand < Gem::TestCase response_profile = "mfa: disabled\n" @fetcher.data["#{@host}/api/v1/gems"] = [ - [response_success, 200, "OK"], + HTTPResponseFactory.create(body: response_success, code: 200, msg: "OK"), ] @fetcher.data["#{@host}/api/v1/api_key"] = [ - [response_mfa_enabled, 401, "Unauthorized"], - ["", 200, "OK"], + HTTPResponseFactory.create(body: response_mfa_enabled, code: 401, msg: "Unauthorized"), + HTTPResponseFactory.create(body: "", code: 200, msg: "OK"), ] @fetcher.data["#{@host}/api/v1/profile/me.yaml"] = [ - [response_profile, 200, "OK"], + HTTPResponseFactory.create(body: response_profile, code: 200, msg: "OK"), ] @cmd.instance_variable_set :@scope, :push_rubygem diff --git a/test/rubygems/test_gem_commands_signin_command.rb b/test/rubygems/test_gem_commands_signin_command.rb index ce745bff20..281e4f9eac 100644 --- a/test/rubygems/test_gem_commands_signin_command.rb +++ b/test/rubygems/test_gem_commands_signin_command.rb @@ -71,6 +71,31 @@ class TestGemCommandsSigninCommand < Gem::TestCase assert_equal api_key, credentials[host] end + def test_execute_with_host_permanent_redirect + host = "http://rubygems.example/" + ENV["RUBYGEMS_HOST"] = host + path = "/api/v1/api_key" + redirected_uri = "http://rubygems.example#{path}" + fetcher = Gem::FakeFetcher.new + fetcher.data["#{host}#{path}"] = HTTPResponseFactory.create( + body: "", + code: "308", + msg: "Permanent Redirect", + headers: { "location" => redirected_uri } + ) + Gem::RemoteFetcher.fetcher = fetcher + ui = Gem::MockGemUi.new("you@example.com\nsecret\n\n\n\n\n\n\n\n\n") + + assert_raise Gem::MockGemUi::TermError do + use_ui ui do + @cmd.execute + end + end + + response = "The request has redirected permanently to #{redirected_uri}. Please check your defined push host URL." + assert_match response, ui.output + end + def test_execute_with_valid_creds_set_for_default_host util_capture { @cmd.execute } @@ -186,7 +211,7 @@ class TestGemCommandsSigninCommand < Gem::TestCase # Set the expected response for the Web-API supplied ENV["RUBYGEMS_HOST"] = host data_key = "#{ENV['RUBYGEMS_HOST']}/api/v1/api_key" - fetcher.data[data_key] = [api_key, 200, "OK"] + fetcher.data[data_key] = HTTPResponseFactory.create(body: api_key, code: 200, msg: "OK") use_ui key_name_ui do @cmd.execute @@ -209,8 +234,8 @@ class TestGemCommandsSigninCommand < Gem::TestCase def util_capture(ui_stub = nil, host = nil, api_key = nil, fetcher = Gem::FakeFetcher.new, mfa_level = "disabled", warning = nil) api_key ||= "a5fdbb6ba150cbb83aad2bb2fede64cf040453903" - response = [api_key, 200, "OK"] - profile_response = [ "mfa: #{mfa_level}\nwarning: #{warning}" , 200, "OK"] + response = HTTPResponseFactory.create(body: api_key, code: 200, msg: "OK") + profile_response = HTTPResponseFactory.create(body: "mfa: #{mfa_level}\nwarning: #{warning}", code: 200, msg: "OK") email = "you@example.com" password = "secret" diff --git a/test/rubygems/test_gem_commands_yank_command.rb b/test/rubygems/test_gem_commands_yank_command.rb index 878b52416e..d14395a75e 100644 --- a/test/rubygems/test_gem_commands_yank_command.rb +++ b/test/rubygems/test_gem_commands_yank_command.rb @@ -43,7 +43,7 @@ class TestGemCommandsYankCommand < Gem::TestCase def test_execute yank_uri = "http://example/api/v1/gems/yank" - @fetcher.data[yank_uri] = ["Successfully yanked", 200, "OK"] + @fetcher.data[yank_uri] = HTTPResponseFactory.create(body: "Successfully yanked", code: 200, msg: "OK") @cmd.options[:args] = %w[a] @cmd.options[:added_platform] = true @@ -69,8 +69,8 @@ class TestGemCommandsYankCommand < Gem::TestCase response_fail = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." yank_uri = "http://example/api/v1/gems/yank" @fetcher.data[yank_uri] = [ - [response_fail, 401, "Unauthorized"], - ["Successfully yanked", 200, "OK"], + HTTPResponseFactory.create(body: response_fail, code: 401, msg: "Unauthorized"), + HTTPResponseFactory.create(body: "Successfully yanked", code: 200, msg: "OK"), ] @cmd.options[:args] = %w[a] @@ -92,7 +92,7 @@ class TestGemCommandsYankCommand < Gem::TestCase def test_execute_with_otp_failure response = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." yank_uri = "http://example/api/v1/gems/yank" - @fetcher.data[yank_uri] = [response, 401, "Unauthorized"] + @fetcher.data[yank_uri] = HTTPResponseFactory.create(body: response, code: 401, msg: "Unauthorized") @cmd.options[:args] = %w[a] @cmd.options[:added_platform] = true @@ -111,7 +111,7 @@ class TestGemCommandsYankCommand < Gem::TestCase def test_execute_key yank_uri = "http://example/api/v1/gems/yank" - @fetcher.data[yank_uri] = ["Successfully yanked", 200, "OK"] + @fetcher.data[yank_uri] = HTTPResponseFactory.create(body: "Successfully yanked", code: 200, msg: "OK") @cmd.options[:args] = %w[a] @cmd.options[:version] = req("= 1.0") @@ -129,7 +129,7 @@ class TestGemCommandsYankCommand < Gem::TestCase def test_execute_host host = "https://other.example" yank_uri = "#{host}/api/v1/gems/yank" - @fetcher.data[yank_uri] = ["Successfully yanked", 200, "OK"] + @fetcher.data[yank_uri] = HTTPResponseFactory.create(body: "Successfully yanked", code: 200, msg: "OK") @cmd.options[:args] = %w[a] @cmd.options[:version] = req("= 1.0") @@ -154,11 +154,11 @@ class TestGemCommandsYankCommand < Gem::TestCase host = "http://example" @fetcher.data["#{host}/api/v1/gems/yank"] = [ - [response_forbidden, 403, "Forbidden"], - [response_success, 200, "OK"], + HTTPResponseFactory.create(body: response_forbidden, code: 403, msg: "Forbidden"), + HTTPResponseFactory.create(body: response_success, code: 200, msg: "OK"), ] - @fetcher.data["#{host}/api/v1/api_key"] = ["", 200, "OK"] + @fetcher.data["#{host}/api/v1/api_key"] = HTTPResponseFactory.create(body: "", code: 200, msg: "OK") @cmd.options[:args] = %w[a] @cmd.options[:added_platform] = true @cmd.options[:version] = req("= 1.0") diff --git a/test/rubygems/test_gem_gemcutter_utilities.rb b/test/rubygems/test_gem_gemcutter_utilities.rb index 2ca5b402d9..5e59733d5a 100644 --- a/test/rubygems/test_gem_gemcutter_utilities.rb +++ b/test/rubygems/test_gem_gemcutter_utilities.rb @@ -93,7 +93,7 @@ class TestGemGemcutterUtilities < Gem::TestCase def test_sign_in api_key = "a5fdbb6ba150cbb83aad2bb2fede64cf040453903" - util_sign_in [api_key, 200, "OK"] + util_sign_in HTTPResponseFactory.create(body: api_key, code: 200, msg: "OK") assert_match %r{Enter your RubyGems.org credentials.}, @sign_in_ui.output assert @fetcher.last_request["authorization"] @@ -106,7 +106,7 @@ class TestGemGemcutterUtilities < Gem::TestCase def test_sign_in_with_host api_key = "a5fdbb6ba150cbb83aad2bb2fede64cf040453903" - util_sign_in [api_key, 200, "OK"], "http://example.com", ["http://example.com"] + util_sign_in HTTPResponseFactory.create(body: api_key, code: 200, msg: "OK"), "http://example.com", ["http://example.com"] assert_match "Enter your http://example.com credentials.", @sign_in_ui.output @@ -120,7 +120,7 @@ class TestGemGemcutterUtilities < Gem::TestCase def test_sign_in_with_host_nil api_key = "a5fdbb6ba150cbb83aad2bb2fede64cf040453903" - util_sign_in [api_key, 200, "OK"], nil, [nil] + util_sign_in HTTPResponseFactory.create(body: api_key, code: 200, msg: "OK"), nil, [nil] assert_match "Enter your RubyGems.org credentials.", @sign_in_ui.output @@ -133,7 +133,7 @@ class TestGemGemcutterUtilities < Gem::TestCase def test_sign_in_with_host_ENV api_key = "a5fdbb6ba150cbb83aad2bb2fede64cf040453903" - util_sign_in [api_key, 200, "OK"], "http://example.com" + util_sign_in HTTPResponseFactory.create(body: api_key, code: 200, msg: "OK"), "http://example.com" assert_match "Enter your http://example.com credentials.", @sign_in_ui.output @@ -148,7 +148,7 @@ class TestGemGemcutterUtilities < Gem::TestCase api_key = "a5fdbb6ba150cbb83aad2bb2fede64cf040453903" Gem.configuration.rubygems_api_key = api_key - util_sign_in [api_key, 200, "OK"] + util_sign_in HTTPResponseFactory.create(body: api_key, code: 200, msg: "OK") assert_equal "", @sign_in_ui.output end @@ -157,7 +157,7 @@ class TestGemGemcutterUtilities < Gem::TestCase api_key = "a5fdbb6ba150cbb83aad2bb2fede64cf040453903" Gem.configuration.api_keys[:KEY] = "other" @cmd.options[:key] = :KEY - util_sign_in [api_key, 200, "OK"] + util_sign_in HTTPResponseFactory.create(body: api_key, code: 200, msg: "OK") assert_equal "", @sign_in_ui.output end @@ -169,7 +169,7 @@ class TestGemGemcutterUtilities < Gem::TestCase File.open Gem.configuration.credentials_path, "w" do |f| f.write Hash[:other_api_key, other_api_key].to_yaml end - util_sign_in [api_key, 200, "OK"] + util_sign_in HTTPResponseFactory.create(body: api_key, code: 200, msg: "OK") assert_match %r{Enter your RubyGems.org credentials.}, @sign_in_ui.output assert_match %r{Signed in.}, @sign_in_ui.output @@ -181,7 +181,7 @@ class TestGemGemcutterUtilities < Gem::TestCase def test_sign_in_with_bad_credentials assert_raise Gem::MockGemUi::TermError do - util_sign_in ["Access Denied.", 403, "Forbidden"] + util_sign_in HTTPResponseFactory.create(body: "Access Denied.", code: 403, msg: "Forbidden") end assert_match %r{Enter your RubyGems.org credentials.}, @sign_in_ui.output @@ -192,7 +192,7 @@ class TestGemGemcutterUtilities < Gem::TestCase ENV["GEM_HOST_OTP_CODE"] = "111111" api_key = "a5fdbb6ba150cbb83aad2bb2fede64cf040453903" - util_sign_in [api_key, 200, "OK"] + util_sign_in HTTPResponseFactory.create(body: api_key, code: 200, msg: "OK") assert_match "Signed in with API key:", @sign_in_ui.output assert_equal "111111", @fetcher.last_request["OTP"] @@ -204,7 +204,11 @@ class TestGemGemcutterUtilities < Gem::TestCase util_sign_in(proc do @call_count ||= 0 - (@call_count += 1).odd? ? [response_fail, 401, "Unauthorized"] : [api_key, 200, "OK"] + if (@call_count += 1).odd? + HTTPResponseFactory.create(body: response_fail, code: 401, msg: "Unauthorized") + else + HTTPResponseFactory.create(body: api_key, code: 200, msg: "OK") + end end, nil, [], "111111\n") assert_match "You have enabled multi-factor authentication. Please enter OTP code.", @sign_in_ui.output @@ -217,7 +221,7 @@ class TestGemGemcutterUtilities < Gem::TestCase response = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." assert_raise Gem::MockGemUi::TermError do - util_sign_in [response, 401, "Unauthorized"], nil, [], "111111\n" + util_sign_in HTTPResponseFactory.create(body: response, code: 401, msg: "Unauthorized"), nil, [], "111111\n" end assert_match "You have enabled multi-factor authentication. Please enter OTP code.", @sign_in_ui.output @@ -229,7 +233,7 @@ class TestGemGemcutterUtilities < Gem::TestCase def util_sign_in(response, host = nil, args = [], extra_input = "") email = "you@example.com" password = "secret" - profile_response = [ "mfa: disabled\n" , 200, "OK"] + profile_response = HTTPResponseFactory.create(body: "mfa: disabled\n", code: 200, msg: "OK") if host ENV["RUBYGEMS_HOST"] = host diff --git a/test/rubygems/test_gem_package.rb b/test/rubygems/test_gem_package.rb index 9295f42dba..eebe4d86d0 100644 --- a/test/rubygems/test_gem_package.rb +++ b/test/rubygems/test_gem_package.rb @@ -510,6 +510,21 @@ class TestGemPackage < Gem::Package::TarTestCase assert_path_exist @destination end + def test_extract_file_permissions + pend "chmod not supported" if win_platform? + + gem_with_long_permissions = File.expand_path("packages/Bluebie-legs-0.6.2.gem", __dir__) + + package = Gem::Package.new gem_with_long_permissions + + package.extract_files @destination + + filepath = File.join @destination, "README.rdoc" + assert_path_exist filepath + + assert_equal 0104444, File.stat(filepath).mode + end + def test_extract_tar_gz_absolute package = Gem::Package.new @gem diff --git a/test/rubygems/test_gem_platform.rb b/test/rubygems/test_gem_platform.rb index 576f150219..61547d8972 100644 --- a/test/rubygems/test_gem_platform.rb +++ b/test/rubygems/test_gem_platform.rb @@ -333,6 +333,34 @@ class TestGemPlatform < Gem::TestCase refute(arm_linux_uclibceabi === arm_linux_eabi, "linux-uclibceabi =~ linux-eabi") end + def test_eabi_and_nil_version_combination_strictness + arm_linux = Gem::Platform.new "arm-linux" + arm_linux_eabi = Gem::Platform.new "arm-linux-eabi" + arm_linux_eabihf = Gem::Platform.new "arm-linux-eabihf" + arm_linux_gnueabi = Gem::Platform.new "arm-linux-gnueabi" + arm_linux_gnueabihf = Gem::Platform.new "arm-linux-gnueabihf" + arm_linux_musleabi = Gem::Platform.new "arm-linux-musleabi" + arm_linux_musleabihf = Gem::Platform.new "arm-linux-musleabihf" + arm_linux_uclibceabi = Gem::Platform.new "arm-linux-uclibceabi" + arm_linux_uclibceabihf = Gem::Platform.new "arm-linux-uclibceabihf" + + # generic arm host runtime with eabi modifier accepts generic arm gems + assert(arm_linux === arm_linux_eabi, "arm-linux =~ arm-linux-eabi") + assert(arm_linux === arm_linux_eabihf, "arm-linux =~ arm-linux-eabihf") + + # explicit gnu arm host runtime with eabi modifier accepts generic arm gems + assert(arm_linux === arm_linux_gnueabi, "arm-linux =~ arm-linux-gnueabi") + assert(arm_linux === arm_linux_gnueabihf, "arm-linux =~ arm-linux-gnueabihf") + + # musl arm host runtime accepts libc-generic or statically linked gems... + assert(arm_linux === arm_linux_musleabi, "arm-linux =~ arm-linux-musleabi") + assert(arm_linux === arm_linux_musleabihf, "arm-linux =~ arm-linux-musleabihf") + + # other libc arm hosts are not glibc compatible + refute(arm_linux === arm_linux_uclibceabi, "arm-linux =~ arm-linux-uclibceabi") + refute(arm_linux === arm_linux_uclibceabihf, "arm-linux =~ arm-linux-uclibceabihf") + end + def test_equals3_cpu_arm arm = Gem::Platform.new "arm-linux" armv5 = Gem::Platform.new "armv5-linux" @@ -452,6 +480,13 @@ class TestGemPlatform < Gem::TestCase assert_equal 1, result.scan(/@version=/).size end + def test_gem_platform_match_with_string_argument + util_set_arch "x86_64-linux-musl" + + assert(Gem::Platform.match(Gem::Platform.new("x86_64-linux")), "should match Gem::Platform") + assert(Gem::Platform.match("x86_64-linux"), "should match String platform") + end + def assert_local_match(name) assert_match Gem::Platform.local, name end diff --git a/test/rubygems/test_gem_resolver.rb b/test/rubygems/test_gem_resolver.rb index c816d5484b..54497c6e4f 100644 --- a/test/rubygems/test_gem_resolver.rb +++ b/test/rubygems/test_gem_resolver.rb @@ -391,6 +391,39 @@ class TestGemResolver < Gem::TestCase end end + def test_pick_generic_linux_variants_on_musl_linux + util_set_arch "aarch64-linux-musl" do + is = Gem::Resolver::IndexSpecification + + linux = Gem::Platform.new("aarch64-linux") + + spec_fetcher do |fetcher| + fetcher.spec "libv8-node", "15.14.0.1" do |s| + s.platform = linux + end + + fetcher.spec "libv8-node", "15.14.0.1" + end + + v15 = v("15.14.0.1") + source = Gem::Source.new @gem_repo + + s = set + + v15_ruby = is.new s, "libv8-node", v15, source, Gem::Platform::RUBY + v15_linux = is.new s, "libv8-node", v15, source, linux.to_s + + s.add v15_linux + s.add v15_ruby + + ad = make_dep "libv8-node", "= 15.14.0.1" + + res = Gem::Resolver.new([ad], s) + + assert_resolves_to [v15_linux.spec], res + end + end + def test_only_returns_spec_once a1 = util_spec "a", "1", "c" => "= 1" b1 = util_spec "b", "1", "c" => "= 1" diff --git a/test/rubygems/test_require.rb b/test/rubygems/test_require.rb index 6135acea92..222bdcfb28 100644 --- a/test/rubygems/test_require.rb +++ b/test/rubygems/test_require.rb @@ -252,9 +252,9 @@ class TestGemRequire < Gem::TestCase # Activates a-1, but not b-1 and b-2 assert_require "test_gem_require_a" assert_equal %w[a-1], loaded_spec_names - assert $LOAD_PATH.include? a1.load_paths[0] - refute $LOAD_PATH.include? b1.load_paths[0] - refute $LOAD_PATH.include? b2.load_paths[0] + assert $LOAD_PATH.include? a1.full_require_paths[0] + refute $LOAD_PATH.include? b1.full_require_paths[0] + refute $LOAD_PATH.include? b2.full_require_paths[0] assert_equal unresolved_names, ["b (>= 1)"] @@ -265,13 +265,13 @@ class TestGemRequire < Gem::TestCase # and as a result #gem_original_require returns false. refute require("benchmark"), "the benchmark stdlib should be recognized as already loaded" - assert_includes $LOAD_PATH, b2.load_paths[0] + assert_includes $LOAD_PATH, b2.full_require_paths[0] assert_includes $LOAD_PATH, rubylibdir message = proc { "this test relies on the b-2 gem lib/ to be before stdlib to make sense\n" + $LOAD_PATH.pretty_inspect } - assert_operator $LOAD_PATH.index(b2.load_paths[0]), :<, $LOAD_PATH.index(rubylibdir), message + assert_operator $LOAD_PATH.index(b2.full_require_paths[0]), :<, $LOAD_PATH.index(rubylibdir), message # We detected that we should activate b-2, so we did so, but # then #gem_original_require decided "I've already got some benchmark.rb" loaded. diff --git a/test/rubygems/utilities.rb b/test/rubygems/utilities.rb index c01f7acd48..8b9fa98e3d 100644 --- a/test/rubygems/utilities.rb +++ b/test/rubygems/utilities.rb @@ -54,13 +54,21 @@ class Gem::FakeFetcher raise Gem::RemoteFetcher::FetchError.new("no data for #{path}", path) end - if @data[path].kind_of?(Array) && @data[path].first.kind_of?(Array) + if @data[path].kind_of?(Array) @data[path].shift else @data[path] end end + def create_response(uri) + data = find_data(uri) + response = data.respond_to?(:call) ? data.call : data + raise TypeError, "#{response.class} is not a type of Net::HTTPResponse" unless response.kind_of?(Net::HTTPResponse) + + response + end + def fetch_path(path, mtime = nil, head = false) data = find_data(path) @@ -85,26 +93,16 @@ class Gem::FakeFetcher # Thanks, FakeWeb! def open_uri_or_path(path) - data = find_data(path) - body, code, msg = data + find_data(path) - response = Net::HTTPResponse.send(:response_class, code.to_s).new("1.0", code.to_s, msg) - response.instance_variable_set(:@body, body) - response.instance_variable_set(:@read, true) - response + create_response(uri) end def request(uri, request_class, last_modified = nil) - data = find_data(uri) - body, code, msg = (data.respond_to?(:call) ? data.call : data) - @last_request = request_class.new uri.request_uri yield @last_request if block_given? - response = Net::HTTPResponse.send(:response_class, code.to_s).new("1.0", code.to_s, msg) - response.instance_variable_set(:@body, body) - response.instance_variable_set(:@read, true) - response + create_response(uri) end def pretty_print(q) # :nodoc: @@ -164,6 +162,30 @@ class Gem::FakeFetcher end end +## +# The HTTPResponseFactory allows easy creation of Net::HTTPResponse instances in RubyGems tests: +# +# Example: +# +# HTTPResponseFactory.create( +# body: "", +# code: 301, +# msg: "Moved Permanently", +# headers: { "location" => "http://example.com" } +# ) +# + +class HTTPResponseFactory + def self.create(body:, code:, msg:, headers: {}) + response = Net::HTTPResponse.send(:response_class, code.to_s).new("1.0", code.to_s, msg) + response.instance_variable_set(:@body, body) + response.instance_variable_set(:@read, true) + headers.each {|name, value| response[name] = value } + + response + end +end + # :stopdoc: class Gem::RemoteFetcher def self.fetcher=(fetcher) diff --git a/tool/bundler/dev_gems.rb.lock b/tool/bundler/dev_gems.rb.lock index 03dceb8816..5fac17bcfd 100644 --- a/tool/bundler/dev_gems.rb.lock +++ b/tool/bundler/dev_gems.rb.lock @@ -53,4 +53,4 @@ DEPENDENCIES webrick (~> 1.6) BUNDLED WITH - 2.3.22 + 2.3.23 diff --git a/tool/bundler/rubocop_gems.rb.lock b/tool/bundler/rubocop_gems.rb.lock index 3325a5a18b..b64bbf0e60 100644 --- a/tool/bundler/rubocop_gems.rb.lock +++ b/tool/bundler/rubocop_gems.rb.lock @@ -47,11 +47,13 @@ PLATFORMS aarch64-linux arm64-darwin-20 arm64-darwin-21 + arm64-darwin-22 universal-java-11 universal-java-18 x64-mingw-ucrt x86_64-darwin-19 x86_64-darwin-20 + x86_64-darwin-21 x86_64-linux DEPENDENCIES @@ -63,4 +65,4 @@ DEPENDENCIES test-unit BUNDLED WITH - 2.3.22 + 2.3.23 diff --git a/tool/bundler/standard_gems.rb.lock b/tool/bundler/standard_gems.rb.lock index 0fb3ada1f0..0c9bfcfa2d 100644 --- a/tool/bundler/standard_gems.rb.lock +++ b/tool/bundler/standard_gems.rb.lock @@ -53,11 +53,13 @@ PLATFORMS aarch64-linux arm64-darwin-20 arm64-darwin-21 + arm64-darwin-22 universal-java-11 universal-java-18 x64-mingw-ucrt x86_64-darwin-19 x86_64-darwin-20 + x86_64-darwin-21 x86_64-linux DEPENDENCIES @@ -69,4 +71,4 @@ DEPENDENCIES test-unit BUNDLED WITH - 2.3.22 + 2.3.23 diff --git a/tool/bundler/test_gems.rb.lock b/tool/bundler/test_gems.rb.lock index a0a4529dff..0fdf9240b4 100644 --- a/tool/bundler/test_gems.rb.lock +++ b/tool/bundler/test_gems.rb.lock @@ -43,4 +43,4 @@ DEPENDENCIES webrick (= 1.7.0) BUNDLED WITH - 2.3.22 + 2.3.23