bundler 2.0.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bundler might be problematic. Click here for more details.

Files changed (303) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +3111 -0
  3. data/LICENSE.md +23 -0
  4. data/README.md +63 -0
  5. data/bundler.gemspec +65 -0
  6. data/exe/bundle +31 -0
  7. data/exe/bundle_ruby +60 -0
  8. data/exe/bundler +4 -0
  9. data/lib/bundler.rb +567 -0
  10. data/lib/bundler/build_metadata.rb +53 -0
  11. data/lib/bundler/capistrano.rb +22 -0
  12. data/lib/bundler/cli.rb +792 -0
  13. data/lib/bundler/cli/add.rb +35 -0
  14. data/lib/bundler/cli/binstubs.rb +49 -0
  15. data/lib/bundler/cli/cache.rb +36 -0
  16. data/lib/bundler/cli/check.rb +38 -0
  17. data/lib/bundler/cli/clean.rb +25 -0
  18. data/lib/bundler/cli/common.rb +102 -0
  19. data/lib/bundler/cli/config.rb +119 -0
  20. data/lib/bundler/cli/console.rb +43 -0
  21. data/lib/bundler/cli/doctor.rb +140 -0
  22. data/lib/bundler/cli/exec.rb +105 -0
  23. data/lib/bundler/cli/gem.rb +252 -0
  24. data/lib/bundler/cli/info.rb +50 -0
  25. data/lib/bundler/cli/init.rb +47 -0
  26. data/lib/bundler/cli/inject.rb +60 -0
  27. data/lib/bundler/cli/install.rb +218 -0
  28. data/lib/bundler/cli/issue.rb +40 -0
  29. data/lib/bundler/cli/list.rb +58 -0
  30. data/lib/bundler/cli/lock.rb +63 -0
  31. data/lib/bundler/cli/open.rb +26 -0
  32. data/lib/bundler/cli/outdated.rb +266 -0
  33. data/lib/bundler/cli/package.rb +49 -0
  34. data/lib/bundler/cli/platform.rb +46 -0
  35. data/lib/bundler/cli/plugin.rb +24 -0
  36. data/lib/bundler/cli/pristine.rb +47 -0
  37. data/lib/bundler/cli/remove.rb +18 -0
  38. data/lib/bundler/cli/show.rb +75 -0
  39. data/lib/bundler/cli/update.rb +91 -0
  40. data/lib/bundler/cli/viz.rb +31 -0
  41. data/lib/bundler/compact_index_client.rb +109 -0
  42. data/lib/bundler/compact_index_client/cache.rb +118 -0
  43. data/lib/bundler/compact_index_client/updater.rb +116 -0
  44. data/lib/bundler/compatibility_guard.rb +13 -0
  45. data/lib/bundler/constants.rb +7 -0
  46. data/lib/bundler/current_ruby.rb +94 -0
  47. data/lib/bundler/definition.rb +995 -0
  48. data/lib/bundler/dep_proxy.rb +48 -0
  49. data/lib/bundler/dependency.rb +139 -0
  50. data/lib/bundler/deployment.rb +69 -0
  51. data/lib/bundler/deprecate.rb +44 -0
  52. data/lib/bundler/dsl.rb +615 -0
  53. data/lib/bundler/endpoint_specification.rb +141 -0
  54. data/lib/bundler/env.rb +149 -0
  55. data/lib/bundler/environment_preserver.rb +59 -0
  56. data/lib/bundler/errors.rb +158 -0
  57. data/lib/bundler/feature_flag.rb +75 -0
  58. data/lib/bundler/fetcher.rb +312 -0
  59. data/lib/bundler/fetcher/base.rb +52 -0
  60. data/lib/bundler/fetcher/compact_index.rb +126 -0
  61. data/lib/bundler/fetcher/dependency.rb +82 -0
  62. data/lib/bundler/fetcher/downloader.rb +84 -0
  63. data/lib/bundler/fetcher/index.rb +52 -0
  64. data/lib/bundler/friendly_errors.rb +131 -0
  65. data/lib/bundler/gem_helper.rb +217 -0
  66. data/lib/bundler/gem_helpers.rb +101 -0
  67. data/lib/bundler/gem_remote_fetcher.rb +43 -0
  68. data/lib/bundler/gem_tasks.rb +7 -0
  69. data/lib/bundler/gem_version_promoter.rb +190 -0
  70. data/lib/bundler/gemdeps.rb +29 -0
  71. data/lib/bundler/graph.rb +152 -0
  72. data/lib/bundler/index.rb +213 -0
  73. data/lib/bundler/injector.rb +253 -0
  74. data/lib/bundler/inline.rb +74 -0
  75. data/lib/bundler/installer.rb +318 -0
  76. data/lib/bundler/installer/gem_installer.rb +85 -0
  77. data/lib/bundler/installer/parallel_installer.rb +229 -0
  78. data/lib/bundler/installer/standalone.rb +53 -0
  79. data/lib/bundler/lazy_specification.rb +123 -0
  80. data/lib/bundler/lockfile_generator.rb +95 -0
  81. data/lib/bundler/lockfile_parser.rb +256 -0
  82. data/lib/bundler/match_platform.rb +24 -0
  83. data/lib/bundler/mirror.rb +223 -0
  84. data/lib/bundler/plugin.rb +294 -0
  85. data/lib/bundler/plugin/api.rb +81 -0
  86. data/lib/bundler/plugin/api/source.rb +306 -0
  87. data/lib/bundler/plugin/dsl.rb +53 -0
  88. data/lib/bundler/plugin/events.rb +61 -0
  89. data/lib/bundler/plugin/index.rb +165 -0
  90. data/lib/bundler/plugin/installer.rb +96 -0
  91. data/lib/bundler/plugin/installer/git.rb +38 -0
  92. data/lib/bundler/plugin/installer/rubygems.rb +27 -0
  93. data/lib/bundler/plugin/source_list.rb +27 -0
  94. data/lib/bundler/process_lock.rb +24 -0
  95. data/lib/bundler/psyched_yaml.rb +37 -0
  96. data/lib/bundler/remote_specification.rb +114 -0
  97. data/lib/bundler/resolver.rb +373 -0
  98. data/lib/bundler/resolver/spec_group.rb +106 -0
  99. data/lib/bundler/retry.rb +66 -0
  100. data/lib/bundler/ruby_dsl.rb +18 -0
  101. data/lib/bundler/ruby_version.rb +152 -0
  102. data/lib/bundler/rubygems_ext.rb +209 -0
  103. data/lib/bundler/rubygems_gem_installer.rb +99 -0
  104. data/lib/bundler/rubygems_integration.rb +915 -0
  105. data/lib/bundler/runtime.rb +322 -0
  106. data/lib/bundler/settings.rb +464 -0
  107. data/lib/bundler/settings/validator.rb +102 -0
  108. data/lib/bundler/setup.rb +28 -0
  109. data/lib/bundler/shared_helpers.rb +386 -0
  110. data/lib/bundler/similarity_detector.rb +63 -0
  111. data/lib/bundler/source.rb +94 -0
  112. data/lib/bundler/source/gemspec.rb +18 -0
  113. data/lib/bundler/source/git.rb +329 -0
  114. data/lib/bundler/source/git/git_proxy.rb +262 -0
  115. data/lib/bundler/source/metadata.rb +62 -0
  116. data/lib/bundler/source/path.rb +249 -0
  117. data/lib/bundler/source/path/installer.rb +74 -0
  118. data/lib/bundler/source/rubygems.rb +539 -0
  119. data/lib/bundler/source/rubygems/remote.rb +69 -0
  120. data/lib/bundler/source_list.rb +186 -0
  121. data/lib/bundler/spec_set.rb +208 -0
  122. data/lib/bundler/ssl_certs/.document +1 -0
  123. data/lib/bundler/ssl_certs/certificate_manager.rb +66 -0
  124. data/lib/bundler/ssl_certs/index.rubygems.org/GlobalSignRootCA.pem +21 -0
  125. data/lib/bundler/ssl_certs/rubygems.global.ssl.fastly.net/DigiCertHighAssuranceEVRootCA.pem +23 -0
  126. data/lib/bundler/ssl_certs/rubygems.org/AddTrustExternalCARoot.pem +25 -0
  127. data/lib/bundler/stub_specification.rb +108 -0
  128. data/lib/bundler/templates/.document +1 -0
  129. data/lib/bundler/templates/Executable +29 -0
  130. data/lib/bundler/templates/Executable.bundler +105 -0
  131. data/lib/bundler/templates/Executable.standalone +14 -0
  132. data/lib/bundler/templates/Gemfile +7 -0
  133. data/lib/bundler/templates/gems.rb +8 -0
  134. data/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +74 -0
  135. data/lib/bundler/templates/newgem/Gemfile.tt +4 -0
  136. data/lib/bundler/templates/newgem/LICENSE.txt.tt +21 -0
  137. data/lib/bundler/templates/newgem/README.md.tt +47 -0
  138. data/lib/bundler/templates/newgem/Rakefile.tt +29 -0
  139. data/lib/bundler/templates/newgem/bin/console.tt +14 -0
  140. data/lib/bundler/templates/newgem/bin/setup.tt +8 -0
  141. data/lib/bundler/templates/newgem/exe/newgem.tt +3 -0
  142. data/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt +3 -0
  143. data/lib/bundler/templates/newgem/ext/newgem/newgem.c.tt +9 -0
  144. data/lib/bundler/templates/newgem/ext/newgem/newgem.h.tt +6 -0
  145. data/lib/bundler/templates/newgem/gitignore.tt +20 -0
  146. data/lib/bundler/templates/newgem/lib/newgem.rb.tt +13 -0
  147. data/lib/bundler/templates/newgem/lib/newgem/version.rb.tt +7 -0
  148. data/lib/bundler/templates/newgem/newgem.gemspec.tt +50 -0
  149. data/lib/bundler/templates/newgem/rspec.tt +3 -0
  150. data/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +9 -0
  151. data/lib/bundler/templates/newgem/spec/spec_helper.rb.tt +14 -0
  152. data/lib/bundler/templates/newgem/test/newgem_test.rb.tt +11 -0
  153. data/lib/bundler/templates/newgem/test/test_helper.rb.tt +8 -0
  154. data/lib/bundler/templates/newgem/travis.yml.tt +7 -0
  155. data/lib/bundler/ui.rb +9 -0
  156. data/lib/bundler/ui/rg_proxy.rb +19 -0
  157. data/lib/bundler/ui/shell.rb +146 -0
  158. data/lib/bundler/ui/silent.rb +69 -0
  159. data/lib/bundler/uri_credentials_filter.rb +37 -0
  160. data/lib/bundler/vendor/fileutils/lib/fileutils.rb +1741 -0
  161. data/lib/bundler/vendor/fileutils/lib/fileutils/version.rb +5 -0
  162. data/lib/bundler/vendor/molinillo/lib/molinillo.rb +12 -0
  163. data/lib/bundler/vendor/molinillo/lib/molinillo/compatibility.rb +26 -0
  164. data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb +57 -0
  165. data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb +81 -0
  166. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +223 -0
  167. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb +36 -0
  168. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +66 -0
  169. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +62 -0
  170. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +63 -0
  171. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +61 -0
  172. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb +126 -0
  173. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb +46 -0
  174. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +36 -0
  175. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +136 -0
  176. data/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +143 -0
  177. data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +6 -0
  178. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +101 -0
  179. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb +67 -0
  180. data/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +837 -0
  181. data/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb +46 -0
  182. data/lib/bundler/vendor/molinillo/lib/molinillo/state.rb +58 -0
  183. data/lib/bundler/vendor/net-http-persistent/lib/net/http/faster.rb +27 -0
  184. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +1233 -0
  185. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/ssl_reuse.rb +129 -0
  186. data/lib/bundler/vendor/thor/lib/thor.rb +509 -0
  187. data/lib/bundler/vendor/thor/lib/thor/actions.rb +331 -0
  188. data/lib/bundler/vendor/thor/lib/thor/actions/create_file.rb +104 -0
  189. data/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb +60 -0
  190. data/lib/bundler/vendor/thor/lib/thor/actions/directory.rb +118 -0
  191. data/lib/bundler/vendor/thor/lib/thor/actions/empty_directory.rb +143 -0
  192. data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +373 -0
  193. data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +109 -0
  194. data/lib/bundler/vendor/thor/lib/thor/base.rb +678 -0
  195. data/lib/bundler/vendor/thor/lib/thor/command.rb +135 -0
  196. data/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +97 -0
  197. data/lib/bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb +12 -0
  198. data/lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb +129 -0
  199. data/lib/bundler/vendor/thor/lib/thor/error.rb +114 -0
  200. data/lib/bundler/vendor/thor/lib/thor/group.rb +281 -0
  201. data/lib/bundler/vendor/thor/lib/thor/invocation.rb +177 -0
  202. data/lib/bundler/vendor/thor/lib/thor/line_editor.rb +17 -0
  203. data/lib/bundler/vendor/thor/lib/thor/line_editor/basic.rb +37 -0
  204. data/lib/bundler/vendor/thor/lib/thor/line_editor/readline.rb +88 -0
  205. data/lib/bundler/vendor/thor/lib/thor/parser.rb +4 -0
  206. data/lib/bundler/vendor/thor/lib/thor/parser/argument.rb +70 -0
  207. data/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb +175 -0
  208. data/lib/bundler/vendor/thor/lib/thor/parser/option.rb +146 -0
  209. data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +226 -0
  210. data/lib/bundler/vendor/thor/lib/thor/rake_compat.rb +71 -0
  211. data/lib/bundler/vendor/thor/lib/thor/runner.rb +324 -0
  212. data/lib/bundler/vendor/thor/lib/thor/shell.rb +81 -0
  213. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +482 -0
  214. data/lib/bundler/vendor/thor/lib/thor/shell/color.rb +149 -0
  215. data/lib/bundler/vendor/thor/lib/thor/shell/html.rb +126 -0
  216. data/lib/bundler/vendor/thor/lib/thor/util.rb +268 -0
  217. data/lib/bundler/vendor/thor/lib/thor/version.rb +3 -0
  218. data/lib/bundler/vendored_fileutils.rb +9 -0
  219. data/lib/bundler/vendored_molinillo.rb +4 -0
  220. data/lib/bundler/vendored_persistent.rb +52 -0
  221. data/lib/bundler/vendored_thor.rb +8 -0
  222. data/lib/bundler/version.rb +28 -0
  223. data/lib/bundler/version_ranges.rb +76 -0
  224. data/lib/bundler/vlad.rb +17 -0
  225. data/lib/bundler/worker.rb +106 -0
  226. data/lib/bundler/yaml_serializer.rb +90 -0
  227. data/man/bundle-add.1 +58 -0
  228. data/man/bundle-add.1.txt +52 -0
  229. data/man/bundle-add.ronn +40 -0
  230. data/man/bundle-binstubs.1 +40 -0
  231. data/man/bundle-binstubs.1.txt +48 -0
  232. data/man/bundle-binstubs.ronn +43 -0
  233. data/man/bundle-check.1 +31 -0
  234. data/man/bundle-check.1.txt +33 -0
  235. data/man/bundle-check.ronn +26 -0
  236. data/man/bundle-clean.1 +24 -0
  237. data/man/bundle-clean.1.txt +26 -0
  238. data/man/bundle-clean.ronn +18 -0
  239. data/man/bundle-config.1 +497 -0
  240. data/man/bundle-config.1.txt +529 -0
  241. data/man/bundle-config.ronn +397 -0
  242. data/man/bundle-doctor.1 +44 -0
  243. data/man/bundle-doctor.1.txt +44 -0
  244. data/man/bundle-doctor.ronn +33 -0
  245. data/man/bundle-exec.1 +165 -0
  246. data/man/bundle-exec.1.txt +178 -0
  247. data/man/bundle-exec.ronn +152 -0
  248. data/man/bundle-gem.1 +80 -0
  249. data/man/bundle-gem.1.txt +91 -0
  250. data/man/bundle-gem.ronn +78 -0
  251. data/man/bundle-info.1 +20 -0
  252. data/man/bundle-info.1.txt +21 -0
  253. data/man/bundle-info.ronn +17 -0
  254. data/man/bundle-init.1 +25 -0
  255. data/man/bundle-init.1.txt +34 -0
  256. data/man/bundle-init.ronn +29 -0
  257. data/man/bundle-inject.1 +33 -0
  258. data/man/bundle-inject.1.txt +32 -0
  259. data/man/bundle-inject.ronn +22 -0
  260. data/man/bundle-install.1 +308 -0
  261. data/man/bundle-install.1.txt +396 -0
  262. data/man/bundle-install.ronn +378 -0
  263. data/man/bundle-list.1 +50 -0
  264. data/man/bundle-list.1.txt +43 -0
  265. data/man/bundle-list.ronn +33 -0
  266. data/man/bundle-lock.1 +84 -0
  267. data/man/bundle-lock.1.txt +93 -0
  268. data/man/bundle-lock.ronn +94 -0
  269. data/man/bundle-open.1 +32 -0
  270. data/man/bundle-open.1.txt +29 -0
  271. data/man/bundle-open.ronn +19 -0
  272. data/man/bundle-outdated.1 +155 -0
  273. data/man/bundle-outdated.1.txt +131 -0
  274. data/man/bundle-outdated.ronn +111 -0
  275. data/man/bundle-package.1 +55 -0
  276. data/man/bundle-package.1.txt +79 -0
  277. data/man/bundle-package.ronn +72 -0
  278. data/man/bundle-platform.1 +61 -0
  279. data/man/bundle-platform.1.txt +57 -0
  280. data/man/bundle-platform.ronn +42 -0
  281. data/man/bundle-pristine.1 +34 -0
  282. data/man/bundle-pristine.1.txt +44 -0
  283. data/man/bundle-pristine.ronn +34 -0
  284. data/man/bundle-remove.1 +31 -0
  285. data/man/bundle-remove.1.txt +34 -0
  286. data/man/bundle-remove.ronn +23 -0
  287. data/man/bundle-show.1 +23 -0
  288. data/man/bundle-show.1.txt +27 -0
  289. data/man/bundle-show.ronn +21 -0
  290. data/man/bundle-update.1 +394 -0
  291. data/man/bundle-update.1.txt +391 -0
  292. data/man/bundle-update.ronn +350 -0
  293. data/man/bundle-viz.1 +39 -0
  294. data/man/bundle-viz.1.txt +39 -0
  295. data/man/bundle-viz.ronn +30 -0
  296. data/man/bundle.1 +136 -0
  297. data/man/bundle.1.txt +116 -0
  298. data/man/bundle.ronn +111 -0
  299. data/man/gemfile.5 +689 -0
  300. data/man/gemfile.5.ronn +521 -0
  301. data/man/gemfile.5.txt +653 -0
  302. data/man/index.txt +25 -0
  303. metadata +463 -0
@@ -0,0 +1,281 @@
1
+ require "bundler/vendor/thor/lib/thor/base"
2
+
3
+ # Bundler::Thor has a special class called Bundler::Thor::Group. The main difference to Bundler::Thor class
4
+ # is that it invokes all commands at once. It also include some methods that allows
5
+ # invocations to be done at the class method, which are not available to Bundler::Thor
6
+ # commands.
7
+ class Bundler::Thor::Group
8
+ class << self
9
+ # The description for this Bundler::Thor::Group. If none is provided, but a source root
10
+ # exists, tries to find the USAGE one folder above it, otherwise searches
11
+ # in the superclass.
12
+ #
13
+ # ==== Parameters
14
+ # description<String>:: The description for this Bundler::Thor::Group.
15
+ #
16
+ def desc(description = nil)
17
+ if description
18
+ @desc = description
19
+ else
20
+ @desc ||= from_superclass(:desc, nil)
21
+ end
22
+ end
23
+
24
+ # Prints help information.
25
+ #
26
+ # ==== Options
27
+ # short:: When true, shows only usage.
28
+ #
29
+ def help(shell)
30
+ shell.say "Usage:"
31
+ shell.say " #{banner}\n"
32
+ shell.say
33
+ class_options_help(shell)
34
+ shell.say desc if desc
35
+ end
36
+
37
+ # Stores invocations for this class merging with superclass values.
38
+ #
39
+ def invocations #:nodoc:
40
+ @invocations ||= from_superclass(:invocations, {})
41
+ end
42
+
43
+ # Stores invocation blocks used on invoke_from_option.
44
+ #
45
+ def invocation_blocks #:nodoc:
46
+ @invocation_blocks ||= from_superclass(:invocation_blocks, {})
47
+ end
48
+
49
+ # Invoke the given namespace or class given. It adds an instance
50
+ # method that will invoke the klass and command. You can give a block to
51
+ # configure how it will be invoked.
52
+ #
53
+ # The namespace/class given will have its options showed on the help
54
+ # usage. Check invoke_from_option for more information.
55
+ #
56
+ def invoke(*names, &block)
57
+ options = names.last.is_a?(Hash) ? names.pop : {}
58
+ verbose = options.fetch(:verbose, true)
59
+
60
+ names.each do |name|
61
+ invocations[name] = false
62
+ invocation_blocks[name] = block if block_given?
63
+
64
+ class_eval <<-METHOD, __FILE__, __LINE__ + 1
65
+ def _invoke_#{name.to_s.gsub(/\W/, '_')}
66
+ klass, command = self.class.prepare_for_invocation(nil, #{name.inspect})
67
+
68
+ if klass
69
+ say_status :invoke, #{name.inspect}, #{verbose.inspect}
70
+ block = self.class.invocation_blocks[#{name.inspect}]
71
+ _invoke_for_class_method klass, command, &block
72
+ else
73
+ say_status :error, %(#{name.inspect} [not found]), :red
74
+ end
75
+ end
76
+ METHOD
77
+ end
78
+ end
79
+
80
+ # Invoke a thor class based on the value supplied by the user to the
81
+ # given option named "name". A class option must be created before this
82
+ # method is invoked for each name given.
83
+ #
84
+ # ==== Examples
85
+ #
86
+ # class GemGenerator < Bundler::Thor::Group
87
+ # class_option :test_framework, :type => :string
88
+ # invoke_from_option :test_framework
89
+ # end
90
+ #
91
+ # ==== Boolean options
92
+ #
93
+ # In some cases, you want to invoke a thor class if some option is true or
94
+ # false. This is automatically handled by invoke_from_option. Then the
95
+ # option name is used to invoke the generator.
96
+ #
97
+ # ==== Preparing for invocation
98
+ #
99
+ # In some cases you want to customize how a specified hook is going to be
100
+ # invoked. You can do that by overwriting the class method
101
+ # prepare_for_invocation. The class method must necessarily return a klass
102
+ # and an optional command.
103
+ #
104
+ # ==== Custom invocations
105
+ #
106
+ # You can also supply a block to customize how the option is going to be
107
+ # invoked. The block receives two parameters, an instance of the current
108
+ # class and the klass to be invoked.
109
+ #
110
+ def invoke_from_option(*names, &block)
111
+ options = names.last.is_a?(Hash) ? names.pop : {}
112
+ verbose = options.fetch(:verbose, :white)
113
+
114
+ names.each do |name|
115
+ unless class_options.key?(name)
116
+ raise ArgumentError, "You have to define the option #{name.inspect} " \
117
+ "before setting invoke_from_option."
118
+ end
119
+
120
+ invocations[name] = true
121
+ invocation_blocks[name] = block if block_given?
122
+
123
+ class_eval <<-METHOD, __FILE__, __LINE__ + 1
124
+ def _invoke_from_option_#{name.to_s.gsub(/\W/, '_')}
125
+ return unless options[#{name.inspect}]
126
+
127
+ value = options[#{name.inspect}]
128
+ value = #{name.inspect} if TrueClass === value
129
+ klass, command = self.class.prepare_for_invocation(#{name.inspect}, value)
130
+
131
+ if klass
132
+ say_status :invoke, value, #{verbose.inspect}
133
+ block = self.class.invocation_blocks[#{name.inspect}]
134
+ _invoke_for_class_method klass, command, &block
135
+ else
136
+ say_status :error, %(\#{value} [not found]), :red
137
+ end
138
+ end
139
+ METHOD
140
+ end
141
+ end
142
+
143
+ # Remove a previously added invocation.
144
+ #
145
+ # ==== Examples
146
+ #
147
+ # remove_invocation :test_framework
148
+ #
149
+ def remove_invocation(*names)
150
+ names.each do |name|
151
+ remove_command(name)
152
+ remove_class_option(name)
153
+ invocations.delete(name)
154
+ invocation_blocks.delete(name)
155
+ end
156
+ end
157
+
158
+ # Overwrite class options help to allow invoked generators options to be
159
+ # shown recursively when invoking a generator.
160
+ #
161
+ def class_options_help(shell, groups = {}) #:nodoc:
162
+ get_options_from_invocations(groups, class_options) do |klass|
163
+ klass.send(:get_options_from_invocations, groups, class_options)
164
+ end
165
+ super(shell, groups)
166
+ end
167
+
168
+ # Get invocations array and merge options from invocations. Those
169
+ # options are added to group_options hash. Options that already exists
170
+ # in base_options are not added twice.
171
+ #
172
+ def get_options_from_invocations(group_options, base_options) #:nodoc: # rubocop:disable MethodLength
173
+ invocations.each do |name, from_option|
174
+ value = if from_option
175
+ option = class_options[name]
176
+ option.type == :boolean ? name : option.default
177
+ else
178
+ name
179
+ end
180
+ next unless value
181
+
182
+ klass, _ = prepare_for_invocation(name, value)
183
+ next unless klass && klass.respond_to?(:class_options)
184
+
185
+ value = value.to_s
186
+ human_name = value.respond_to?(:classify) ? value.classify : value
187
+
188
+ group_options[human_name] ||= []
189
+ group_options[human_name] += klass.class_options.values.select do |class_option|
190
+ base_options[class_option.name.to_sym].nil? && class_option.group.nil? &&
191
+ !group_options.values.flatten.any? { |i| i.name == class_option.name }
192
+ end
193
+
194
+ yield klass if block_given?
195
+ end
196
+ end
197
+
198
+ # Returns commands ready to be printed.
199
+ def printable_commands(*)
200
+ item = []
201
+ item << banner
202
+ item << (desc ? "# #{desc.gsub(/\s+/m, ' ')}" : "")
203
+ [item]
204
+ end
205
+ alias_method :printable_tasks, :printable_commands
206
+
207
+ def handle_argument_error(command, error, _args, arity) #:nodoc:
208
+ msg = "#{basename} #{command.name} takes #{arity} argument".dup
209
+ msg << "s" if arity > 1
210
+ msg << ", but it should not."
211
+ raise error, msg
212
+ end
213
+
214
+ protected
215
+
216
+ # The method responsible for dispatching given the args.
217
+ def dispatch(command, given_args, given_opts, config) #:nodoc:
218
+ if Bundler::Thor::HELP_MAPPINGS.include?(given_args.first)
219
+ help(config[:shell])
220
+ return
221
+ end
222
+
223
+ args, opts = Bundler::Thor::Options.split(given_args)
224
+ opts = given_opts || opts
225
+
226
+ instance = new(args, opts, config)
227
+ yield instance if block_given?
228
+
229
+ if command
230
+ instance.invoke_command(all_commands[command])
231
+ else
232
+ instance.invoke_all
233
+ end
234
+ end
235
+
236
+ # The banner for this class. You can customize it if you are invoking the
237
+ # thor class by another ways which is not the Bundler::Thor::Runner.
238
+ def banner
239
+ "#{basename} #{self_command.formatted_usage(self, false)}"
240
+ end
241
+
242
+ # Represents the whole class as a command.
243
+ def self_command #:nodoc:
244
+ Bundler::Thor::DynamicCommand.new(namespace, class_options)
245
+ end
246
+ alias_method :self_task, :self_command
247
+
248
+ def baseclass #:nodoc:
249
+ Bundler::Thor::Group
250
+ end
251
+
252
+ def create_command(meth) #:nodoc:
253
+ commands[meth.to_s] = Bundler::Thor::Command.new(meth, nil, nil, nil, nil)
254
+ true
255
+ end
256
+ alias_method :create_task, :create_command
257
+ end
258
+
259
+ include Bundler::Thor::Base
260
+
261
+ protected
262
+
263
+ # Shortcut to invoke with padding and block handling. Use internally by
264
+ # invoke and invoke_from_option class methods.
265
+ def _invoke_for_class_method(klass, command = nil, *args, &block) #:nodoc:
266
+ with_padding do
267
+ if block
268
+ case block.arity
269
+ when 3
270
+ yield(self, klass, command)
271
+ when 2
272
+ yield(self, klass)
273
+ when 1
274
+ instance_exec(klass, &block)
275
+ end
276
+ else
277
+ invoke klass, command, *args
278
+ end
279
+ end
280
+ end
281
+ end
@@ -0,0 +1,177 @@
1
+ class Bundler::Thor
2
+ module Invocation
3
+ def self.included(base) #:nodoc:
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+ # This method is responsible for receiving a name and find the proper
9
+ # class and command for it. The key is an optional parameter which is
10
+ # available only in class methods invocations (i.e. in Bundler::Thor::Group).
11
+ def prepare_for_invocation(key, name) #:nodoc:
12
+ case name
13
+ when Symbol, String
14
+ Bundler::Thor::Util.find_class_and_command_by_namespace(name.to_s, !key)
15
+ else
16
+ name
17
+ end
18
+ end
19
+ end
20
+
21
+ # Make initializer aware of invocations and the initialization args.
22
+ def initialize(args = [], options = {}, config = {}, &block) #:nodoc:
23
+ @_invocations = config[:invocations] || Hash.new { |h, k| h[k] = [] }
24
+ @_initializer = [args, options, config]
25
+ super
26
+ end
27
+
28
+ # Make the current command chain accessible with in a Bundler::Thor-(sub)command
29
+ def current_command_chain
30
+ @_invocations.values.flatten.map(&:to_sym)
31
+ end
32
+
33
+ # Receives a name and invokes it. The name can be a string (either "command" or
34
+ # "namespace:command"), a Bundler::Thor::Command, a Class or a Bundler::Thor instance. If the
35
+ # command cannot be guessed by name, it can also be supplied as second argument.
36
+ #
37
+ # You can also supply the arguments, options and configuration values for
38
+ # the command to be invoked, if none is given, the same values used to
39
+ # initialize the invoker are used to initialize the invoked.
40
+ #
41
+ # When no name is given, it will invoke the default command of the current class.
42
+ #
43
+ # ==== Examples
44
+ #
45
+ # class A < Bundler::Thor
46
+ # def foo
47
+ # invoke :bar
48
+ # invoke "b:hello", ["Erik"]
49
+ # end
50
+ #
51
+ # def bar
52
+ # invoke "b:hello", ["Erik"]
53
+ # end
54
+ # end
55
+ #
56
+ # class B < Bundler::Thor
57
+ # def hello(name)
58
+ # puts "hello #{name}"
59
+ # end
60
+ # end
61
+ #
62
+ # You can notice that the method "foo" above invokes two commands: "bar",
63
+ # which belongs to the same class and "hello" which belongs to the class B.
64
+ #
65
+ # By using an invocation system you ensure that a command is invoked only once.
66
+ # In the example above, invoking "foo" will invoke "b:hello" just once, even
67
+ # if it's invoked later by "bar" method.
68
+ #
69
+ # When class A invokes class B, all arguments used on A initialization are
70
+ # supplied to B. This allows lazy parse of options. Let's suppose you have
71
+ # some rspec commands:
72
+ #
73
+ # class Rspec < Bundler::Thor::Group
74
+ # class_option :mock_framework, :type => :string, :default => :rr
75
+ #
76
+ # def invoke_mock_framework
77
+ # invoke "rspec:#{options[:mock_framework]}"
78
+ # end
79
+ # end
80
+ #
81
+ # As you noticed, it invokes the given mock framework, which might have its
82
+ # own options:
83
+ #
84
+ # class Rspec::RR < Bundler::Thor::Group
85
+ # class_option :style, :type => :string, :default => :mock
86
+ # end
87
+ #
88
+ # Since it's not rspec concern to parse mock framework options, when RR
89
+ # is invoked all options are parsed again, so RR can extract only the options
90
+ # that it's going to use.
91
+ #
92
+ # If you want Rspec::RR to be initialized with its own set of options, you
93
+ # have to do that explicitly:
94
+ #
95
+ # invoke "rspec:rr", [], :style => :foo
96
+ #
97
+ # Besides giving an instance, you can also give a class to invoke:
98
+ #
99
+ # invoke Rspec::RR, [], :style => :foo
100
+ #
101
+ def invoke(name = nil, *args)
102
+ if name.nil?
103
+ warn "[Bundler::Thor] Calling invoke() without argument is deprecated. Please use invoke_all instead.\n#{caller.join("\n")}"
104
+ return invoke_all
105
+ end
106
+
107
+ args.unshift(nil) if args.first.is_a?(Array) || args.first.nil?
108
+ command, args, opts, config = args
109
+
110
+ klass, command = _retrieve_class_and_command(name, command)
111
+ raise "Missing Bundler::Thor class for invoke #{name}" unless klass
112
+ raise "Expected Bundler::Thor class, got #{klass}" unless klass <= Bundler::Thor::Base
113
+
114
+ args, opts, config = _parse_initialization_options(args, opts, config)
115
+ klass.send(:dispatch, command, args, opts, config) do |instance|
116
+ instance.parent_options = options
117
+ end
118
+ end
119
+
120
+ # Invoke the given command if the given args.
121
+ def invoke_command(command, *args) #:nodoc:
122
+ current = @_invocations[self.class]
123
+
124
+ unless current.include?(command.name)
125
+ current << command.name
126
+ command.run(self, *args)
127
+ end
128
+ end
129
+ alias_method :invoke_task, :invoke_command
130
+
131
+ # Invoke all commands for the current instance.
132
+ def invoke_all #:nodoc:
133
+ self.class.all_commands.map { |_, command| invoke_command(command) }
134
+ end
135
+
136
+ # Invokes using shell padding.
137
+ def invoke_with_padding(*args)
138
+ with_padding { invoke(*args) }
139
+ end
140
+
141
+ protected
142
+
143
+ # Configuration values that are shared between invocations.
144
+ def _shared_configuration #:nodoc:
145
+ {:invocations => @_invocations}
146
+ end
147
+
148
+ # This method simply retrieves the class and command to be invoked.
149
+ # If the name is nil or the given name is a command in the current class,
150
+ # use the given name and return self as class. Otherwise, call
151
+ # prepare_for_invocation in the current class.
152
+ def _retrieve_class_and_command(name, sent_command = nil) #:nodoc:
153
+ if name.nil?
154
+ [self.class, nil]
155
+ elsif self.class.all_commands[name.to_s]
156
+ [self.class, name.to_s]
157
+ else
158
+ klass, command = self.class.prepare_for_invocation(nil, name)
159
+ [klass, command || sent_command]
160
+ end
161
+ end
162
+ alias_method :_retrieve_class_and_task, :_retrieve_class_and_command
163
+
164
+ # Initialize klass using values stored in the @_initializer.
165
+ def _parse_initialization_options(args, opts, config) #:nodoc:
166
+ stored_args, stored_opts, stored_config = @_initializer
167
+
168
+ args ||= stored_args.dup
169
+ opts ||= stored_opts.dup
170
+
171
+ config ||= {}
172
+ config = stored_config.merge(_shared_configuration).merge!(config)
173
+
174
+ [args, opts, config]
175
+ end
176
+ end
177
+ end