ruby-changes:43367
From: hsbt <ko1@a...>
Date: Sat, 18 Jun 2016 14:12:00 +0900 (JST)
Subject: [ruby-changes:43367] hsbt:r55441 (trunk): * lib/rubygems.rb, lib/rubygems/*, test/rubygems/*: Update rubygems
hsbt 2016-06-18 14:11:55 +0900 (Sat, 18 Jun 2016) New Revision: 55441 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=55441 Log: * lib/rubygems.rb, lib/rubygems/*, test/rubygems/*: Update rubygems HEAD(2c6d256). It contains to update vendored Molinillo to 0.5.0. https://github.com/rubygems/rubygems/pull/1638 Added directories: trunk/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/ trunk/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/ Added files: trunk/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/resolution_state.rb trunk/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/specification_provider.rb trunk/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action.rb trunk/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb trunk/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_vertex.rb trunk/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb trunk/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/log.rb trunk/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/set_payload.rb trunk/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/tag.rb trunk/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex.rb trunk/lib/rubygems/ssl_certs/index.rubygems.org/GlobalSignRootCA.pem trunk/lib/rubygems/ssl_certs/rubygems.org/AddTrustExternalCARoot.pem Removed files: trunk/lib/rubygems/ssl_certs/index.rubygems.org/GlobalSignRoot.pem trunk/lib/rubygems/ssl_certs/rubygems.org/AddTrustExternalCARoot-2048.pem Modified files: trunk/ChangeLog trunk/lib/rubygems/installer.rb trunk/lib/rubygems/package/tar_writer.rb trunk/lib/rubygems/package.rb trunk/lib/rubygems/remote_fetcher.rb trunk/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb trunk/lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb trunk/lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb trunk/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb trunk/lib/rubygems/resolver/molinillo/lib/molinillo/state.rb trunk/lib/rubygems/security/signer.rb trunk/lib/rubygems/specification.rb trunk/lib/rubygems.rb trunk/test/rubygems/test_bundled_ca.rb trunk/test/rubygems/test_gem_installer.rb trunk/test/rubygems/test_gem_package.rb trunk/test/rubygems/test_gem_package_tar_writer.rb trunk/test/rubygems/test_gem_remote_fetcher.rb trunk/test/rubygems/test_gem_security_signer.rb Index: test/rubygems/test_gem_remote_fetcher.rb =================================================================== --- test/rubygems/test_gem_remote_fetcher.rb (revision 55440) +++ test/rubygems/test_gem_remote_fetcher.rb (revision 55441) @@ -81,6 +81,7 @@ gems: https://github.com/ruby/ruby/blob/trunk/test/rubygems/test_gem_remote_fetcher.rb#L81 # Generated via: # x = OpenSSL::PKey::DH.new(2048) # wait a while... # x.to_s => pem + # x.priv_key.to_s => hex for OpenSSL::BN.new TEST_KEY_DH2048 = OpenSSL::PKey::DH.new <<-_end_of_pem_ -----BEGIN DH PARAMETERS----- MIIBCAKCAQEA3Ze2EHSfYkZLUn557torAmjBgPsqzbodaRaGZtgK1gEU+9nNJaFV @@ -92,6 +93,17 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== https://github.com/ruby/ruby/blob/trunk/test/rubygems/test_gem_remote_fetcher.rb#L93 -----END DH PARAMETERS----- _end_of_pem_ + TEST_KEY_DH2048.priv_key = OpenSSL::BN.new("108911488509734781344423639" \ + "5585749502236089033416160524030987005037540379474123441273555416835" \ + "4725688238369352738266590757370603937618499698665047757588998555345" \ + "3446251978586372525530219375408331096098220027413238477359960428372" \ + "0195464393332338164504352015535549496585792320286513563739305843396" \ + "9294344974028713065472959376197728193162272314514335882399554394661" \ + "5306385003430991221886779612878793446851681835397455333989268503748" \ + "7862488679178398716189205737442996155432191656080664090596502674943" \ + "7902481557157485795980326766117882761941455140582265347052939604724" \ + "964857770053363840471912215799994973597613931991572884", 16) + def setup @proxies = %w[https_proxy http_proxy HTTP_PROXY http_proxy_user HTTP_PROXY_USER http_proxy_pass HTTP_PROXY_PASS no_proxy NO_PROXY] @old_proxies = @proxies.map {|k| ENV[k] } Index: test/rubygems/test_gem_package_tar_writer.rb =================================================================== --- test/rubygems/test_gem_package_tar_writer.rb (revision 55440) +++ test/rubygems/test_gem_package_tar_writer.rb (revision 55441) @@ -229,6 +229,22 @@ class TestGemPackageTarWriter < Gem::Pac https://github.com/ruby/ruby/blob/trunk/test/rubygems/test_gem_package_tar_writer.rb#L229 assert_equal ["#{'qwer/' * 19}bla", 'a' * 151], @tar_writer.split_name("#{'a' * 151}/#{'qwer/' * 19}bla") + names = [ + ([''] + ['123456789'] * 9 + ['1234567890']).join('/'), # 101 bytes (several pieces) + (['123456789'] * 9 + ['1234567890'] + ['']).join('/'), # 101 bytes (several pieces) + '/' * 99, + '/' * 100, + '/' * 101, + '/' * 102, + ] + names.each do |name| + newname, prefix = @tar_writer.split_name(name) + assert(!(newname.empty?), "split_name() returned empty name") + assert(newname.bytesize <= 100, "split_name() returned name longer than 100 bytes: '#{newname}' for '#{name}'") + assert(prefix.bytesize <= 155, "split_name() returned prefix longer than 155 bytes: '#{prefix}' for '#{name}'") + newname = [prefix, newname].join('/') unless prefix.empty? + assert_equal name, newname + end end def test_split_name_too_long_name @@ -239,6 +255,14 @@ class TestGemPackageTarWriter < Gem::Pac https://github.com/ruby/ruby/blob/trunk/test/rubygems/test_gem_package_tar_writer.rb#L255 exception = assert_raises Gem::Package::TooLongFileName do @tar_writer.split_name name end + assert_includes exception.message, name + + # note, GNU tar 1.28 is unable to handle this case too, + # tested with "tar --format=ustar -cPf /tmp/foo.tartar -- /aaaaaa....a" + name = '/' + 'a' * 100 + exception = assert_raises Gem::Package::TooLongFileName do + @tar_writer.split_name name + end assert_includes exception.message, name end Index: test/rubygems/test_gem_security_signer.rb =================================================================== --- test/rubygems/test_gem_security_signer.rb (revision 55440) +++ test/rubygems/test_gem_security_signer.rb (revision 55441) @@ -205,5 +205,13 @@ c7NM7KZZjj7G++SXjYTEI1PHSA7aFQ/i/+qSUvx+ https://github.com/ruby/ruby/blob/trunk/test/rubygems/test_gem_security_signer.rb#L205 end end + def test_sign_no_certs + signer = Gem::Security::Signer.new ALTERNATE_KEY, [] + + assert_raises Gem::Security::Exception do + signer.sign 'hello' + end + end + end if defined?(OpenSSL::SSL) Index: test/rubygems/test_gem_package.rb =================================================================== --- test/rubygems/test_gem_package.rb (revision 55440) +++ test/rubygems/test_gem_package.rb (revision 55441) @@ -141,7 +141,9 @@ class TestGemPackage < Gem::Package::Tar https://github.com/ruby/ruby/blob/trunk/test/rubygems/test_gem_package.rb#L141 FileUtils.mkdir_p 'lib' open 'lib/code.rb', 'w' do |io| io.write '# lib/code.rb' end - File.symlink('lib/code.rb', 'lib/code_sym.rb') + + # NOTE: 'code.rb' is correct, because it's relative to lib/code_sym.rb + File.symlink('code.rb', 'lib/code_sym.rb') package = Gem::Package.new 'bogus.gem' package.spec = spec @@ -156,12 +158,16 @@ class TestGemPackage < Gem::Package::Tar https://github.com/ruby/ruby/blob/trunk/test/rubygems/test_gem_package.rb#L158 Gem::Package::TarReader.new tar do |tar_io| tar_io.each_entry do |entry| - (entry.symlink? ? symlinks : files) << entry.full_name + if entry.symlink? + symlinks << { entry.full_name => entry.header.linkname } + else + files << entry.full_name + end end end assert_equal %w[lib/code.rb], files - assert_equal %w[lib/code_sym.rb], symlinks + assert_equal [{'lib/code_sym.rb' => 'lib/code.rb'}], symlinks end def test_build Index: test/rubygems/test_gem_installer.rb =================================================================== --- test/rubygems/test_gem_installer.rb (revision 55440) +++ test/rubygems/test_gem_installer.rb (revision 55441) @@ -1106,6 +1106,77 @@ gem 'other', version https://github.com/ruby/ruby/blob/trunk/test/rubygems/test_gem_installer.rb#L1106 assert_path_exists expected_makefile end + def test_install_extension_dir_is_removed_on_reinstall + @spec.extensions << "extconf.rb" + write_file File.join(@tempdir, "extconf.rb") do |io| + io.write <<-RUBY + require "mkmf" + create_makefile("#{@spec.name}") + RUBY + end + + @spec.files += %w[extconf.rb] + + path = Gem::Package.build @spec + + # Install a gem with an extension + use_ui @ui do + installer = Gem::Installer.at path + installer.install + end + + # pretend that a binary file was created as part of the build + should_be_removed = File.join(@spec.extension_dir, "#{@spec.name}.so") + write_file should_be_removed do |io| + io.write "DELETE ME ON REINSTALL" + end + assert_path_exists should_be_removed + + # reinstall the gem, this is also the same as pristine + use_ui @ui do + installer = Gem::Installer.at path + installer.install + end + + refute_path_exists should_be_removed + end + + def test_find_lib_file_after_install + @spec.extensions << "extconf.rb" + write_file File.join(@tempdir, "extconf.rb") do |io| + io.write <<-RUBY + require "mkmf" + create_makefile("#{@spec.name}") + RUBY + end + + write_file File.join(@tempdir, "a.c") do |io| + io.write <<-C + #include <ruby.h> + void Init_a() { } + C + end + + Dir.mkdir File.join(@tempdir, "lib") + write_file File.join(@tempdir, 'lib', "b.rb") do |io| + io.write "# b.rb" + end + + @spec.files += %w[extconf.rb lib/b.rb a.c] + + use_ui @ui do + path = Gem::Package.build @spec + + installer = Gem::Installer.at path + installer.install + end + + expected = File.join @spec.full_require_paths.find { |path| + File.exist? File.join path, 'b.rb' + }, 'b.rb' + assert_equal expected, @spec.matches_for_glob('b.rb').first + end + def test_install_extension_and_script @spec.extensions << "extconf.rb" write_file File.join(@tempdir, "extconf.rb") do |io| Index: test/rubygems/test_bundled_ca.rb =================================================================== --- test/rubygems/test_bundled_ca.rb (revision 55440) +++ test/rubygems/test_bundled_ca.rb (revision 55441) @@ -8,7 +8,7 @@ require 'rubygems/request' https://github.com/ruby/ruby/blob/trunk/test/rubygems/test_bundled_ca.rb#L8 # The tested hosts are explained in detail here: https://github.com/rubygems/rubygems/commit/5e16a5428f973667cabfa07e94ff939e7a83ebd9 # -if ENV["TRAVIS"] || ENV["TEST_SSL"] +if ENV["CI"] || ENV["TEST_SSL"] class TestBundledCA < Gem::TestCase THIS_FILE = File.expand_path __FILE__ Index: lib/rubygems.rb =================================================================== --- lib/rubygems.rb (revision 55440) +++ lib/rubygems.rb (revision 55441) @@ -154,6 +154,26 @@ module Gem https://github.com/ruby/ruby/blob/trunk/lib/rubygems.rb#L154 specifications/default ] + ## + # Exception classes used in a Gem.read_binary +rescue+ statement. Not all of + # these are defined in Ruby 1.8.7, hence the need for this convoluted setup. + + READ_BINARY_ERRORS = begin + read_binary_errors = [Errno::EACCES] + read_binary_errors << Errno::ENOTSUP if Errno.const_defined?(:ENOTSUP) + read_binary_errors + end.freeze + + ## + # Exception classes used in Gem.write_binary +rescue+ statement. Not all of + # these are defined in Ruby 1.8.7. + + WRITE_BINARY_ERRORS = begin + write_binary_errors = [] + write_binary_errors << Errno::ENOTSUP if Errno.const_defined?(:ENOTSUP) + write_binary_errors + end.freeze + @@win_platform = nil @configuration = nil @@ -829,7 +849,7 @@ An Array (#{env.inspect}) was passed in https://github.com/ruby/ruby/blob/trunk/lib/rubygems.rb#L849 f.flock(File::LOCK_EX) f.read end - rescue Errno::EACCES + rescue *READ_BINARY_ERRORS open path, 'rb' do |f| f.read end @@ -842,6 +862,26 @@ An Array (#{env.inspect}) was passed in https://github.com/ruby/ruby/blob/trunk/lib/rubygems.rb#L862 end end end + + ## + # Safely write a file in binary mode on all platforms. + def self.write_binary(path, data) + open(path, 'wb') do |io| + begin + io.flock(File::LOCK_EX) + rescue *WRITE_BINARY_ERRORS + end + io.write data + end + rescue Errno::ENOLCK # NFS + if Thread.main != Thread.current + raise + else + open(path, 'wb') do |io| + io.write data + end + end + end ## # The path to the running Ruby interpreter. Index: lib/rubygems/package.rb =================================================================== --- lib/rubygems/package.rb (revision 55440) +++ lib/rubygems/package.rb (revision 55441) @@ -211,7 +211,9 @@ class Gem::Package https://github.com/ruby/ruby/blob/trunk/lib/rubygems/package.rb#L211 stat = File.lstat file if stat.symlink? - tar.add_symlink file, File.readlink(file), stat.mode + relative_dir = File.dirname(file).sub("#{Dir.pwd}/", '') + target_path = File.join(relative_dir, File.readlink(file)) + tar.add_symlink file, target_path, stat.mode end next unless stat.file? Index: lib/rubygems/remote_fetcher.rb =================================================================== --- lib/rubygems/remote_fetcher.rb (revision 55440) +++ lib/rubygems/remote_fetcher.rb (revision 55441) @@ -328,20 +328,7 @@ class Gem::RemoteFetcher https://github.com/ruby/ruby/blob/trunk/lib/rubygems/remote_fetcher.rb#L328 end if update and path - begin - open(path, 'wb') do |io| - io.flock(File::LOCK_EX) - io.write data - end - rescue Errno::ENOLCK # NFS - if Thread.main != Thread.current - raise - else - open(path, 'wb') do |io| - io.write data - end - end - end + Gem.write_binary(path, data) end data @@ -427,4 +414,3 @@ class Gem::RemoteFetcher https://github.com/ruby/ruby/blob/trunk/lib/rubygems/remote_fetcher.rb#L414 end end end - Index: lib/rubygems/installer.rb =================================================================== --- lib/rubygems/installer.rb (revision 55440) +++ lib/rubygems/installer.rb (revision 55441) @@ -284,6 +284,7 @@ class Gem::Installer https://github.com/ruby/ruby/blob/trunk/lib/rubygems/installer.rb#L284 # Completely remove any previous gem files FileUtils.rm_rf gem_dir + FileUtils.rm_rf spec.extension_dir FileUtils.mkdir_p gem_dir Index: lib/rubygems/resolver/molinillo/lib/molinillo/state.rb =================================================================== --- lib/rubygems/resolver/molinillo/lib/molinillo/state.rb (revision 55440) +++ lib/rubygems/resolver/molinillo/lib/molinillo/state.rb (revision 55441) @@ -36,12 +36,14 @@ module Gem::Resolver::Molinillo https://github.com/ruby/ruby/blob/trunk/lib/rubygems/resolver/molinillo/lib/molinillo/state.rb#L36 PossibilityState.new( name, requirements.dup, - activated.dup, + activated, requirement, [possibilities.pop], depth + 1, conflicts.dup - ) + ).tap do |state| + state.activated.tag(state) + end end end Index: lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb =================================================================== --- lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb (revision 55440) +++ lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb (revision 55441) @@ -52,6 +52,7 @@ module Gem::Resolver::Molinillo https://github.com/ruby/ruby/blob/trunk/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb#L52 @base = base @states = [] @iteration_counter = 0 + @parent_of = {} end # Resolves the {#original_requested} dependencies into a full dependency @@ -67,7 +68,12 @@ module Gem::Resolver::Molinillo https://github.com/ruby/ruby/blob/trunk/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb#L68 indicate_progress if state.respond_to?(:pop_possibility_state) # DependencyState debug(depth) { "Creating possibility state for #{requirement} (#{possibilities.count} remaining)" } - state.pop_possibility_state.tap { |s| states.push(s) if s } + state.pop_possibility_state.tap do |s| + if s + states.push(s) + activated.tag(s) + end + end end process_topmost_state end @@ -118,27 +124,11 @@ module Gem::Resolver::Molinillo https://github.com/ruby/ruby/blob/trunk/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb#L124 require 'rubygems/resolver/molinillo/lib/molinillo/state' require 'rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider' - ResolutionState.new.members.each do |member| - define_method member do |*args, &block| - current_state = state || ResolutionState.empty - current_state.send(member, *args, &block) - end - end + require 'rubygems/resolver/molinillo/lib/molinillo/delegates/resolution_state' + require 'rubygems/resolver/molinillo/lib/molinillo/delegates/specification_provider' - SpecificationProvider.instance_methods(false).each do |instance_method| - define_method instance_method do |*args, &block| - begin - specification_provider.send(instance_method, *args, &block) - rescue NoSuchDependencyError => error - if state - vertex = activated.vertex_named(name_for error.dependency) - error.required_by += vertex.incoming_edges.map { |e| e.origin.name } - error.required_by << name_for_explicit_dependency_source unless vertex.explicit_requirements.empty? - end - raise - end - end - end + include Gem::Resolver::Molinillo::Delegates::ResolutionState + include Gem::Resolver::Molinillo::Delegates::SpecificationProvider # Processes the topmost available {RequirementState} on the stack # @return [void] @@ -169,6 +159,7 @@ module Gem::Resolver::Molinillo https://github.com/ruby/ruby/blob/trunk/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb#L159 def initial_state graph = DependencyGraph.new.tap do |dg| original_requested.each { |r| dg.add_vertex(name_for(r), nil, true).tap { |v| v.explicit_requirements << r } } + dg.tag(:initial_state) end requirements = sort_dependencies(original_requested, graph, {}) @@ -189,8 +180,9 @@ module Gem::Resolver::Molinillo https://github.com/ruby/ruby/blob/trunk/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb#L180 def unwind_for_conflict debug(depth) { "Unwinding for conflict: #{requirement}" } conflicts.tap do |c| - states.slice!((state_index_for_unwind + 1)..-1) + sliced_states = states.slice!((state_index_for_unwind + 1)..-1) raise VersionConflict.new(c) unless state + activated.rewind_to(sliced_states.first || :initial_state) if sliced_states state.conflicts = c end end @@ -217,20 +209,14 @@ module Gem::Resolver::Molinillo https://github.com/ruby/ruby/blob/trunk/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb#L209 # @return [Object] the requirement that led to `requirement` being added # to the list of requirements. def parent_of(requirement) - return nil unless requirement - seen = false - state = states.reverse_each.find do |s| - seen ||= s.requirement == requirement || s.requirements.include?(requirement) - seen && s.requirement != requirement && !s.requirements.include?(requirement) - end - state && state.requirement + @parent_of[requirement] end # @return [Object] the requirement that led to a version of a possibility # with the given name being activated. def requirement_for_existing_name(name) return nil unless activated.vertex_named(name).payload - states.reverse_each.find { |s| !s.activated.vertex_named(name).payload }.requirement + states.find { |s| s.name == name }.requirement end # @return [ResolutionState] the state whose `requirement` is the given @@ -250,19 +236,25 @@ module Gem::Resolver::Molinillo https://github.com/ruby/ruby/blob/trunk/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb#L236 # the {#possibility} in conjunction with the current {#state} def create_conflict vertex = activated.vertex_named(name) - requirements = { - name_for_explicit_dependency_source => vertex.explicit_requirements, - name_for_locking_dependency_source => Array(locked_requirement_named(name)), - } + locked_requirement = locked_requirement_named(name) + + requirements = {} + unless vertex.explicit_requirements.empty? + requirements[name_for_explicit_dependency_source] = vertex.explicit_requirements + end + requirements[name_for_locking_dependency_source] = [locked_requirement] if locked_requirement vertex.incoming_edges.each { |edge| (requirements[edge.origin.payload] ||= []).unshift(edge.requirement) } + + activated_by_name = {} + activated.each { |v| activated_by_name[v.name] = v.payload if v.payload } conflicts[name] = Conflict.new( requirement, - Hash[requirements.select { |_, r| !r.empty? }], + requirements, vertex.payload, possibility, - (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/