bundler 2.3.11 → 2.3.12

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0c24b409a733f2efbfde08b4f1ca210538a377ad365148d41b37d5802fa4040c
4
- data.tar.gz: 18a27b9facc0f42594d97fe40dfe8fcf34d4128048d4e208b5af5a9670c676b9
3
+ metadata.gz: 489c8d7661dcb4d99b7990a44d02dc883d10e31adb0297fa09f52ff502424e63
4
+ data.tar.gz: d050d525313844234ca93b7c879f7582ff2d0e0a334f33b706bc67039e8511b5
5
5
  SHA512:
6
- metadata.gz: 4938ee9af4788a04ec40959302c746da584b9694004d7b7d76896f7a6e588abf11f05d819678d7ea0199e78c1526cafac4a9aea1edc9ffb72db6f19a6a102900
7
- data.tar.gz: bf517233851defccbbc3cbc0d2fbc7d0ab0828dc3c558c5d503fc7a08b3a04c907b19be4a446415427fb6f56a062e5ed9a3ffcedf67b5acc308489124f4aadd3
6
+ metadata.gz: 853c3263abfbf6296e2256a5ea8df6860fe71591b25d3c5087839c9c0a0e5b7787b5696e621becb4c825f1429bc6fb1c07ca9b6b87f508910415ff23d2c05015
7
+ data.tar.gz: e4fe33afda4a3c4ab8ea8b3e6ba458fc335cc76443d1062a674be0093fb87b25dd37c310e53d0c00dca3417c2e20c89c5f4e72b03000e897d4136758ccc2e210
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ # 2.3.12 (April 20, 2022)
2
+
3
+ ## Enhancements:
4
+
5
+ - Improve Ruby version resolution conflicts [#5474](https://github.com/rubygems/rubygems/pull/5474)
6
+ - Stop considering `RUBY_PATCHLEVEL` for resolution [#5472](https://github.com/rubygems/rubygems/pull/5472)
7
+ - Add modern rubies as valid platform values in Gemfile DSL [#5469](https://github.com/rubygems/rubygems/pull/5469)
8
+
1
9
  # 2.3.11 (April 7, 2022)
2
10
 
3
11
  ## Enhancements:
@@ -4,8 +4,8 @@ module Bundler
4
4
  # Represents metadata from when the Bundler gem was built.
5
5
  module BuildMetadata
6
6
  # begin ivars
7
- @built_at = "2022-04-07".freeze
8
- @git_commit_sha = "9b6c5a801a".freeze
7
+ @built_at = "2022-04-20".freeze
8
+ @git_commit_sha = "75031e03f4".freeze
9
9
  @release = true
10
10
  # end ivars
11
11
 
@@ -21,6 +21,7 @@ module Bundler
21
21
  2.6
22
22
  2.7
23
23
  3.0
24
+ 3.1
24
25
  ].freeze
25
26
 
26
27
  KNOWN_MAJOR_VERSIONS = KNOWN_MINOR_VERSIONS.map {|v| v.split(".", 2).first }.uniq.freeze
@@ -732,30 +732,13 @@ module Bundler
732
732
 
733
733
  def metadata_dependencies
734
734
  @metadata_dependencies ||= begin
735
- ruby_versions = ruby_version_requirements(@ruby_version)
736
735
  [
737
- Dependency.new("Ruby\0", ruby_versions),
736
+ Dependency.new("Ruby\0", RubyVersion.system.gem_version),
738
737
  Dependency.new("RubyGems\0", Gem::VERSION),
739
738
  ]
740
739
  end
741
740
  end
742
741
 
743
- def ruby_version_requirements(ruby_version)
744
- return [] unless ruby_version
745
- if ruby_version.patchlevel
746
- [ruby_version.to_gem_version_with_patchlevel]
747
- else
748
- ruby_version.versions.map do |version|
749
- requirement = Gem::Requirement.new(version)
750
- if requirement.exact?
751
- "~> #{version}.0"
752
- else
753
- requirement
754
- end
755
- end
756
- end
757
- end
758
-
759
742
  def expand_dependencies(dependencies, remote = false)
760
743
  deps = []
761
744
  dependencies.each do |dep|
@@ -20,6 +20,9 @@ module Bundler
20
20
  :ruby_24 => Gem::Platform::RUBY,
21
21
  :ruby_25 => Gem::Platform::RUBY,
22
22
  :ruby_26 => Gem::Platform::RUBY,
23
+ :ruby_27 => Gem::Platform::RUBY,
24
+ :ruby_30 => Gem::Platform::RUBY,
25
+ :ruby_31 => Gem::Platform::RUBY,
23
26
  :mri => Gem::Platform::RUBY,
24
27
  :mri_18 => Gem::Platform::RUBY,
25
28
  :mri_19 => Gem::Platform::RUBY,
@@ -30,6 +33,9 @@ module Bundler
30
33
  :mri_24 => Gem::Platform::RUBY,
31
34
  :mri_25 => Gem::Platform::RUBY,
32
35
  :mri_26 => Gem::Platform::RUBY,
36
+ :mri_27 => Gem::Platform::RUBY,
37
+ :mri_30 => Gem::Platform::RUBY,
38
+ :mri_31 => Gem::Platform::RUBY,
33
39
  :rbx => Gem::Platform::RUBY,
34
40
  :truffleruby => Gem::Platform::RUBY,
35
41
  :jruby => Gem::Platform::JAVA,
@@ -45,6 +51,9 @@ module Bundler
45
51
  :mswin_24 => Gem::Platform::MSWIN,
46
52
  :mswin_25 => Gem::Platform::MSWIN,
47
53
  :mswin_26 => Gem::Platform::MSWIN,
54
+ :mswin_27 => Gem::Platform::MSWIN,
55
+ :mswin_30 => Gem::Platform::MSWIN,
56
+ :mswin_31 => Gem::Platform::MSWIN,
48
57
  :mswin64 => Gem::Platform::MSWIN64,
49
58
  :mswin64_19 => Gem::Platform::MSWIN64,
50
59
  :mswin64_20 => Gem::Platform::MSWIN64,
@@ -54,6 +63,9 @@ module Bundler
54
63
  :mswin64_24 => Gem::Platform::MSWIN64,
55
64
  :mswin64_25 => Gem::Platform::MSWIN64,
56
65
  :mswin64_26 => Gem::Platform::MSWIN64,
66
+ :mswin64_27 => Gem::Platform::MSWIN64,
67
+ :mswin64_30 => Gem::Platform::MSWIN64,
68
+ :mswin64_31 => Gem::Platform::MSWIN64,
57
69
  :mingw => Gem::Platform::MINGW,
58
70
  :mingw_18 => Gem::Platform::MINGW,
59
71
  :mingw_19 => Gem::Platform::MINGW,
@@ -64,6 +76,9 @@ module Bundler
64
76
  :mingw_24 => Gem::Platform::MINGW,
65
77
  :mingw_25 => Gem::Platform::MINGW,
66
78
  :mingw_26 => Gem::Platform::MINGW,
79
+ :mingw_27 => Gem::Platform::MINGW,
80
+ :mingw_30 => Gem::Platform::MINGW,
81
+ :mingw_31 => Gem::Platform::MINGW,
67
82
  :x64_mingw => Gem::Platform::X64_MINGW,
68
83
  :x64_mingw_20 => Gem::Platform::X64_MINGW,
69
84
  :x64_mingw_21 => Gem::Platform::X64_MINGW,
@@ -72,6 +87,9 @@ module Bundler
72
87
  :x64_mingw_24 => Gem::Platform::X64_MINGW,
73
88
  :x64_mingw_25 => Gem::Platform::X64_MINGW,
74
89
  :x64_mingw_26 => Gem::Platform::X64_MINGW,
90
+ :x64_mingw_27 => Gem::Platform::X64_MINGW,
91
+ :x64_mingw_30 => Gem::Platform::X64_MINGW,
92
+ :x64_mingw_31 => Gem::Platform::X64_MINGW,
75
93
  }.freeze
76
94
 
77
95
  def initialize(name, version, options = {}, &blk)
@@ -97,10 +97,10 @@ module Bundler
97
97
  spec = @specs[platform].first
98
98
  return [] if spec.is_a?(LazySpecification)
99
99
  dependencies = []
100
- if !spec.required_ruby_version.nil? && !spec.required_ruby_version.none?
100
+ unless spec.required_ruby_version.none?
101
101
  dependencies << DepProxy.get_proxy(Gem::Dependency.new("Ruby\0", spec.required_ruby_version), platform)
102
102
  end
103
- if !spec.required_rubygems_version.nil? && !spec.required_rubygems_version.none?
103
+ unless spec.required_rubygems_version.none?
104
104
  dependencies << DepProxy.get_proxy(Gem::Dependency.new("RubyGems\0", spec.required_rubygems_version), platform)
105
105
  end
106
106
  dependencies
@@ -312,29 +312,66 @@ module Bundler
312
312
 
313
313
  e = Molinillo::VersionConflict.new(conflicts, e.specification_provider) unless conflicts.empty?
314
314
 
315
- solver_name = "Bundler"
316
- possibility_type = "gem"
317
315
  e.message_with_trees(
318
- :solver_name => solver_name,
319
- :possibility_type => possibility_type,
320
- :reduce_trees => lambda do |trees|
316
+ :full_message_for_conflict => lambda do |name, conflict|
317
+ o = if name.end_with?("\0")
318
+ String.new("Bundler found conflicting requirements for the #{name} version:")
319
+ else
320
+ String.new("Bundler could not find compatible versions for gem \"#{name}\":")
321
+ end
322
+ o << %(\n)
323
+ if conflict.locked_requirement
324
+ o << %( In snapshot (#{name_for_locking_dependency_source}):\n)
325
+ o << %( #{SharedHelpers.pretty_dependency(conflict.locked_requirement)}\n)
326
+ o << %(\n)
327
+ end
328
+ o << %( In #{name_for_explicit_dependency_source}:\n)
329
+ trees = conflict.requirement_trees
330
+
321
331
  # called first, because we want to reduce the amount of work required to find maximal empty sets
322
332
  trees = trees.uniq {|t| t.flatten.map {|dep| [dep.name, dep.requirement] } }
323
333
 
324
334
  # bail out if tree size is too big for Array#combination to make any sense
325
- return trees if trees.size > 15
326
- maximal = 1.upto(trees.size).map do |size|
327
- trees.map(&:last).flatten(1).combination(size).to_a
328
- end.flatten(1).select do |deps|
329
- Bundler::VersionRanges.empty?(*Bundler::VersionRanges.for_many(deps.map(&:requirement)))
330
- end.min_by(&:size)
331
-
332
- trees.reject! {|t| !maximal.include?(t.last) } if maximal
333
-
334
- trees.sort_by {|t| t.reverse.map(&:name) }
335
- end,
336
- :printable_requirement => lambda {|req| SharedHelpers.pretty_dependency(req) },
337
- :additional_message_for_conflict => lambda do |o, name, conflict|
335
+ if trees.size <= 15
336
+ maximal = 1.upto(trees.size).map do |size|
337
+ trees.map(&:last).flatten(1).combination(size).to_a
338
+ end.flatten(1).select do |deps|
339
+ Bundler::VersionRanges.empty?(*Bundler::VersionRanges.for_many(deps.map(&:requirement)))
340
+ end.min_by(&:size)
341
+
342
+ trees.reject! {|t| !maximal.include?(t.last) } if maximal
343
+
344
+ trees.sort_by! {|t| t.reverse.map(&:name) }
345
+ end
346
+
347
+ metadata_requirements = {}
348
+
349
+ o << trees.map do |tree|
350
+ t = "".dup
351
+ depth = 2
352
+
353
+ base_tree = tree.first
354
+ base_tree_name = base_tree.name
355
+
356
+ if base_tree_name.end_with?("\0")
357
+ metadata_requirements[base_tree_name] = base_tree
358
+ t = nil
359
+ else
360
+ tree.each do |req|
361
+ t << " " * depth << SharedHelpers.pretty_dependency(req)
362
+ unless tree.last == req
363
+ if spec = conflict.activated_by_name[req.name]
364
+ t << %( was resolved to #{spec.version}, which)
365
+ end
366
+ t << %( depends on)
367
+ end
368
+ t << %(\n)
369
+ depth += 1
370
+ end
371
+ end
372
+ t
373
+ end.compact.join("\n")
374
+
338
375
  if name == "bundler"
339
376
  o << %(\n Current Bundler version:\n bundler (#{Bundler::VERSION}))
340
377
 
@@ -355,11 +392,13 @@ module Bundler
355
392
  o << "Your bundle requires a different version of Bundler than the one you're running, and that version could not be found.\n"
356
393
  end
357
394
  end
395
+ elsif name.end_with?("\0")
396
+ o << %(\n Current #{name} version:\n #{SharedHelpers.pretty_dependency(metadata_requirements[name])}\n\n)
358
397
  elsif conflict.locked_requirement
359
398
  o << "\n"
360
399
  o << %(Running `bundle update` will rebuild your snapshot from scratch, using only\n)
361
400
  o << %(the gems in your Gemfile, which may resolve the conflict.\n)
362
- elsif !conflict.existing && !name.end_with?("\0")
401
+ elsif !conflict.existing
363
402
  o << "\n"
364
403
 
365
404
  relevant_source = conflict.requirement.source || source_for(name)
@@ -372,14 +411,8 @@ module Bundler
372
411
 
373
412
  o << gem_not_found_message(name, conflict.requirement, relevant_source, extra_message)
374
413
  end
375
- end,
376
- :version_for_spec => lambda {|spec| spec.version },
377
- :incompatible_version_message_for_conflict => lambda do |name, _conflict|
378
- if name.end_with?("\0")
379
- %(#{solver_name} found conflicting requirements for the #{name} version:)
380
- else
381
- %(#{solver_name} could not find compatible versions for #{possibility_type} "#{name}":)
382
- end
414
+
415
+ o
383
416
  end
384
417
  )
385
418
  end
@@ -110,19 +110,6 @@ module Bundler
110
110
  @ruby_version ||= RubyVersion.new(ruby_version, patchlevel, ruby_engine, ruby_engine_version)
111
111
  end
112
112
 
113
- def to_gem_version_with_patchlevel
114
- @gem_version_with_patch ||= begin
115
- Gem::Version.create("#{@gem_version}.#{@patchlevel}")
116
- rescue ArgumentError
117
- @gem_version
118
- end
119
- end
120
-
121
- def exact?
122
- return @exact if defined?(@exact)
123
- @exact = versions.all? {|v| Gem::Requirement.create(v).exact? }
124
- end
125
-
126
113
  private
127
114
 
128
115
  def matches?(requirements, version)
@@ -67,6 +67,23 @@ module Gem
67
67
  full_gem_path
68
68
  end
69
69
 
70
+ unless const_defined?(:LATEST_RUBY_WITHOUT_PATCH_VERSIONS)
71
+ LATEST_RUBY_WITHOUT_PATCH_VERSIONS = Gem::Version.new("2.1")
72
+
73
+ alias_method :rg_required_ruby_version=, :required_ruby_version=
74
+ def required_ruby_version=(req)
75
+ self.rg_required_ruby_version = req
76
+
77
+ @required_ruby_version.requirements.map! do |op, v|
78
+ if v >= LATEST_RUBY_WITHOUT_PATCH_VERSIONS && v.release.segments.size == 4
79
+ [op == "~>" ? "=" : op, Gem::Version.new(v.segments.tap {|s| s.delete_at(3) }.join("."))]
80
+ else
81
+ [op, v]
82
+ end
83
+ end
84
+ end
85
+ end
86
+
70
87
  def groups
71
88
  @groups ||= []
72
89
  end
@@ -5,7 +5,7 @@ module Bundler
5
5
  class Metadata < Source
6
6
  def specs
7
7
  @specs ||= Index.build do |idx|
8
- idx << Gem::Specification.new("Ruby\0", RubyVersion.system.to_gem_version_with_patchlevel)
8
+ idx << Gem::Specification.new("Ruby\0", RubyVersion.system.gem_version)
9
9
  idx << Gem::Specification.new("RubyGems\0", Gem::VERSION) do |s|
10
10
  s.required_rubygems_version = Gem::Requirement.default
11
11
  end
@@ -32,7 +32,7 @@ module Bundler::Molinillo
32
32
  # all belong to the same graph.
33
33
  # @return [Array<Vertex>] The sorted vertices.
34
34
  def self.tsort(vertices)
35
- TSort.tsort(
35
+ Bundler::TSort.tsort(
36
36
  lambda { |b| vertices.each(&b) },
37
37
  lambda { |v, &b| (v.successors & vertices).each(&b) }
38
38
  )
@@ -107,36 +107,42 @@ module Bundler::Molinillo
107
107
  end
108
108
  end
109
109
 
110
- conflicts.sort.reduce(''.dup) do |o, (name, conflict)|
111
- o << "\n" << incompatible_version_message_for_conflict.call(name, conflict) << "\n"
112
- if conflict.locked_requirement
113
- o << %( In snapshot (#{name_for_locking_dependency_source}):\n)
114
- o << %( #{printable_requirement.call(conflict.locked_requirement)}\n)
115
- o << %(\n)
116
- end
117
- o << %( In #{name_for_explicit_dependency_source}:\n)
118
- trees = reduce_trees.call(conflict.requirement_trees)
119
-
120
- o << trees.map do |tree|
121
- t = ''.dup
122
- depth = 2
123
- tree.each do |req|
124
- t << ' ' * depth << printable_requirement.call(req)
125
- unless tree.last == req
126
- if spec = conflict.activated_by_name[name_for(req)]
127
- t << %( was resolved to #{version_for_spec.call(spec)}, which)
110
+ full_message_for_conflict = opts.delete(:full_message_for_conflict) do
111
+ proc do |name, conflict|
112
+ o = "\n".dup << incompatible_version_message_for_conflict.call(name, conflict) << "\n"
113
+ if conflict.locked_requirement
114
+ o << %( In snapshot (#{name_for_locking_dependency_source}):\n)
115
+ o << %( #{printable_requirement.call(conflict.locked_requirement)}\n)
116
+ o << %(\n)
117
+ end
118
+ o << %( In #{name_for_explicit_dependency_source}:\n)
119
+ trees = reduce_trees.call(conflict.requirement_trees)
120
+
121
+ o << trees.map do |tree|
122
+ t = ''.dup
123
+ depth = 2
124
+ tree.each do |req|
125
+ t << ' ' * depth << printable_requirement.call(req)
126
+ unless tree.last == req
127
+ if spec = conflict.activated_by_name[name_for(req)]
128
+ t << %( was resolved to #{version_for_spec.call(spec)}, which)
129
+ end
130
+ t << %( depends on)
128
131
  end
129
- t << %( depends on)
132
+ t << %(\n)
133
+ depth += 1
130
134
  end
131
- t << %(\n)
132
- depth += 1
133
- end
134
- t
135
- end.join("\n")
135
+ t
136
+ end.join("\n")
136
137
 
137
- additional_message_for_conflict.call(o, name, conflict)
138
+ additional_message_for_conflict.call(o, name, conflict)
138
139
 
139
- o
140
+ o
141
+ end
142
+ end
143
+
144
+ conflicts.sort.reduce(''.dup) do |o, (name, conflict)|
145
+ o << full_message_for_conflict.call(name, conflict)
140
146
  end.strip
141
147
  end
142
148
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Bundler::Molinillo
4
4
  # The version of Bundler::Molinillo.
5
- VERSION = '0.7.0'.freeze
5
+ VERSION = '0.8.0'.freeze
6
6
  end
@@ -6,24 +6,24 @@
6
6
  #
7
7
 
8
8
  #
9
- # TSort implements topological sorting using Tarjan's algorithm for
9
+ # Bundler::TSort implements topological sorting using Tarjan's algorithm for
10
10
  # strongly connected components.
11
11
  #
12
- # TSort is designed to be able to be used with any object which can be
12
+ # Bundler::TSort is designed to be able to be used with any object which can be
13
13
  # interpreted as a directed graph.
14
14
  #
15
- # TSort requires two methods to interpret an object as a graph,
15
+ # Bundler::TSort requires two methods to interpret an object as a graph,
16
16
  # tsort_each_node and tsort_each_child.
17
17
  #
18
18
  # * tsort_each_node is used to iterate for all nodes over a graph.
19
19
  # * tsort_each_child is used to iterate for child nodes of a given node.
20
20
  #
21
21
  # The equality of nodes are defined by eql? and hash since
22
- # TSort uses Hash internally.
22
+ # Bundler::TSort uses Hash internally.
23
23
  #
24
24
  # == A Simple Example
25
25
  #
26
- # The following example demonstrates how to mix the TSort module into an
26
+ # The following example demonstrates how to mix the Bundler::TSort module into an
27
27
  # existing class (in this case, Hash). Here, we're treating each key in
28
28
  # the hash as a node in the graph, and so we simply alias the required
29
29
  # #tsort_each_node method to Hash's #each_key method. For each key in the
@@ -32,10 +32,10 @@
32
32
  # method, which fetches the array of child nodes and then iterates over that
33
33
  # array using the user-supplied block.
34
34
  #
35
- # require 'tsort'
35
+ # require 'bundler/vendor/tsort/lib/tsort'
36
36
  #
37
37
  # class Hash
38
- # include TSort
38
+ # include Bundler::TSort
39
39
  # alias tsort_each_node each_key
40
40
  # def tsort_each_child(node, &block)
41
41
  # fetch(node).each(&block)
@@ -52,7 +52,7 @@
52
52
  #
53
53
  # A very simple `make' like tool can be implemented as follows:
54
54
  #
55
- # require 'tsort'
55
+ # require 'bundler/vendor/tsort/lib/tsort'
56
56
  #
57
57
  # class Make
58
58
  # def initialize
@@ -70,7 +70,7 @@
70
70
  # each_strongly_connected_component_from(target) {|ns|
71
71
  # if ns.length != 1
72
72
  # fs = ns.delete_if {|n| Array === n}
73
- # raise TSort::Cyclic.new("cyclic dependencies: #{fs.join ', '}")
73
+ # raise Bundler::TSort::Cyclic.new("cyclic dependencies: #{fs.join ', '}")
74
74
  # end
75
75
  # n = ns.first
76
76
  # if Array === n
@@ -93,7 +93,7 @@
93
93
  # def tsort_each_child(node, &block)
94
94
  # @dep[node].each(&block)
95
95
  # end
96
- # include TSort
96
+ # include Bundler::TSort
97
97
  # end
98
98
  #
99
99
  # def command(arg)
@@ -120,334 +120,333 @@
120
120
  # R. E. Tarjan, "Depth First Search and Linear Graph Algorithms",
121
121
  # <em>SIAM Journal on Computing</em>, Vol. 1, No. 2, pp. 146-160, June 1972.
122
122
  #
123
- module Bundler
124
- module TSort
125
- class Cyclic < StandardError
126
- end
127
123
 
128
- # Returns a topologically sorted array of nodes.
129
- # The array is sorted from children to parents, i.e.
130
- # the first element has no child and the last node has no parent.
131
- #
132
- # If there is a cycle, TSort::Cyclic is raised.
133
- #
134
- # class G
135
- # include TSort
136
- # def initialize(g)
137
- # @g = g
138
- # end
139
- # def tsort_each_child(n, &b) @g[n].each(&b) end
140
- # def tsort_each_node(&b) @g.each_key(&b) end
141
- # end
142
- #
143
- # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
144
- # p graph.tsort #=> [4, 2, 3, 1]
145
- #
146
- # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]})
147
- # p graph.tsort # raises TSort::Cyclic
148
- #
149
- def tsort
150
- each_node = method(:tsort_each_node)
151
- each_child = method(:tsort_each_child)
152
- TSort.tsort(each_node, each_child)
153
- end
124
+ module Bundler::TSort
125
+ class Cyclic < StandardError
126
+ end
154
127
 
155
- # Returns a topologically sorted array of nodes.
156
- # The array is sorted from children to parents, i.e.
157
- # the first element has no child and the last node has no parent.
158
- #
159
- # The graph is represented by _each_node_ and _each_child_.
160
- # _each_node_ should have +call+ method which yields for each node in the graph.
161
- # _each_child_ should have +call+ method which takes a node argument and yields for each child node.
162
- #
163
- # If there is a cycle, TSort::Cyclic is raised.
164
- #
165
- # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}
166
- # each_node = lambda {|&b| g.each_key(&b) }
167
- # each_child = lambda {|n, &b| g[n].each(&b) }
168
- # p TSort.tsort(each_node, each_child) #=> [4, 2, 3, 1]
169
- #
170
- # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
171
- # each_node = lambda {|&b| g.each_key(&b) }
172
- # each_child = lambda {|n, &b| g[n].each(&b) }
173
- # p TSort.tsort(each_node, each_child) # raises TSort::Cyclic
174
- #
175
- def TSort.tsort(each_node, each_child)
176
- TSort.tsort_each(each_node, each_child).to_a
177
- end
128
+ # Returns a topologically sorted array of nodes.
129
+ # The array is sorted from children to parents, i.e.
130
+ # the first element has no child and the last node has no parent.
131
+ #
132
+ # If there is a cycle, Bundler::TSort::Cyclic is raised.
133
+ #
134
+ # class G
135
+ # include Bundler::TSort
136
+ # def initialize(g)
137
+ # @g = g
138
+ # end
139
+ # def tsort_each_child(n, &b) @g[n].each(&b) end
140
+ # def tsort_each_node(&b) @g.each_key(&b) end
141
+ # end
142
+ #
143
+ # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
144
+ # p graph.tsort #=> [4, 2, 3, 1]
145
+ #
146
+ # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]})
147
+ # p graph.tsort # raises Bundler::TSort::Cyclic
148
+ #
149
+ def tsort
150
+ each_node = method(:tsort_each_node)
151
+ each_child = method(:tsort_each_child)
152
+ Bundler::TSort.tsort(each_node, each_child)
153
+ end
178
154
 
179
- # The iterator version of the #tsort method.
180
- # <tt><em>obj</em>.tsort_each</tt> is similar to <tt><em>obj</em>.tsort.each</tt>, but
181
- # modification of _obj_ during the iteration may lead to unexpected results.
182
- #
183
- # #tsort_each returns +nil+.
184
- # If there is a cycle, TSort::Cyclic is raised.
185
- #
186
- # class G
187
- # include TSort
188
- # def initialize(g)
189
- # @g = g
190
- # end
191
- # def tsort_each_child(n, &b) @g[n].each(&b) end
192
- # def tsort_each_node(&b) @g.each_key(&b) end
193
- # end
194
- #
195
- # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
196
- # graph.tsort_each {|n| p n }
197
- # #=> 4
198
- # # 2
199
- # # 3
200
- # # 1
201
- #
202
- def tsort_each(&block) # :yields: node
203
- each_node = method(:tsort_each_node)
204
- each_child = method(:tsort_each_child)
205
- TSort.tsort_each(each_node, each_child, &block)
206
- end
155
+ # Returns a topologically sorted array of nodes.
156
+ # The array is sorted from children to parents, i.e.
157
+ # the first element has no child and the last node has no parent.
158
+ #
159
+ # The graph is represented by _each_node_ and _each_child_.
160
+ # _each_node_ should have +call+ method which yields for each node in the graph.
161
+ # _each_child_ should have +call+ method which takes a node argument and yields for each child node.
162
+ #
163
+ # If there is a cycle, Bundler::TSort::Cyclic is raised.
164
+ #
165
+ # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}
166
+ # each_node = lambda {|&b| g.each_key(&b) }
167
+ # each_child = lambda {|n, &b| g[n].each(&b) }
168
+ # p Bundler::TSort.tsort(each_node, each_child) #=> [4, 2, 3, 1]
169
+ #
170
+ # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
171
+ # each_node = lambda {|&b| g.each_key(&b) }
172
+ # each_child = lambda {|n, &b| g[n].each(&b) }
173
+ # p Bundler::TSort.tsort(each_node, each_child) # raises Bundler::TSort::Cyclic
174
+ #
175
+ def self.tsort(each_node, each_child)
176
+ tsort_each(each_node, each_child).to_a
177
+ end
207
178
 
208
- # The iterator version of the TSort.tsort method.
209
- #
210
- # The graph is represented by _each_node_ and _each_child_.
211
- # _each_node_ should have +call+ method which yields for each node in the graph.
212
- # _each_child_ should have +call+ method which takes a node argument and yields for each child node.
213
- #
214
- # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}
215
- # each_node = lambda {|&b| g.each_key(&b) }
216
- # each_child = lambda {|n, &b| g[n].each(&b) }
217
- # TSort.tsort_each(each_node, each_child) {|n| p n }
218
- # #=> 4
219
- # # 2
220
- # # 3
221
- # # 1
222
- #
223
- def TSort.tsort_each(each_node, each_child) # :yields: node
224
- return to_enum(__method__, each_node, each_child) unless block_given?
179
+ # The iterator version of the #tsort method.
180
+ # <tt><em>obj</em>.tsort_each</tt> is similar to <tt><em>obj</em>.tsort.each</tt>, but
181
+ # modification of _obj_ during the iteration may lead to unexpected results.
182
+ #
183
+ # #tsort_each returns +nil+.
184
+ # If there is a cycle, Bundler::TSort::Cyclic is raised.
185
+ #
186
+ # class G
187
+ # include Bundler::TSort
188
+ # def initialize(g)
189
+ # @g = g
190
+ # end
191
+ # def tsort_each_child(n, &b) @g[n].each(&b) end
192
+ # def tsort_each_node(&b) @g.each_key(&b) end
193
+ # end
194
+ #
195
+ # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
196
+ # graph.tsort_each {|n| p n }
197
+ # #=> 4
198
+ # # 2
199
+ # # 3
200
+ # # 1
201
+ #
202
+ def tsort_each(&block) # :yields: node
203
+ each_node = method(:tsort_each_node)
204
+ each_child = method(:tsort_each_child)
205
+ Bundler::TSort.tsort_each(each_node, each_child, &block)
206
+ end
225
207
 
226
- TSort.each_strongly_connected_component(each_node, each_child) {|component|
227
- if component.size == 1
228
- yield component.first
229
- else
230
- raise Cyclic.new("topological sort failed: #{component.inspect}")
231
- end
232
- }
233
- end
208
+ # The iterator version of the Bundler::TSort.tsort method.
209
+ #
210
+ # The graph is represented by _each_node_ and _each_child_.
211
+ # _each_node_ should have +call+ method which yields for each node in the graph.
212
+ # _each_child_ should have +call+ method which takes a node argument and yields for each child node.
213
+ #
214
+ # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}
215
+ # each_node = lambda {|&b| g.each_key(&b) }
216
+ # each_child = lambda {|n, &b| g[n].each(&b) }
217
+ # Bundler::TSort.tsort_each(each_node, each_child) {|n| p n }
218
+ # #=> 4
219
+ # # 2
220
+ # # 3
221
+ # # 1
222
+ #
223
+ def self.tsort_each(each_node, each_child) # :yields: node
224
+ return to_enum(__method__, each_node, each_child) unless block_given?
234
225
 
235
- # Returns strongly connected components as an array of arrays of nodes.
236
- # The array is sorted from children to parents.
237
- # Each elements of the array represents a strongly connected component.
238
- #
239
- # class G
240
- # include TSort
241
- # def initialize(g)
242
- # @g = g
243
- # end
244
- # def tsort_each_child(n, &b) @g[n].each(&b) end
245
- # def tsort_each_node(&b) @g.each_key(&b) end
246
- # end
247
- #
248
- # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
249
- # p graph.strongly_connected_components #=> [[4], [2], [3], [1]]
250
- #
251
- # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]})
252
- # p graph.strongly_connected_components #=> [[4], [2, 3], [1]]
253
- #
254
- def strongly_connected_components
255
- each_node = method(:tsort_each_node)
256
- each_child = method(:tsort_each_child)
257
- TSort.strongly_connected_components(each_node, each_child)
258
- end
226
+ each_strongly_connected_component(each_node, each_child) {|component|
227
+ if component.size == 1
228
+ yield component.first
229
+ else
230
+ raise Cyclic.new("topological sort failed: #{component.inspect}")
231
+ end
232
+ }
233
+ end
259
234
 
260
- # Returns strongly connected components as an array of arrays of nodes.
261
- # The array is sorted from children to parents.
262
- # Each elements of the array represents a strongly connected component.
263
- #
264
- # The graph is represented by _each_node_ and _each_child_.
265
- # _each_node_ should have +call+ method which yields for each node in the graph.
266
- # _each_child_ should have +call+ method which takes a node argument and yields for each child node.
267
- #
268
- # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}
269
- # each_node = lambda {|&b| g.each_key(&b) }
270
- # each_child = lambda {|n, &b| g[n].each(&b) }
271
- # p TSort.strongly_connected_components(each_node, each_child)
272
- # #=> [[4], [2], [3], [1]]
273
- #
274
- # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
275
- # each_node = lambda {|&b| g.each_key(&b) }
276
- # each_child = lambda {|n, &b| g[n].each(&b) }
277
- # p TSort.strongly_connected_components(each_node, each_child)
278
- # #=> [[4], [2, 3], [1]]
279
- #
280
- def TSort.strongly_connected_components(each_node, each_child)
281
- TSort.each_strongly_connected_component(each_node, each_child).to_a
282
- end
235
+ # Returns strongly connected components as an array of arrays of nodes.
236
+ # The array is sorted from children to parents.
237
+ # Each elements of the array represents a strongly connected component.
238
+ #
239
+ # class G
240
+ # include Bundler::TSort
241
+ # def initialize(g)
242
+ # @g = g
243
+ # end
244
+ # def tsort_each_child(n, &b) @g[n].each(&b) end
245
+ # def tsort_each_node(&b) @g.each_key(&b) end
246
+ # end
247
+ #
248
+ # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
249
+ # p graph.strongly_connected_components #=> [[4], [2], [3], [1]]
250
+ #
251
+ # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]})
252
+ # p graph.strongly_connected_components #=> [[4], [2, 3], [1]]
253
+ #
254
+ def strongly_connected_components
255
+ each_node = method(:tsort_each_node)
256
+ each_child = method(:tsort_each_child)
257
+ Bundler::TSort.strongly_connected_components(each_node, each_child)
258
+ end
283
259
 
284
- # The iterator version of the #strongly_connected_components method.
285
- # <tt><em>obj</em>.each_strongly_connected_component</tt> is similar to
286
- # <tt><em>obj</em>.strongly_connected_components.each</tt>, but
287
- # modification of _obj_ during the iteration may lead to unexpected results.
288
- #
289
- # #each_strongly_connected_component returns +nil+.
290
- #
291
- # class G
292
- # include TSort
293
- # def initialize(g)
294
- # @g = g
295
- # end
296
- # def tsort_each_child(n, &b) @g[n].each(&b) end
297
- # def tsort_each_node(&b) @g.each_key(&b) end
298
- # end
299
- #
300
- # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
301
- # graph.each_strongly_connected_component {|scc| p scc }
302
- # #=> [4]
303
- # # [2]
304
- # # [3]
305
- # # [1]
306
- #
307
- # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]})
308
- # graph.each_strongly_connected_component {|scc| p scc }
309
- # #=> [4]
310
- # # [2, 3]
311
- # # [1]
312
- #
313
- def each_strongly_connected_component(&block) # :yields: nodes
314
- each_node = method(:tsort_each_node)
315
- each_child = method(:tsort_each_child)
316
- TSort.each_strongly_connected_component(each_node, each_child, &block)
317
- end
260
+ # Returns strongly connected components as an array of arrays of nodes.
261
+ # The array is sorted from children to parents.
262
+ # Each elements of the array represents a strongly connected component.
263
+ #
264
+ # The graph is represented by _each_node_ and _each_child_.
265
+ # _each_node_ should have +call+ method which yields for each node in the graph.
266
+ # _each_child_ should have +call+ method which takes a node argument and yields for each child node.
267
+ #
268
+ # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}
269
+ # each_node = lambda {|&b| g.each_key(&b) }
270
+ # each_child = lambda {|n, &b| g[n].each(&b) }
271
+ # p Bundler::TSort.strongly_connected_components(each_node, each_child)
272
+ # #=> [[4], [2], [3], [1]]
273
+ #
274
+ # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
275
+ # each_node = lambda {|&b| g.each_key(&b) }
276
+ # each_child = lambda {|n, &b| g[n].each(&b) }
277
+ # p Bundler::TSort.strongly_connected_components(each_node, each_child)
278
+ # #=> [[4], [2, 3], [1]]
279
+ #
280
+ def self.strongly_connected_components(each_node, each_child)
281
+ each_strongly_connected_component(each_node, each_child).to_a
282
+ end
318
283
 
319
- # The iterator version of the TSort.strongly_connected_components method.
320
- #
321
- # The graph is represented by _each_node_ and _each_child_.
322
- # _each_node_ should have +call+ method which yields for each node in the graph.
323
- # _each_child_ should have +call+ method which takes a node argument and yields for each child node.
324
- #
325
- # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}
326
- # each_node = lambda {|&b| g.each_key(&b) }
327
- # each_child = lambda {|n, &b| g[n].each(&b) }
328
- # TSort.each_strongly_connected_component(each_node, each_child) {|scc| p scc }
329
- # #=> [4]
330
- # # [2]
331
- # # [3]
332
- # # [1]
333
- #
334
- # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
335
- # each_node = lambda {|&b| g.each_key(&b) }
336
- # each_child = lambda {|n, &b| g[n].each(&b) }
337
- # TSort.each_strongly_connected_component(each_node, each_child) {|scc| p scc }
338
- # #=> [4]
339
- # # [2, 3]
340
- # # [1]
341
- #
342
- def TSort.each_strongly_connected_component(each_node, each_child) # :yields: nodes
343
- return to_enum(__method__, each_node, each_child) unless block_given?
284
+ # The iterator version of the #strongly_connected_components method.
285
+ # <tt><em>obj</em>.each_strongly_connected_component</tt> is similar to
286
+ # <tt><em>obj</em>.strongly_connected_components.each</tt>, but
287
+ # modification of _obj_ during the iteration may lead to unexpected results.
288
+ #
289
+ # #each_strongly_connected_component returns +nil+.
290
+ #
291
+ # class G
292
+ # include Bundler::TSort
293
+ # def initialize(g)
294
+ # @g = g
295
+ # end
296
+ # def tsort_each_child(n, &b) @g[n].each(&b) end
297
+ # def tsort_each_node(&b) @g.each_key(&b) end
298
+ # end
299
+ #
300
+ # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
301
+ # graph.each_strongly_connected_component {|scc| p scc }
302
+ # #=> [4]
303
+ # # [2]
304
+ # # [3]
305
+ # # [1]
306
+ #
307
+ # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]})
308
+ # graph.each_strongly_connected_component {|scc| p scc }
309
+ # #=> [4]
310
+ # # [2, 3]
311
+ # # [1]
312
+ #
313
+ def each_strongly_connected_component(&block) # :yields: nodes
314
+ each_node = method(:tsort_each_node)
315
+ each_child = method(:tsort_each_child)
316
+ Bundler::TSort.each_strongly_connected_component(each_node, each_child, &block)
317
+ end
344
318
 
345
- id_map = {}
346
- stack = []
347
- each_node.call {|node|
348
- unless id_map.include? node
349
- TSort.each_strongly_connected_component_from(node, each_child, id_map, stack) {|c|
350
- yield c
351
- }
352
- end
353
- }
354
- nil
355
- end
319
+ # The iterator version of the Bundler::TSort.strongly_connected_components method.
320
+ #
321
+ # The graph is represented by _each_node_ and _each_child_.
322
+ # _each_node_ should have +call+ method which yields for each node in the graph.
323
+ # _each_child_ should have +call+ method which takes a node argument and yields for each child node.
324
+ #
325
+ # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}
326
+ # each_node = lambda {|&b| g.each_key(&b) }
327
+ # each_child = lambda {|n, &b| g[n].each(&b) }
328
+ # Bundler::TSort.each_strongly_connected_component(each_node, each_child) {|scc| p scc }
329
+ # #=> [4]
330
+ # # [2]
331
+ # # [3]
332
+ # # [1]
333
+ #
334
+ # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
335
+ # each_node = lambda {|&b| g.each_key(&b) }
336
+ # each_child = lambda {|n, &b| g[n].each(&b) }
337
+ # Bundler::TSort.each_strongly_connected_component(each_node, each_child) {|scc| p scc }
338
+ # #=> [4]
339
+ # # [2, 3]
340
+ # # [1]
341
+ #
342
+ def self.each_strongly_connected_component(each_node, each_child) # :yields: nodes
343
+ return to_enum(__method__, each_node, each_child) unless block_given?
356
344
 
357
- # Iterates over strongly connected component in the subgraph reachable from
358
- # _node_.
359
- #
360
- # Return value is unspecified.
361
- #
362
- # #each_strongly_connected_component_from doesn't call #tsort_each_node.
363
- #
364
- # class G
365
- # include TSort
366
- # def initialize(g)
367
- # @g = g
368
- # end
369
- # def tsort_each_child(n, &b) @g[n].each(&b) end
370
- # def tsort_each_node(&b) @g.each_key(&b) end
371
- # end
372
- #
373
- # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
374
- # graph.each_strongly_connected_component_from(2) {|scc| p scc }
375
- # #=> [4]
376
- # # [2]
377
- #
378
- # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]})
379
- # graph.each_strongly_connected_component_from(2) {|scc| p scc }
380
- # #=> [4]
381
- # # [2, 3]
382
- #
383
- def each_strongly_connected_component_from(node, id_map={}, stack=[], &block) # :yields: nodes
384
- TSort.each_strongly_connected_component_from(node, method(:tsort_each_child), id_map, stack, &block)
385
- end
345
+ id_map = {}
346
+ stack = []
347
+ each_node.call {|node|
348
+ unless id_map.include? node
349
+ each_strongly_connected_component_from(node, each_child, id_map, stack) {|c|
350
+ yield c
351
+ }
352
+ end
353
+ }
354
+ nil
355
+ end
386
356
 
387
- # Iterates over strongly connected components in a graph.
388
- # The graph is represented by _node_ and _each_child_.
389
- #
390
- # _node_ is the first node.
391
- # _each_child_ should have +call+ method which takes a node argument
392
- # and yields for each child node.
393
- #
394
- # Return value is unspecified.
395
- #
396
- # #TSort.each_strongly_connected_component_from is a class method and
397
- # it doesn't need a class to represent a graph which includes TSort.
398
- #
399
- # graph = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
400
- # each_child = lambda {|n, &b| graph[n].each(&b) }
401
- # TSort.each_strongly_connected_component_from(1, each_child) {|scc|
402
- # p scc
403
- # }
404
- # #=> [4]
405
- # # [2, 3]
406
- # # [1]
407
- #
408
- def TSort.each_strongly_connected_component_from(node, each_child, id_map={}, stack=[]) # :yields: nodes
409
- return to_enum(__method__, node, each_child, id_map, stack) unless block_given?
357
+ # Iterates over strongly connected component in the subgraph reachable from
358
+ # _node_.
359
+ #
360
+ # Return value is unspecified.
361
+ #
362
+ # #each_strongly_connected_component_from doesn't call #tsort_each_node.
363
+ #
364
+ # class G
365
+ # include Bundler::TSort
366
+ # def initialize(g)
367
+ # @g = g
368
+ # end
369
+ # def tsort_each_child(n, &b) @g[n].each(&b) end
370
+ # def tsort_each_node(&b) @g.each_key(&b) end
371
+ # end
372
+ #
373
+ # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
374
+ # graph.each_strongly_connected_component_from(2) {|scc| p scc }
375
+ # #=> [4]
376
+ # # [2]
377
+ #
378
+ # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]})
379
+ # graph.each_strongly_connected_component_from(2) {|scc| p scc }
380
+ # #=> [4]
381
+ # # [2, 3]
382
+ #
383
+ def each_strongly_connected_component_from(node, id_map={}, stack=[], &block) # :yields: nodes
384
+ Bundler::TSort.each_strongly_connected_component_from(node, method(:tsort_each_child), id_map, stack, &block)
385
+ end
410
386
 
411
- minimum_id = node_id = id_map[node] = id_map.size
412
- stack_length = stack.length
413
- stack << node
387
+ # Iterates over strongly connected components in a graph.
388
+ # The graph is represented by _node_ and _each_child_.
389
+ #
390
+ # _node_ is the first node.
391
+ # _each_child_ should have +call+ method which takes a node argument
392
+ # and yields for each child node.
393
+ #
394
+ # Return value is unspecified.
395
+ #
396
+ # #Bundler::TSort.each_strongly_connected_component_from is a class method and
397
+ # it doesn't need a class to represent a graph which includes Bundler::TSort.
398
+ #
399
+ # graph = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
400
+ # each_child = lambda {|n, &b| graph[n].each(&b) }
401
+ # Bundler::TSort.each_strongly_connected_component_from(1, each_child) {|scc|
402
+ # p scc
403
+ # }
404
+ # #=> [4]
405
+ # # [2, 3]
406
+ # # [1]
407
+ #
408
+ def self.each_strongly_connected_component_from(node, each_child, id_map={}, stack=[]) # :yields: nodes
409
+ return to_enum(__method__, node, each_child, id_map, stack) unless block_given?
414
410
 
415
- each_child.call(node) {|child|
416
- if id_map.include? child
417
- child_id = id_map[child]
418
- minimum_id = child_id if child_id && child_id < minimum_id
419
- else
420
- sub_minimum_id =
421
- TSort.each_strongly_connected_component_from(child, each_child, id_map, stack) {|c|
422
- yield c
423
- }
424
- minimum_id = sub_minimum_id if sub_minimum_id < minimum_id
425
- end
426
- }
411
+ minimum_id = node_id = id_map[node] = id_map.size
412
+ stack_length = stack.length
413
+ stack << node
427
414
 
428
- if node_id == minimum_id
429
- component = stack.slice!(stack_length .. -1)
430
- component.each {|n| id_map[n] = nil}
431
- yield component
415
+ each_child.call(node) {|child|
416
+ if id_map.include? child
417
+ child_id = id_map[child]
418
+ minimum_id = child_id if child_id && child_id < minimum_id
419
+ else
420
+ sub_minimum_id =
421
+ each_strongly_connected_component_from(child, each_child, id_map, stack) {|c|
422
+ yield c
423
+ }
424
+ minimum_id = sub_minimum_id if sub_minimum_id < minimum_id
432
425
  end
426
+ }
433
427
 
434
- minimum_id
428
+ if node_id == minimum_id
429
+ component = stack.slice!(stack_length .. -1)
430
+ component.each {|n| id_map[n] = nil}
431
+ yield component
435
432
  end
436
433
 
437
- # Should be implemented by a extended class.
438
- #
439
- # #tsort_each_node is used to iterate for all nodes over a graph.
440
- #
441
- def tsort_each_node # :yields: node
442
- raise NotImplementedError.new
443
- end
434
+ minimum_id
435
+ end
444
436
 
445
- # Should be implemented by a extended class.
446
- #
447
- # #tsort_each_child is used to iterate for child nodes of _node_.
448
- #
449
- def tsort_each_child(node) # :yields: child
450
- raise NotImplementedError.new
451
- end
437
+ # Should be implemented by a extended class.
438
+ #
439
+ # #tsort_each_node is used to iterate for all nodes over a graph.
440
+ #
441
+ def tsort_each_node # :yields: node
442
+ raise NotImplementedError.new
443
+ end
444
+
445
+ # Should be implemented by a extended class.
446
+ #
447
+ # #tsort_each_child is used to iterate for child nodes of _node_.
448
+ #
449
+ def tsort_each_child(node) # :yields: child
450
+ raise NotImplementedError.new
452
451
  end
453
452
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: false
2
2
 
3
3
  module Bundler
4
- VERSION = "2.3.11".freeze
4
+ VERSION = "2.3.12".freeze
5
5
 
6
6
  def self.bundler_major_version
7
7
  @bundler_major_version ||= VERSION.split(".").first.to_i
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bundler
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.11
4
+ version: 2.3.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - André Arko
@@ -22,7 +22,7 @@ authors:
22
22
  autorequire:
23
23
  bindir: exe
24
24
  cert_chain: []
25
- date: 2022-04-07 00:00:00.000000000 Z
25
+ date: 2022-04-20 00:00:00.000000000 Z
26
26
  dependencies: []
27
27
  description: Bundler manages an application's dependencies through its entire life,
28
28
  across many machines, systematically and repeatably
@@ -369,7 +369,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
369
369
  - !ruby/object:Gem::Version
370
370
  version: 2.5.2
371
371
  requirements: []
372
- rubygems_version: 3.3.11
372
+ rubygems_version: 3.3.12
373
373
  signing_key:
374
374
  specification_version: 4
375
375
  summary: The best way to manage your application's dependencies