rubygems-update 3.3.11 → 3.3.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +17 -0
  3. data/bundler/CHANGELOG.md +8 -0
  4. data/bundler/lib/bundler/build_metadata.rb +2 -2
  5. data/bundler/lib/bundler/current_ruby.rb +1 -0
  6. data/bundler/lib/bundler/definition.rb +1 -18
  7. data/bundler/lib/bundler/dependency.rb +18 -0
  8. data/bundler/lib/bundler/resolver/spec_group.rb +2 -2
  9. data/bundler/lib/bundler/resolver.rb +60 -27
  10. data/bundler/lib/bundler/ruby_version.rb +0 -13
  11. data/bundler/lib/bundler/rubygems_ext.rb +17 -0
  12. data/bundler/lib/bundler/source/metadata.rb +1 -1
  13. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +1 -1
  14. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +32 -26
  15. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +1 -1
  16. data/bundler/lib/bundler/vendor/tsort/lib/tsort.rb +318 -319
  17. data/bundler/lib/bundler/version.rb +1 -1
  18. data/lib/rubygems/installer.rb +0 -2
  19. data/lib/rubygems/optparse/lib/optparse/ac.rb +1 -1
  20. data/lib/rubygems/optparse/lib/optparse/date.rb +1 -1
  21. data/lib/rubygems/optparse/lib/optparse/kwargs.rb +1 -1
  22. data/lib/rubygems/optparse/lib/optparse/shellwords.rb +1 -1
  23. data/lib/rubygems/optparse/lib/optparse/time.rb +1 -1
  24. data/lib/rubygems/optparse/lib/optparse/uri.rb +1 -1
  25. data/lib/rubygems/optparse/lib/optparse.rb +75 -2
  26. data/lib/rubygems/specification.rb +10 -0
  27. data/lib/rubygems.rb +6 -8
  28. data/rubygems-update.gemspec +1 -1
  29. data/test/rubygems/helper.rb +1 -6
  30. data/test/rubygems/test_gem.rb +6 -14
  31. data/test/rubygems/test_gem_ext_cargo_builder/custom_name/Cargo.lock +2 -2
  32. data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock +2 -2
  33. data/test/rubygems/test_gem_ext_cargo_builder.rb +1 -3
  34. data/test/rubygems/test_gem_installer.rb +3 -5
  35. metadata +3 -3
@@ -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