rubygems-update 3.3.26 → 3.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (272) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +35 -0
  3. data/CONTRIBUTING.md +24 -1
  4. data/Manifest.txt +30 -27
  5. data/POLICIES.md +10 -8
  6. data/README.md +2 -2
  7. data/bin/gem +1 -4
  8. data/bin/update_rubygems +1 -1
  9. data/bundler/CHANGELOG.md +59 -0
  10. data/bundler/README.md +2 -2
  11. data/bundler/bundler.gemspec +2 -2
  12. data/bundler/exe/bundle +1 -4
  13. data/bundler/lib/bundler/build_metadata.rb +2 -2
  14. data/bundler/lib/bundler/cli/add.rb +1 -1
  15. data/bundler/lib/bundler/cli/check.rb +1 -1
  16. data/bundler/lib/bundler/cli/common.rb +1 -0
  17. data/bundler/lib/bundler/cli/console.rb +2 -2
  18. data/bundler/lib/bundler/cli/doctor.rb +4 -6
  19. data/bundler/lib/bundler/cli/gem.rb +62 -40
  20. data/bundler/lib/bundler/cli/install.rb +2 -3
  21. data/bundler/lib/bundler/cli/lock.rb +8 -5
  22. data/bundler/lib/bundler/cli/outdated.rb +1 -3
  23. data/bundler/lib/bundler/cli/viz.rb +1 -1
  24. data/bundler/lib/bundler/cli.rb +43 -2
  25. data/bundler/lib/bundler/compact_index_client/cache.rb +1 -1
  26. data/bundler/lib/bundler/compact_index_client/updater.rb +40 -39
  27. data/bundler/lib/bundler/constants.rb +1 -1
  28. data/bundler/lib/bundler/definition.rb +61 -31
  29. data/bundler/lib/bundler/dependency.rb +12 -11
  30. data/bundler/lib/bundler/digest.rb +1 -1
  31. data/bundler/lib/bundler/dsl.rb +1 -1
  32. data/bundler/lib/bundler/env.rb +1 -1
  33. data/bundler/lib/bundler/environment_preserver.rb +1 -0
  34. data/bundler/lib/bundler/errors.rb +1 -11
  35. data/bundler/lib/bundler/fetcher/compact_index.rb +9 -11
  36. data/bundler/lib/bundler/fetcher/dependency.rb +1 -1
  37. data/bundler/lib/bundler/fetcher/downloader.rb +2 -5
  38. data/bundler/lib/bundler/fetcher.rb +2 -6
  39. data/bundler/lib/bundler/force_platform.rb +18 -0
  40. data/bundler/lib/bundler/friendly_errors.rb +0 -3
  41. data/bundler/lib/bundler/gem_version_promoter.rb +52 -86
  42. data/bundler/lib/bundler/graph.rb +3 -3
  43. data/bundler/lib/bundler/index.rb +5 -13
  44. data/bundler/lib/bundler/injector.rb +1 -1
  45. data/bundler/lib/bundler/inline.rb +2 -2
  46. data/bundler/lib/bundler/installer/parallel_installer.rb +0 -31
  47. data/bundler/lib/bundler/installer.rb +6 -16
  48. data/bundler/lib/bundler/lazy_specification.rb +5 -1
  49. data/bundler/lib/bundler/lockfile_parser.rb +5 -5
  50. data/bundler/lib/bundler/man/bundle-add.1 +1 -1
  51. data/bundler/lib/bundler/man/bundle-binstubs.1 +1 -1
  52. data/bundler/lib/bundler/man/bundle-cache.1 +1 -1
  53. data/bundler/lib/bundler/man/bundle-check.1 +1 -1
  54. data/bundler/lib/bundler/man/bundle-clean.1 +1 -1
  55. data/bundler/lib/bundler/man/bundle-config.1 +1 -1
  56. data/bundler/lib/bundler/man/bundle-console.1 +1 -1
  57. data/bundler/lib/bundler/man/bundle-doctor.1 +1 -1
  58. data/bundler/lib/bundler/man/bundle-exec.1 +1 -1
  59. data/bundler/lib/bundler/man/bundle-gem.1 +27 -37
  60. data/bundler/lib/bundler/man/bundle-gem.1.ronn +5 -5
  61. data/bundler/lib/bundler/man/bundle-help.1 +1 -1
  62. data/bundler/lib/bundler/man/bundle-info.1 +1 -1
  63. data/bundler/lib/bundler/man/bundle-init.1 +1 -1
  64. data/bundler/lib/bundler/man/bundle-inject.1 +1 -1
  65. data/bundler/lib/bundler/man/bundle-install.1 +1 -30
  66. data/bundler/lib/bundler/man/bundle-install.1.ronn +0 -29
  67. data/bundler/lib/bundler/man/bundle-list.1 +1 -1
  68. data/bundler/lib/bundler/man/bundle-lock.1 +1 -1
  69. data/bundler/lib/bundler/man/bundle-open.1 +1 -1
  70. data/bundler/lib/bundler/man/bundle-outdated.1 +1 -1
  71. data/bundler/lib/bundler/man/bundle-platform.1 +2 -2
  72. data/bundler/lib/bundler/man/bundle-platform.1.ronn +1 -1
  73. data/bundler/lib/bundler/man/bundle-plugin.1 +1 -1
  74. data/bundler/lib/bundler/man/bundle-pristine.1 +1 -1
  75. data/bundler/lib/bundler/man/bundle-remove.1 +1 -1
  76. data/bundler/lib/bundler/man/bundle-show.1 +1 -1
  77. data/bundler/lib/bundler/man/bundle-update.1 +1 -1
  78. data/bundler/lib/bundler/man/bundle-version.1 +1 -1
  79. data/bundler/lib/bundler/man/bundle-viz.1 +1 -1
  80. data/bundler/lib/bundler/man/bundle.1 +1 -1
  81. data/bundler/lib/bundler/man/gemfile.5 +1 -1
  82. data/bundler/lib/bundler/mirror.rb +5 -7
  83. data/bundler/lib/bundler/plugin/index.rb +4 -4
  84. data/bundler/lib/bundler/plugin/installer/rubygems.rb +0 -4
  85. data/bundler/lib/bundler/resolver/base.rb +7 -11
  86. data/bundler/lib/bundler/resolver/candidate.rb +92 -0
  87. data/bundler/lib/bundler/resolver/incompatibility.rb +15 -0
  88. data/bundler/lib/bundler/resolver/package.rb +63 -0
  89. data/bundler/lib/bundler/resolver/root.rb +25 -0
  90. data/bundler/lib/bundler/resolver/spec_group.rb +26 -36
  91. data/bundler/lib/bundler/resolver.rb +294 -277
  92. data/bundler/lib/bundler/rubygems_ext.rb +11 -6
  93. data/bundler/lib/bundler/rubygems_gem_installer.rb +4 -2
  94. data/bundler/lib/bundler/rubygems_integration.rb +1 -9
  95. data/bundler/lib/bundler/runtime.rb +1 -5
  96. data/bundler/lib/bundler/settings.rb +0 -6
  97. data/bundler/lib/bundler/shared_helpers.rb +1 -0
  98. data/bundler/lib/bundler/source/git/git_proxy.rb +193 -67
  99. data/bundler/lib/bundler/source/git.rb +15 -17
  100. data/bundler/lib/bundler/source/metadata.rb +0 -1
  101. data/bundler/lib/bundler/source/path/installer.rb +1 -22
  102. data/bundler/lib/bundler/source/path.rb +5 -5
  103. data/bundler/lib/bundler/source/rubygems.rb +13 -67
  104. data/bundler/lib/bundler/source_list.rb +8 -2
  105. data/bundler/lib/bundler/spec_set.rb +7 -9
  106. data/bundler/lib/bundler/templates/Executable +1 -1
  107. data/bundler/lib/bundler/templates/Executable.bundler +4 -9
  108. data/bundler/lib/bundler/templates/Executable.standalone +2 -0
  109. data/bundler/lib/bundler/templates/newgem/Cargo.toml.tt +7 -0
  110. data/bundler/lib/bundler/templates/newgem/Gemfile.tt +3 -0
  111. data/bundler/lib/bundler/templates/newgem/README.md.tt +6 -4
  112. data/bundler/lib/bundler/templates/newgem/Rakefile.tt +2 -1
  113. data/bundler/lib/bundler/templates/newgem/circleci/config.yml.tt +12 -0
  114. data/bundler/lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt +15 -0
  115. data/bundler/lib/bundler/templates/newgem/ext/newgem/{extconf.rb.tt → extconf-c.rb.tt} +0 -0
  116. data/bundler/lib/bundler/templates/newgem/ext/newgem/extconf-rust.rb.tt +6 -0
  117. data/bundler/lib/bundler/templates/newgem/ext/newgem/src/lib.rs.tt +12 -0
  118. data/bundler/lib/bundler/templates/newgem/github/workflows/main.yml.tt +10 -0
  119. data/bundler/lib/bundler/templates/newgem/gitignore.tt +3 -0
  120. data/bundler/lib/bundler/templates/newgem/gitlab-ci.yml.tt +8 -0
  121. data/bundler/lib/bundler/templates/newgem/newgem.gemspec.tt +8 -2
  122. data/bundler/lib/bundler/ui/shell.rb +35 -12
  123. data/bundler/lib/bundler/ui/silent.rb +21 -5
  124. data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +3 -3
  125. data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +0 -1
  126. data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +3 -1
  127. data/bundler/lib/bundler/vendor/fileutils/lib/fileutils.rb +1350 -408
  128. data/bundler/lib/bundler/vendor/net-http-persistent/README.rdoc +1 -1
  129. data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +1 -1
  130. data/bundler/lib/bundler/vendor/pub_grub/LICENSE.txt +21 -0
  131. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/assignment.rb +20 -0
  132. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/basic_package_source.rb +189 -0
  133. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/failure_writer.rb +182 -0
  134. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/incompatibility.rb +151 -0
  135. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/package.rb +43 -0
  136. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/partial_solution.rb +121 -0
  137. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/rubygems.rb +45 -0
  138. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/solve_failure.rb +19 -0
  139. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/static_package_source.rb +53 -0
  140. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/term.rb +105 -0
  141. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version.rb +3 -0
  142. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_constraint.rb +124 -0
  143. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_range.rb +409 -0
  144. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_solver.rb +240 -0
  145. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_union.rb +178 -0
  146. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub.rb +31 -0
  147. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +1 -1
  148. data/bundler/lib/bundler/vendor/uri/lib/uri/common.rb +64 -16
  149. data/bundler/lib/bundler/vendor/uri/lib/uri/file.rb +7 -1
  150. data/bundler/lib/bundler/vendor/uri/lib/uri/ftp.rb +2 -1
  151. data/bundler/lib/bundler/vendor/uri/lib/uri/generic.rb +27 -7
  152. data/bundler/lib/bundler/vendor/uri/lib/uri/http.rb +40 -2
  153. data/bundler/lib/bundler/vendor/uri/lib/uri/https.rb +2 -1
  154. data/bundler/lib/bundler/vendor/uri/lib/uri/ldap.rb +1 -1
  155. data/bundler/lib/bundler/vendor/uri/lib/uri/ldaps.rb +2 -1
  156. data/bundler/lib/bundler/vendor/uri/lib/uri/mailto.rb +2 -2
  157. data/bundler/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +13 -7
  158. data/bundler/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb +10 -5
  159. data/bundler/lib/bundler/vendor/uri/lib/uri/version.rb +1 -1
  160. data/bundler/lib/bundler/vendor/uri/lib/uri/ws.rb +1 -2
  161. data/bundler/lib/bundler/vendor/uri/lib/uri/wss.rb +2 -1
  162. data/bundler/lib/bundler/vendor/uri/lib/uri.rb +3 -2
  163. data/bundler/lib/bundler/vendored_persistent.rb +1 -33
  164. data/bundler/lib/bundler/{vendored_tmpdir.rb → vendored_pub_grub.rb} +1 -1
  165. data/bundler/lib/bundler/version.rb +5 -1
  166. data/bundler/lib/bundler/worker.rb +5 -7
  167. data/bundler/lib/bundler.rb +20 -64
  168. data/lib/rubygems/command_manager.rb +2 -2
  169. data/lib/rubygems/commands/fetch_command.rb +1 -1
  170. data/lib/rubygems/commands/install_command.rb +7 -3
  171. data/lib/rubygems/commands/rdoc_command.rb +3 -2
  172. data/lib/rubygems/commands/setup_command.rb +2 -2
  173. data/lib/rubygems/commands/unpack_command.rb +1 -1
  174. data/lib/rubygems/commands/update_command.rb +1 -7
  175. data/lib/rubygems/config_file.rb +33 -0
  176. data/lib/rubygems/core_ext/kernel_warn.rb +1 -2
  177. data/lib/rubygems/defaults.rb +15 -1
  178. data/lib/rubygems/dependency.rb +4 -1
  179. data/lib/rubygems/dependency_installer.rb +24 -24
  180. data/lib/rubygems/exceptions.rb +1 -3
  181. data/lib/rubygems/ext/builder.rb +3 -3
  182. data/lib/rubygems/ext/cargo_builder/link_flag_converter.rb +9 -5
  183. data/lib/rubygems/ext/cargo_builder.rb +15 -20
  184. data/lib/rubygems/ext/ext_conf_builder.rb +2 -0
  185. data/lib/rubygems/indexer.rb +1 -1
  186. data/lib/rubygems/installer.rb +5 -5
  187. data/lib/rubygems/optparse/lib/optparse.rb +20 -15
  188. data/lib/rubygems/package/tar_header.rb +11 -11
  189. data/lib/rubygems/platform.rb +0 -2
  190. data/lib/rubygems/request_set/gem_dependency_api.rb +104 -104
  191. data/lib/rubygems/requirement.rb +7 -7
  192. data/lib/rubygems/resolver/installer_set.rb +1 -1
  193. data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb +1 -1
  194. data/lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb +32 -26
  195. data/lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb +1 -1
  196. data/lib/rubygems/security/policies.rb +40 -40
  197. data/lib/rubygems/security/trust_dir.rb +1 -1
  198. data/lib/rubygems/security.rb +3 -16
  199. data/lib/rubygems/source.rb +2 -2
  200. data/lib/rubygems/specification.rb +37 -49
  201. data/lib/rubygems/specification_policy.rb +14 -0
  202. data/lib/rubygems/stub_specification.rb +2 -2
  203. data/lib/rubygems/text.rb +1 -1
  204. data/lib/rubygems/tsort/lib/tsort.rb +308 -310
  205. data/lib/rubygems/update_suggestion.rb +69 -0
  206. data/lib/rubygems/util.rb +1 -5
  207. data/lib/rubygems/validator.rb +1 -1
  208. data/lib/rubygems.rb +8 -3
  209. data/rubygems-update.gemspec +2 -2
  210. data/test/rubygems/helper.rb +7 -3
  211. data/test/rubygems/test_bundled_ca.rb +1 -1
  212. data/test/rubygems/test_exit.rb +6 -0
  213. data/test/rubygems/test_gem.rb +4 -9
  214. data/test/rubygems/test_gem_bundler_version_finder.rb +2 -1
  215. data/test/rubygems/test_gem_command_manager.rb +1 -1
  216. data/test/rubygems/test_gem_commands_install_command.rb +19 -0
  217. data/test/rubygems/test_gem_commands_setup_command.rb +1 -8
  218. data/test/rubygems/test_gem_commands_update_command.rb +6 -6
  219. data/test/rubygems/test_gem_config_file.rb +1 -1
  220. data/test/rubygems/test_gem_dependency.rb +2 -0
  221. data/test/rubygems/test_gem_ext_builder.rb +3 -3
  222. data/test/rubygems/test_gem_ext_cargo_builder/custom_name/Cargo.lock +22 -32
  223. data/test/rubygems/test_gem_ext_cargo_builder/custom_name/Cargo.toml +1 -1
  224. data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock +22 -32
  225. data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml +1 -1
  226. data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/src/lib.rs +12 -0
  227. data/test/rubygems/test_gem_ext_cargo_builder.rb +22 -27
  228. data/test/rubygems/test_gem_ext_cargo_builder_link_flag_converter.rb +16 -16
  229. data/test/rubygems/test_gem_ext_cargo_builder_unit.rb +0 -10
  230. data/test/rubygems/test_gem_indexer.rb +39 -20
  231. data/test/rubygems/test_gem_installer.rb +68 -2
  232. data/test/rubygems/test_gem_package_tar_header.rb +13 -13
  233. data/test/rubygems/test_gem_platform.rb +59 -60
  234. data/test/rubygems/test_gem_remote_fetcher.rb +4 -4
  235. data/test/rubygems/test_gem_request_set.rb +2 -2
  236. data/test/rubygems/test_gem_requirement.rb +1 -1
  237. data/test/rubygems/test_gem_resolver_api_set.rb +12 -12
  238. data/test/rubygems/test_gem_resolver_api_specification.rb +19 -19
  239. data/test/rubygems/test_gem_resolver_git_specification.rb +1 -1
  240. data/test/rubygems/test_gem_security_policy.rb +10 -10
  241. data/test/rubygems/test_gem_security_trust_dir.rb +2 -2
  242. data/test/rubygems/test_gem_specification.rb +50 -37
  243. data/test/rubygems/test_gem_uninstaller.rb +1 -1
  244. data/test/rubygems/test_gem_update_suggestion.rb +208 -0
  245. data/test/rubygems/test_kernel.rb +10 -8
  246. data/test/rubygems/test_require.rb +70 -55
  247. metadata +34 -31
  248. data/bundler/lib/bundler/templates/newgem/travis.yml.tt +0 -6
  249. data/bundler/lib/bundler/vendor/molinillo/LICENSE +0 -9
  250. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb +0 -57
  251. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb +0 -88
  252. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb +0 -36
  253. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +0 -66
  254. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +0 -62
  255. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +0 -63
  256. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +0 -61
  257. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb +0 -126
  258. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb +0 -46
  259. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +0 -36
  260. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +0 -164
  261. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +0 -255
  262. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +0 -149
  263. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +0 -6
  264. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +0 -112
  265. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb +0 -67
  266. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +0 -839
  267. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb +0 -46
  268. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/state.rb +0 -58
  269. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo.rb +0 -11
  270. data/bundler/lib/bundler/vendor/tmpdir/lib/tmpdir.rb +0 -154
  271. data/bundler/lib/bundler/vendored_molinillo.rb +0 -4
  272. data/bundler/lib/bundler/version_ranges.rb +0 -122
@@ -121,334 +121,332 @@
121
121
  # <em>SIAM Journal on Computing</em>, Vol. 1, No. 2, pp. 146-160, June 1972.
122
122
  #
123
123
 
124
- module Gem
125
- module TSort
126
- class Cyclic < StandardError
127
- end
128
-
129
- # Returns a topologically sorted array of nodes.
130
- # The array is sorted from children to parents, i.e.
131
- # the first element has no child and the last node has no parent.
132
- #
133
- # If there is a cycle, Gem::TSort::Cyclic is raised.
134
- #
135
- # class G
136
- # include Gem::TSort
137
- # def initialize(g)
138
- # @g = g
139
- # end
140
- # def tsort_each_child(n, &b) @g[n].each(&b) end
141
- # def tsort_each_node(&b) @g.each_key(&b) end
142
- # end
143
- #
144
- # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
145
- # p graph.tsort #=> [4, 2, 3, 1]
146
- #
147
- # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]})
148
- # p graph.tsort # raises Gem::TSort::Cyclic
149
- #
150
- def tsort
151
- each_node = method(:tsort_each_node)
152
- each_child = method(:tsort_each_child)
153
- Gem::TSort.tsort(each_node, each_child)
154
- end
124
+ module Gem::TSort
125
+ class Cyclic < StandardError
126
+ end
155
127
 
156
- # Returns a topologically sorted array of nodes.
157
- # The array is sorted from children to parents, i.e.
158
- # the first element has no child and the last node has no parent.
159
- #
160
- # The graph is represented by _each_node_ and _each_child_.
161
- # _each_node_ should have +call+ method which yields for each node in the graph.
162
- # _each_child_ should have +call+ method which takes a node argument and yields for each child node.
163
- #
164
- # If there is a cycle, Gem::TSort::Cyclic is raised.
165
- #
166
- # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}
167
- # each_node = lambda {|&b| g.each_key(&b) }
168
- # each_child = lambda {|n, &b| g[n].each(&b) }
169
- # p Gem::TSort.tsort(each_node, each_child) #=> [4, 2, 3, 1]
170
- #
171
- # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
172
- # each_node = lambda {|&b| g.each_key(&b) }
173
- # each_child = lambda {|n, &b| g[n].each(&b) }
174
- # p Gem::TSort.tsort(each_node, each_child) # raises Gem::TSort::Cyclic
175
- #
176
- def TSort.tsort(each_node, each_child)
177
- Gem::TSort.tsort_each(each_node, each_child).to_a
178
- 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, Gem::TSort::Cyclic is raised.
133
+ #
134
+ # class G
135
+ # include Gem::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 Gem::TSort::Cyclic
148
+ #
149
+ def tsort
150
+ each_node = method(:tsort_each_node)
151
+ each_child = method(:tsort_each_child)
152
+ Gem::TSort.tsort(each_node, each_child)
153
+ end
179
154
 
180
- # The iterator version of the #tsort method.
181
- # <tt><em>obj</em>.tsort_each</tt> is similar to <tt><em>obj</em>.tsort.each</tt>, but
182
- # modification of _obj_ during the iteration may lead to unexpected results.
183
- #
184
- # #tsort_each returns +nil+.
185
- # If there is a cycle, Gem::TSort::Cyclic is raised.
186
- #
187
- # class G
188
- # include Gem::TSort
189
- # def initialize(g)
190
- # @g = g
191
- # end
192
- # def tsort_each_child(n, &b) @g[n].each(&b) end
193
- # def tsort_each_node(&b) @g.each_key(&b) end
194
- # end
195
- #
196
- # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
197
- # graph.tsort_each {|n| p n }
198
- # #=> 4
199
- # # 2
200
- # # 3
201
- # # 1
202
- #
203
- def tsort_each(&block) # :yields: node
204
- each_node = method(:tsort_each_node)
205
- each_child = method(:tsort_each_child)
206
- Gem::TSort.tsort_each(each_node, each_child, &block)
207
- 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, Gem::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 Gem::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 Gem::TSort.tsort(each_node, each_child) # raises Gem::TSort::Cyclic
174
+ #
175
+ def self.tsort(each_node, each_child)
176
+ tsort_each(each_node, each_child).to_a
177
+ end
208
178
 
209
- # The iterator version of the Gem::TSort.tsort method.
210
- #
211
- # The graph is represented by _each_node_ and _each_child_.
212
- # _each_node_ should have +call+ method which yields for each node in the graph.
213
- # _each_child_ should have +call+ method which takes a node argument and yields for each child node.
214
- #
215
- # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}
216
- # each_node = lambda {|&b| g.each_key(&b) }
217
- # each_child = lambda {|n, &b| g[n].each(&b) }
218
- # Gem::TSort.tsort_each(each_node, each_child) {|n| p n }
219
- # #=> 4
220
- # # 2
221
- # # 3
222
- # # 1
223
- #
224
- def TSort.tsort_each(each_node, each_child) # :yields: node
225
- 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, Gem::TSort::Cyclic is raised.
185
+ #
186
+ # class G
187
+ # include Gem::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
+ Gem::TSort.tsort_each(each_node, each_child, &block)
206
+ end
226
207
 
227
- Gem::TSort.each_strongly_connected_component(each_node, each_child) {|component|
228
- if component.size == 1
229
- yield component.first
230
- else
231
- raise Cyclic.new("topological sort failed: #{component.inspect}")
232
- end
233
- }
234
- end
208
+ # The iterator version of the Gem::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
+ # Gem::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?
235
225
 
236
- # Returns strongly connected components as an array of arrays of nodes.
237
- # The array is sorted from children to parents.
238
- # Each elements of the array represents a strongly connected component.
239
- #
240
- # class G
241
- # include Gem::TSort
242
- # def initialize(g)
243
- # @g = g
244
- # end
245
- # def tsort_each_child(n, &b) @g[n].each(&b) end
246
- # def tsort_each_node(&b) @g.each_key(&b) end
247
- # end
248
- #
249
- # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
250
- # p graph.strongly_connected_components #=> [[4], [2], [3], [1]]
251
- #
252
- # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]})
253
- # p graph.strongly_connected_components #=> [[4], [2, 3], [1]]
254
- #
255
- def strongly_connected_components
256
- each_node = method(:tsort_each_node)
257
- each_child = method(:tsort_each_child)
258
- Gem::TSort.strongly_connected_components(each_node, each_child)
259
- 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
260
234
 
261
- # Returns strongly connected components as an array of arrays of nodes.
262
- # The array is sorted from children to parents.
263
- # Each elements of the array represents a strongly connected component.
264
- #
265
- # The graph is represented by _each_node_ and _each_child_.
266
- # _each_node_ should have +call+ method which yields for each node in the graph.
267
- # _each_child_ should have +call+ method which takes a node argument and yields for each child node.
268
- #
269
- # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}
270
- # each_node = lambda {|&b| g.each_key(&b) }
271
- # each_child = lambda {|n, &b| g[n].each(&b) }
272
- # p Gem::TSort.strongly_connected_components(each_node, each_child)
273
- # #=> [[4], [2], [3], [1]]
274
- #
275
- # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
276
- # each_node = lambda {|&b| g.each_key(&b) }
277
- # each_child = lambda {|n, &b| g[n].each(&b) }
278
- # p Gem::TSort.strongly_connected_components(each_node, each_child)
279
- # #=> [[4], [2, 3], [1]]
280
- #
281
- def TSort.strongly_connected_components(each_node, each_child)
282
- Gem::TSort.each_strongly_connected_component(each_node, each_child).to_a
283
- 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 Gem::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
+ Gem::TSort.strongly_connected_components(each_node, each_child)
258
+ end
284
259
 
285
- # The iterator version of the #strongly_connected_components method.
286
- # <tt><em>obj</em>.each_strongly_connected_component</tt> is similar to
287
- # <tt><em>obj</em>.strongly_connected_components.each</tt>, but
288
- # modification of _obj_ during the iteration may lead to unexpected results.
289
- #
290
- # #each_strongly_connected_component returns +nil+.
291
- #
292
- # class G
293
- # include Gem::TSort
294
- # def initialize(g)
295
- # @g = g
296
- # end
297
- # def tsort_each_child(n, &b) @g[n].each(&b) end
298
- # def tsort_each_node(&b) @g.each_key(&b) end
299
- # end
300
- #
301
- # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
302
- # graph.each_strongly_connected_component {|scc| p scc }
303
- # #=> [4]
304
- # # [2]
305
- # # [3]
306
- # # [1]
307
- #
308
- # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]})
309
- # graph.each_strongly_connected_component {|scc| p scc }
310
- # #=> [4]
311
- # # [2, 3]
312
- # # [1]
313
- #
314
- def each_strongly_connected_component(&block) # :yields: nodes
315
- each_node = method(:tsort_each_node)
316
- each_child = method(:tsort_each_child)
317
- Gem::TSort.each_strongly_connected_component(each_node, each_child, &block)
318
- 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 Gem::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 Gem::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
319
283
 
320
- # The iterator version of the Gem::TSort.strongly_connected_components method.
321
- #
322
- # The graph is represented by _each_node_ and _each_child_.
323
- # _each_node_ should have +call+ method which yields for each node in the graph.
324
- # _each_child_ should have +call+ method which takes a node argument and yields for each child node.
325
- #
326
- # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}
327
- # each_node = lambda {|&b| g.each_key(&b) }
328
- # each_child = lambda {|n, &b| g[n].each(&b) }
329
- # Gem::TSort.each_strongly_connected_component(each_node, each_child) {|scc| p scc }
330
- # #=> [4]
331
- # # [2]
332
- # # [3]
333
- # # [1]
334
- #
335
- # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
336
- # each_node = lambda {|&b| g.each_key(&b) }
337
- # each_child = lambda {|n, &b| g[n].each(&b) }
338
- # Gem::TSort.each_strongly_connected_component(each_node, each_child) {|scc| p scc }
339
- # #=> [4]
340
- # # [2, 3]
341
- # # [1]
342
- #
343
- def TSort.each_strongly_connected_component(each_node, each_child) # :yields: nodes
344
- 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 Gem::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
+ Gem::TSort.each_strongly_connected_component(each_node, each_child, &block)
317
+ end
345
318
 
346
- id_map = {}
347
- stack = []
348
- each_node.call {|node|
349
- unless id_map.include? node
350
- Gem::TSort.each_strongly_connected_component_from(node, each_child, id_map, stack) {|c|
351
- yield c
352
- }
353
- end
354
- }
355
- nil
356
- end
319
+ # The iterator version of the Gem::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
+ # Gem::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
+ # Gem::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?
357
344
 
358
- # Iterates over strongly connected component in the subgraph reachable from
359
- # _node_.
360
- #
361
- # Return value is unspecified.
362
- #
363
- # #each_strongly_connected_component_from doesn't call #tsort_each_node.
364
- #
365
- # class G
366
- # include Gem::TSort
367
- # def initialize(g)
368
- # @g = g
369
- # end
370
- # def tsort_each_child(n, &b) @g[n].each(&b) end
371
- # def tsort_each_node(&b) @g.each_key(&b) end
372
- # end
373
- #
374
- # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
375
- # graph.each_strongly_connected_component_from(2) {|scc| p scc }
376
- # #=> [4]
377
- # # [2]
378
- #
379
- # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]})
380
- # graph.each_strongly_connected_component_from(2) {|scc| p scc }
381
- # #=> [4]
382
- # # [2, 3]
383
- #
384
- def each_strongly_connected_component_from(node, id_map={}, stack=[], &block) # :yields: nodes
385
- Gem::TSort.each_strongly_connected_component_from(node, method(:tsort_each_child), id_map, stack, &block)
386
- 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
387
356
 
388
- # Iterates over strongly connected components in a graph.
389
- # The graph is represented by _node_ and _each_child_.
390
- #
391
- # _node_ is the first node.
392
- # _each_child_ should have +call+ method which takes a node argument
393
- # and yields for each child node.
394
- #
395
- # Return value is unspecified.
396
- #
397
- # #Gem::TSort.each_strongly_connected_component_from is a class method and
398
- # it doesn't need a class to represent a graph which includes Gem::TSort.
399
- #
400
- # graph = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
401
- # each_child = lambda {|n, &b| graph[n].each(&b) }
402
- # Gem::TSort.each_strongly_connected_component_from(1, each_child) {|scc|
403
- # p scc
404
- # }
405
- # #=> [4]
406
- # # [2, 3]
407
- # # [1]
408
- #
409
- def TSort.each_strongly_connected_component_from(node, each_child, id_map={}, stack=[]) # :yields: nodes
410
- 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 Gem::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
+ Gem::TSort.each_strongly_connected_component_from(node, method(:tsort_each_child), id_map, stack, &block)
385
+ end
411
386
 
412
- minimum_id = node_id = id_map[node] = id_map.size
413
- stack_length = stack.length
414
- 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
+ # #Gem::TSort.each_strongly_connected_component_from is a class method and
397
+ # it doesn't need a class to represent a graph which includes Gem::TSort.
398
+ #
399
+ # graph = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
400
+ # each_child = lambda {|n, &b| graph[n].each(&b) }
401
+ # Gem::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?
415
410
 
416
- each_child.call(node) {|child|
417
- if id_map.include? child
418
- child_id = id_map[child]
419
- minimum_id = child_id if child_id && child_id < minimum_id
420
- else
421
- sub_minimum_id =
422
- Gem::TSort.each_strongly_connected_component_from(child, each_child, id_map, stack) {|c|
423
- yield c
424
- }
425
- minimum_id = sub_minimum_id if sub_minimum_id < minimum_id
426
- end
427
- }
411
+ minimum_id = node_id = id_map[node] = id_map.size
412
+ stack_length = stack.length
413
+ stack << node
428
414
 
429
- if node_id == minimum_id
430
- component = stack.slice!(stack_length .. -1)
431
- component.each {|n| id_map[n] = nil}
432
- 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
433
425
  end
426
+ }
434
427
 
435
- 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
436
432
  end
437
433
 
438
- # Should be implemented by a extended class.
439
- #
440
- # #tsort_each_node is used to iterate for all nodes over a graph.
441
- #
442
- def tsort_each_node # :yields: node
443
- raise NotImplementedError.new
444
- end
434
+ minimum_id
435
+ end
445
436
 
446
- # Should be implemented by a extended class.
447
- #
448
- # #tsort_each_child is used to iterate for child nodes of _node_.
449
- #
450
- def tsort_each_child(node) # :yields: child
451
- raise NotImplementedError.new
452
- 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
453
451
  end
454
452
  end