[前][次][番号順一覧][スレッド一覧]

ruby-changes:45928

From: naruse <ko1@a...>
Date: Fri, 17 Mar 2017 13:36:56 +0900 (JST)
Subject: [ruby-changes:45928] naruse:r58001 (ruby_2_4): merge revision(s) 57523, 57998: [Backport #13322]

naruse	2017-03-17 13:36:49 +0900 (Fri, 17 Mar 2017)

  New Revision: 58001

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=58001

  Log:
    merge revision(s) 57523,57998: [Backport #13322]
    
    test_gem.rb: exclude default gems
    
    * test/rubygems/test_gem.rb: check difference to exclude default
      gems from the expected results.  [Feature #13186]
    Merge rubygems-2.6.11
    
      This version fixed regression of rubygems-2.6.10.
      https://github.com/rubygems/rubygems/pull/1856
    
      See details of changelogs for 2.6.11 release:
      https://github.com/rubygems/rubygems/blob/adfcf40502716080bd9cdfdd2e43bd4296872784/History.txt#L3

  Modified directories:
    branches/ruby_2_4/
  Modified files:
    branches/ruby_2_4/lib/rubygems/request_set/lockfile/tokenizer.rb
    branches/ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb
    branches/ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex.rb
    branches/ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb
    branches/ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb
    branches/ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/modules/ui.rb
    branches/ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb
    branches/ruby_2_4/lib/rubygems/resolver/set.rb
    branches/ruby_2_4/lib/rubygems/resolver.rb
    branches/ruby_2_4/lib/rubygems/test_case.rb
    branches/ruby_2_4/lib/rubygems.rb
    branches/ruby_2_4/test/rubygems/test_gem.rb
    branches/ruby_2_4/test/rubygems/test_gem_resolver.rb
    branches/ruby_2_4/version.h
Index: ruby_2_4/lib/rubygems.rb
===================================================================
--- ruby_2_4/lib/rubygems.rb	(revision 58000)
+++ ruby_2_4/lib/rubygems.rb	(revision 58001)
@@ -10,7 +10,7 @@ require 'rbconfig' https://github.com/ruby/ruby/blob/trunk/ruby_2_4/lib/rubygems.rb#L10
 require 'thread'
 
 module Gem
-  VERSION = "2.6.10"
+  VERSION = "2.6.11"
 end
 
 # Must be first since it unloads the prelude from 1.9.2
Index: ruby_2_4/lib/rubygems/request_set/lockfile/tokenizer.rb
===================================================================
--- ruby_2_4/lib/rubygems/request_set/lockfile/tokenizer.rb	(revision 58000)
+++ ruby_2_4/lib/rubygems/request_set/lockfile/tokenizer.rb	(revision 58001)
@@ -1,5 +1,4 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_4/lib/rubygems/request_set/lockfile/tokenizer.rb#L1
 # frozen_string_literal: true
-require 'strscan'
 require 'rubygems/request_set/lockfile/parser'
 
 class Gem::RequestSet::Lockfile::Tokenizer
@@ -58,6 +57,7 @@ class Gem::RequestSet::Lockfile::Tokeniz https://github.com/ruby/ruby/blob/trunk/ruby_2_4/lib/rubygems/request_set/lockfile/tokenizer.rb#L57
   private
 
   def tokenize input
+    require 'strscan'
     s = StringScanner.new input
 
     until s.eos? do
Index: ruby_2_4/lib/rubygems/resolver.rb
===================================================================
--- ruby_2_4/lib/rubygems/resolver.rb	(revision 58000)
+++ ruby_2_4/lib/rubygems/resolver.rb	(revision 58001)
@@ -4,9 +4,6 @@ require 'rubygems/exceptions' https://github.com/ruby/ruby/blob/trunk/ruby_2_4/lib/rubygems/resolver.rb#L4
 require 'rubygems/util'
 require 'rubygems/util/list'
 
-require 'uri'
-require 'net/http'
-
 ##
 # Given a set of Gem::Dependency objects as +needed+ and a way to query the
 # set of available specs via +set+, calculates a set of ActivationRequest
@@ -256,6 +253,44 @@ class Gem::Resolver https://github.com/ruby/ruby/blob/trunk/ruby_2_4/lib/rubygems/resolver.rb#L253
     @soft_missing
   end
 
+  def sort_dependencies(dependencies, activated, conflicts)
+    dependencies.sort_by do |dependency|
+      name = name_for(dependency)
+      [
+        activated.vertex_named(name).payload ? 0 : 1,
+        amount_constrained(dependency),
+        conflicts[name] ? 0 : 1,
+        activated.vertex_named(name).payload ? 0 : search_for(dependency).count,
+      ]
+    end
+  end
+
+  SINGLE_POSSIBILITY_CONSTRAINT_PENALTY = 1_000_000
+  private_constant :SINGLE_POSSIBILITY_CONSTRAINT_PENALTY if defined?(private_constant)
+
+  # returns an integer \in (-\infty, 0]
+  # a number closer to 0 means the dependency is less constraining
+  #
+  # dependencies w/ 0 or 1 possibilities (ignoring version requirements)
+  # are given very negative values, so they _always_ sort first,
+  # before dependencies that are unconstrained
+  def amount_constrained(dependency)
+    @amount_constrained ||= {}
+    @amount_constrained[dependency.name] ||= begin
+      name_dependency = Gem::Dependency.new(dependency.name)
+      dependency_request_for_name = Gem::Resolver::DependencyRequest.new(name_dependency, dependency.requester)
+      all = @set.find_all(dependency_request_for_name).size
+
+      if all <= 1
+        all - SINGLE_POSSIBILITY_CONSTRAINT_PENALTY
+      else
+        search = search_for(dependency).size
+        search - all
+      end
+    end
+  end
+  private :amount_constrained
+
 end
 
 ##
Index: ruby_2_4/lib/rubygems/resolver/set.rb
===================================================================
--- ruby_2_4/lib/rubygems/resolver/set.rb	(revision 58000)
+++ ruby_2_4/lib/rubygems/resolver/set.rb	(revision 58001)
@@ -21,6 +21,7 @@ class Gem::Resolver::Set https://github.com/ruby/ruby/blob/trunk/ruby_2_4/lib/rubygems/resolver/set.rb#L21
   attr_accessor :prerelease
 
   def initialize # :nodoc:
+    require 'uri'
     @prerelease = false
     @remote     = true
     @errors     = []
@@ -54,4 +55,3 @@ class Gem::Resolver::Set https://github.com/ruby/ruby/blob/trunk/ruby_2_4/lib/rubygems/resolver/set.rb#L55
   end
 
 end
-
Index: ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb
===================================================================
--- ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb	(revision 58000)
+++ ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb	(revision 58001)
@@ -23,8 +23,8 @@ module Gem::Resolver::Molinillo https://github.com/ruby/ruby/blob/trunk/ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb#L23
       # (see Action#down)
       def down(graph)
         edge = make_edge(graph)
-        edge.origin.outgoing_edges.delete(edge)
-        edge.destination.incoming_edges.delete(edge)
+        delete_first(edge.origin.outgoing_edges, edge)
+        delete_first(edge.destination.incoming_edges, edge)
       end
 
       # @!group AddEdgeNoCircular
@@ -53,6 +53,13 @@ module Gem::Resolver::Molinillo https://github.com/ruby/ruby/blob/trunk/ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb#L53
         @destination = destination
         @requirement = requirement
       end
+
+      private
+
+      def delete_first(array, item)
+        return unless index = array.index(item)
+        array.delete_at(index)
+      end
     end
   end
 end
Index: ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex.rb
===================================================================
--- ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex.rb	(revision 58000)
+++ ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex.rb	(revision 58001)
@@ -10,7 +10,7 @@ module Gem::Resolver::Molinillo https://github.com/ruby/ruby/blob/trunk/ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex.rb#L10
       # @return [Object] the payload the vertex holds
       attr_accessor :payload
 
-      # @return [Arrary<Object>] the explicit requirements that required
+      # @return [Array<Object>] the explicit requirements that required
       #   this vertex
       attr_reader :explicit_requirements
 
Index: ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb
===================================================================
--- ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb	(revision 58000)
+++ ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb	(revision 58001)
@@ -98,18 +98,27 @@ module Gem::Resolver::Molinillo https://github.com/ruby/ruby/blob/trunk/ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb#L98
       "#{self.class}:#{vertices.values.inspect}"
     end
 
+    # @param [Hash] options options for dot output.
     # @return [String] Returns a dot format representation of the graph
-    def to_dot
+    def to_dot(options = {})
+      edge_label = options.delete(:edge_label)
+      raise ArgumentError, "Unknown options: #{options.keys}" unless options.empty?
+
       dot_vertices = []
       dot_edges = []
       vertices.each do |n, v|
         dot_vertices << "  #{n} [label=\"{#{n}|#{v.payload}}\"]"
         v.outgoing_edges.each do |e|
-          dot_edges << "  #{e.origin.name} -> #{e.destination.name} [label=\"#{e.requirement}\"]"
+          label = edge_label ? edge_label.call(e) : e.requirement
+          dot_edges << "  #{e.origin.name} -> #{e.destination.name} [label=#{label.to_s.dump}]"
         end
       end
+
+      dot_vertices.uniq!
       dot_vertices.sort!
+      dot_edges.uniq!
       dot_edges.sort!
+
       dot = dot_vertices.unshift('digraph G {').push('') + dot_edges.push('}')
       dot.join("\n")
     end
@@ -123,7 +132,8 @@ module Gem::Resolver::Molinillo https://github.com/ruby/ruby/blob/trunk/ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb#L132
       vertices.each do |name, vertex|
         other_vertex = other.vertex_named(name)
         return false unless other_vertex
-        return false unless other_vertex.successors.map(&:name).to_set == vertex.successors.map(&:name).to_set
+        return false unless vertex.payload == other_vertex.payload
+        return false unless other_vertex.successors.to_set == vertex.successors.to_set
       end
     end
 
Index: ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb
===================================================================
--- ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb	(revision 58000)
+++ ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb	(revision 58001)
@@ -52,7 +52,7 @@ module Gem::Resolver::Molinillo https://github.com/ruby/ruby/blob/trunk/ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb#L52
         @base = base
         @states = []
         @iteration_counter = 0
-        @parent_of = {}
+        @parents_of = Hash.new { |h, k| h[k] = [] }
       end
 
       # Resolves the {#original_requested} dependencies into a full dependency
@@ -105,7 +105,7 @@ module Gem::Resolver::Molinillo https://github.com/ruby/ruby/blob/trunk/ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb#L105
 
         handle_missing_or_push_dependency_state(initial_state)
 
-        debug { "Starting resolution (#{@started_at})" }
+        debug { "Starting resolution (#{@started_at})\nUser-requested dependencies: #{original_requested}" }
         resolver_ui.before_resolution
       end
 
@@ -178,14 +178,14 @@ module Gem::Resolver::Molinillo https://github.com/ruby/ruby/blob/trunk/ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb#L178
       # Unwinds the states stack because a conflict has been encountered
       # @return [void]
       def unwind_for_conflict
-        debug(depth) { "Unwinding for conflict: #{requirement}" }
+        debug(depth) { "Unwinding for conflict: #{requirement} to #{state_index_for_unwind / 2}" }
         conflicts.tap do |c|
           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
           index = states.size - 1
-          @parent_of.reject! { |_, i| i >= index }
+          @parents_of.each { |_, a| a.reject! { |i| i >= index } }
         end
       end
 
@@ -214,7 +214,7 @@ module Gem::Resolver::Molinillo https://github.com/ruby/ruby/blob/trunk/ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb#L214
       #   to the list of requirements.
       def parent_of(requirement)
         return unless requirement
-        return unless index = @parent_of[requirement]
+        return unless index = @parents_of[requirement].last
         return unless parent_state = @states[index]
         parent_state.requirement
       end
@@ -356,16 +356,25 @@ module Gem::Resolver::Molinillo https://github.com/ruby/ruby/blob/trunk/ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb#L356
       # Ensures there are no orphaned successors to the given {vertex}.
       # @param [DependencyGraph::Vertex] vertex the vertex to fix up.
       # @return [void]
-      def fixup_swapped_children(vertex)
+      def fixup_swapped_children(vertex) # rubocop:disable Metrics/CyclomaticComplexity
         payload = vertex.payload
         deps = dependencies_for(payload).group_by(&method(:name_for))
         vertex.outgoing_edges.each do |outgoing_edge|
-          @parent_of[outgoing_edge.requirement] = states.size - 1
+          requirement = outgoing_edge.requirement
+          parent_index = @parents_of[requirement].last
           succ = outgoing_edge.destination
           matching_deps = Array(deps[succ.name])
+          dep_matched = matching_deps.include?(requirement)
+
+          # only push the current index when it was originally required by the
+          # same named spec
+          if parent_index && states[parent_index].name == name
+            @parents_of[requirement].push(states.size - 1)
+          end
+
           if matching_deps.empty? && !succ.root? && succ.predecessors.to_a == [vertex]
             debug(depth) { "Removing orphaned spec #{succ.name} after swapping #{name}" }
-            succ.requirements.each { |r| @parent_of.delete(r) }
+            succ.requirements.each { |r| @parents_of.delete(r) }
 
             removed_names = activated.detach_vertex_named(succ.name).map(&:name)
             requirements.delete_if do |r|
@@ -373,9 +382,14 @@ module Gem::Resolver::Molinillo https://github.com/ruby/ruby/blob/trunk/ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb#L382
               # so it's safe to delete only based upon name here
               removed_names.include?(name_for(r))
             end
-          elsif !matching_deps.include?(outgoing_edge.requirement)
+          elsif !dep_matched
+            debug(depth) { "Removing orphaned dependency #{requirement} after swapping #{name}" }
+            # also reset if we're removing the edge, but only if its parent has
+            # already been fixed up
+            @parents_of[requirement].push(states.size - 1) if @parents_of[requirement].empty?
+
             activated.delete_edge(outgoing_edge)
-            requirements.delete(outgoing_edge.requirement)
+            requirements.delete(requirement)
           end
         end
       end
@@ -395,13 +409,18 @@ module Gem::Resolver::Molinillo https://github.com/ruby/ruby/blob/trunk/ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb#L409
       # @return [Boolean] whether the current spec is satisfied as a new
       # possibility.
       def new_spec_satisfied?
+        unless requirement_satisfied_by?(requirement, activated, possibility)
+          debug(depth) { 'Unsatisfied by requested spec' }
+          return false
+        end
+
         locked_requirement = locked_requirement_named(name)
-        requested_spec_satisfied = requirement_satisfied_by?(requirement, activated, possibility)
+
         locked_spec_satisfied = !locked_requirement ||
           requirement_satisfied_by?(locked_requirement, activated, possibility)
-        debug(depth) { 'Unsatisfied by requested spec' } unless requested_spec_satisfied
         debug(depth) { 'Unsatisfied by locked spec' } unless locked_spec_satisfied
-        requested_spec_satisfied && locked_spec_satisfied
+
+        locked_spec_satisfied
       end
 
       # @param [String] requirement_name the spec name to search for
@@ -417,7 +436,7 @@ module Gem::Resolver::Molinillo https://github.com/ruby/ruby/blob/trunk/ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb#L436
       # @return [void]
       def activate_spec
         conflicts.delete(name)
-        debug(depth) { 'Activated ' + name + ' at ' + possibility.to_s }
+        debug(depth) { "Activated #{name} at #{possibility}" }
         activated.set_payload(name, possibility)
         require_nested_dependencies_for(possibility)
       end
@@ -432,7 +451,8 @@ module Gem::Resolver::Molinillo https://github.com/ruby/ruby/blob/trunk/ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb#L451
         nested_dependencies.each do |d|
           activated.add_child_vertex(name_for(d), nil, [name_for(activated_spec)], d)
           parent_index = states.size - 1
-          @parent_of[d] ||= parent_index
+          parents = @parents_of[d]
+          parents << parent_index if parents.empty?
         end
 
         push_state_for_requirements(requirements + nested_dependencies, !nested_dependencies.empty?)
Index: ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/modules/ui.rb
===================================================================
--- ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/modules/ui.rb	(revision 58000)
+++ ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/modules/ui.rb	(revision 58001)
@@ -48,7 +48,7 @@ module Gem::Resolver::Molinillo https://github.com/ruby/ruby/blob/trunk/ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/modules/ui.rb#L48
       if debug?
         debug_info = yield
         debug_info = debug_info.inspect unless debug_info.is_a?(String)
-        output.puts debug_info.split("\n").map { |s| '  ' * depth + s }
+        output.puts debug_info.split("\n").map { |s| ' ' * depth + s }
       end
     end
 
Index: ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb
===================================================================
--- ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb	(revision 58000)
+++ ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb	(revision 58001)
@@ -1,5 +1,5 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_4/lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb#L1
 # frozen_string_literal: true
 module Gem::Resolver::Molinillo
   # The version of Gem::Resolver::Molinillo.
-  VERSION = '0.5.5'.freeze
+  VERSION = '0.5.7'.freeze
 end
Index: ruby_2_4/lib/rubygems/test_case.rb
===================================================================
--- ruby_2_4/lib/rubygems/test_case.rb	(revision 58000)
+++ ruby_2_4/lib/rubygems/test_case.rb	(revision 58001)
@@ -1334,7 +1334,7 @@ Also, a list: https://github.com/ruby/ruby/blob/trunk/ruby_2_4/lib/rubygems/test_case.rb#L1334
   end
 
   ##
-  # create_gemspec creates gem specification in given +direcotry+ or '.'
+  # create_gemspec creates gem specification in given +directory+ or '.'
   # for the given +name+ and +version+.
   #
   # Yields the +specification+ to the block, if given
Index: ruby_2_4/test/rubygems/test_gem_resolver.rb
===================================================================
--- ruby_2_4/test/rubygems/test_gem_resolver.rb	(revision 58000)
+++ ruby_2_4/test/rubygems/test_gem_resolver.rb	(revision 58001)
@@ -521,11 +521,11 @@ class TestGemResolver < Gem::TestCase https://github.com/ruby/ruby/blob/trunk/ruby_2_4/test/rubygems/test_gem_resolver.rb#L521
     assert_equal req('>= 0'), dependency.requirement
 
     activated = e.conflict.activated
-    assert_equal 'c-2', activated.full_name
+    assert_equal 'c-1', activated.full_name
 
-    assert_equal dep('c', '>= 2'), activated.request.dependency
+    assert_equal dep('c', '= 1'), activated.request.dependency
 
-    assert_equal [dep('c', '= 1'), dep('c', '>= 2')],
+    assert_equal [dep('c', '>= 2'), dep('c', '= 1')],
                  e.conflict.conflicting_dependencies
   end
 
Index: ruby_2_4/test/rubygems/test_gem.rb
===================================================================
--- ruby_2_4/test/rubygems/test_gem.rb	(revision 58000)
+++ ruby_2_4/test/rubygems/test_gem.rb	(revision 58001)
@@ -1434,14 +1434,6 @@ class TestGem < Gem::TestCase https://github.com/ruby/ruby/blob/trunk/ruby_2_4/test/rubygems/test_gem.rb#L1434
 
     install_specs a, b, c
 
-    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
-
     path = File.join(@tempdir, "gd-tmp")
     install_gem a, :install_dir => path
     install_gem b, :install_dir => path
@@ -1450,10 +1442,27 @@ class TestGem < Gem::TestCase https://github.com/ruby/ruby/blob/trunk/ruby_2_4/test/rubygems/test_gem.rb#L1442
     ENV['GEM_PATH'] = path
     ENV['RUBYGEMS_GEMDEPS'] = "-"
 
-    out = `#{Gem.ruby.dup.untaint} -I "#{LIB_PATH.untaint}" -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"`
-    out.sub!(/, "openssl-#{Gem::Version::VERSION_PATTERN}"/, "")
+    path = File.join @tempdir, "gem.deps.rb"
+    cmd = [Gem.ruby.dup.untaint, "-I#{LIB_PATH.untaint}", "-rubygems"]
+    if RUBY_VERSION < '1.9'
+      cmd << "-e 'puts Gem.loaded_specs.values.map(&:full_name).sort'"
+      cmd = cmd.join(' ') (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]