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,81 @@
1
+ require "rbconfig"
2
+
3
+ class Bundler::Thor
4
+ module Base
5
+ class << self
6
+ attr_writer :shell
7
+
8
+ # Returns the shell used in all Bundler::Thor classes. If you are in a Unix platform
9
+ # it will use a colored log, otherwise it will use a basic one without color.
10
+ #
11
+ def shell
12
+ @shell ||= if ENV["THOR_SHELL"] && !ENV["THOR_SHELL"].empty?
13
+ Bundler::Thor::Shell.const_get(ENV["THOR_SHELL"])
14
+ elsif RbConfig::CONFIG["host_os"] =~ /mswin|mingw/ && !ENV["ANSICON"]
15
+ Bundler::Thor::Shell::Basic
16
+ else
17
+ Bundler::Thor::Shell::Color
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ module Shell
24
+ SHELL_DELEGATED_METHODS = [:ask, :error, :set_color, :yes?, :no?, :say, :say_status, :print_in_columns, :print_table, :print_wrapped, :file_collision, :terminal_width]
25
+ attr_writer :shell
26
+
27
+ autoload :Basic, "bundler/vendor/thor/lib/thor/shell/basic"
28
+ autoload :Color, "bundler/vendor/thor/lib/thor/shell/color"
29
+ autoload :HTML, "bundler/vendor/thor/lib/thor/shell/html"
30
+
31
+ # Add shell to initialize config values.
32
+ #
33
+ # ==== Configuration
34
+ # shell<Object>:: An instance of the shell to be used.
35
+ #
36
+ # ==== Examples
37
+ #
38
+ # class MyScript < Bundler::Thor
39
+ # argument :first, :type => :numeric
40
+ # end
41
+ #
42
+ # MyScript.new [1.0], { :foo => :bar }, :shell => Bundler::Thor::Shell::Basic.new
43
+ #
44
+ def initialize(args = [], options = {}, config = {})
45
+ super
46
+ self.shell = config[:shell]
47
+ shell.base ||= self if shell.respond_to?(:base)
48
+ end
49
+
50
+ # Holds the shell for the given Bundler::Thor instance. If no shell is given,
51
+ # it gets a default shell from Bundler::Thor::Base.shell.
52
+ def shell
53
+ @shell ||= Bundler::Thor::Base.shell.new
54
+ end
55
+
56
+ # Common methods that are delegated to the shell.
57
+ SHELL_DELEGATED_METHODS.each do |method|
58
+ module_eval <<-METHOD, __FILE__, __LINE__ + 1
59
+ def #{method}(*args,&block)
60
+ shell.#{method}(*args,&block)
61
+ end
62
+ METHOD
63
+ end
64
+
65
+ # Yields the given block with padding.
66
+ def with_padding
67
+ shell.padding += 1
68
+ yield
69
+ ensure
70
+ shell.padding -= 1
71
+ end
72
+
73
+ protected
74
+
75
+ # Allow shell to be shared between invocations.
76
+ #
77
+ def _shared_configuration #:nodoc:
78
+ super.merge!(:shell => shell)
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,482 @@
1
+ class Bundler::Thor
2
+ module Shell
3
+ class Basic
4
+ DEFAULT_TERMINAL_WIDTH = 80
5
+
6
+ attr_accessor :base
7
+ attr_reader :padding
8
+
9
+ # Initialize base, mute and padding to nil.
10
+ #
11
+ def initialize #:nodoc:
12
+ @base = nil
13
+ @mute = false
14
+ @padding = 0
15
+ @always_force = false
16
+ end
17
+
18
+ # Mute everything that's inside given block
19
+ #
20
+ def mute
21
+ @mute = true
22
+ yield
23
+ ensure
24
+ @mute = false
25
+ end
26
+
27
+ # Check if base is muted
28
+ #
29
+ def mute?
30
+ @mute
31
+ end
32
+
33
+ # Sets the output padding, not allowing less than zero values.
34
+ #
35
+ def padding=(value)
36
+ @padding = [0, value].max
37
+ end
38
+
39
+ # Sets the output padding while executing a block and resets it.
40
+ #
41
+ def indent(count = 1)
42
+ orig_padding = padding
43
+ self.padding = padding + count
44
+ yield
45
+ self.padding = orig_padding
46
+ end
47
+
48
+ # Asks something to the user and receives a response.
49
+ #
50
+ # If a default value is specified it will be presented to the user
51
+ # and allows them to select that value with an empty response. This
52
+ # option is ignored when limited answers are supplied.
53
+ #
54
+ # If asked to limit the correct responses, you can pass in an
55
+ # array of acceptable answers. If one of those is not supplied,
56
+ # they will be shown a message stating that one of those answers
57
+ # must be given and re-asked the question.
58
+ #
59
+ # If asking for sensitive information, the :echo option can be set
60
+ # to false to mask user input from $stdin.
61
+ #
62
+ # If the required input is a path, then set the path option to
63
+ # true. This will enable tab completion for file paths relative
64
+ # to the current working directory on systems that support
65
+ # Readline.
66
+ #
67
+ # ==== Example
68
+ # ask("What is your name?")
69
+ #
70
+ # ask("What is the planet furthest from the sun?", :default => "Pluto")
71
+ #
72
+ # ask("What is your favorite Neopolitan flavor?", :limited_to => ["strawberry", "chocolate", "vanilla"])
73
+ #
74
+ # ask("What is your password?", :echo => false)
75
+ #
76
+ # ask("Where should the file be saved?", :path => true)
77
+ #
78
+ def ask(statement, *args)
79
+ options = args.last.is_a?(Hash) ? args.pop : {}
80
+ color = args.first
81
+
82
+ if options[:limited_to]
83
+ ask_filtered(statement, color, options)
84
+ else
85
+ ask_simply(statement, color, options)
86
+ end
87
+ end
88
+
89
+ # Say (print) something to the user. If the sentence ends with a whitespace
90
+ # or tab character, a new line is not appended (print + flush). Otherwise
91
+ # are passed straight to puts (behavior got from Highline).
92
+ #
93
+ # ==== Example
94
+ # say("I know you knew that.")
95
+ #
96
+ def say(message = "", color = nil, force_new_line = (message.to_s !~ /( |\t)\Z/))
97
+ buffer = prepare_message(message, *color)
98
+ buffer << "\n" if force_new_line && !message.to_s.end_with?("\n")
99
+
100
+ stdout.print(buffer)
101
+ stdout.flush
102
+ end
103
+
104
+ # Say a status with the given color and appends the message. Since this
105
+ # method is used frequently by actions, it allows nil or false to be given
106
+ # in log_status, avoiding the message from being shown. If a Symbol is
107
+ # given in log_status, it's used as the color.
108
+ #
109
+ def say_status(status, message, log_status = true)
110
+ return if quiet? || log_status == false
111
+ spaces = " " * (padding + 1)
112
+ color = log_status.is_a?(Symbol) ? log_status : :green
113
+
114
+ status = status.to_s.rjust(12)
115
+ status = set_color status, color, true if color
116
+
117
+ buffer = "#{status}#{spaces}#{message}"
118
+ buffer = "#{buffer}\n" unless buffer.end_with?("\n")
119
+
120
+ stdout.print(buffer)
121
+ stdout.flush
122
+ end
123
+
124
+ # Make a question the to user and returns true if the user replies "y" or
125
+ # "yes".
126
+ #
127
+ def yes?(statement, color = nil)
128
+ !!(ask(statement, color, :add_to_history => false) =~ is?(:yes))
129
+ end
130
+
131
+ # Make a question the to user and returns true if the user replies "n" or
132
+ # "no".
133
+ #
134
+ def no?(statement, color = nil)
135
+ !!(ask(statement, color, :add_to_history => false) =~ is?(:no))
136
+ end
137
+
138
+ # Prints values in columns
139
+ #
140
+ # ==== Parameters
141
+ # Array[String, String, ...]
142
+ #
143
+ def print_in_columns(array)
144
+ return if array.empty?
145
+ colwidth = (array.map { |el| el.to_s.size }.max || 0) + 2
146
+ array.each_with_index do |value, index|
147
+ # Don't output trailing spaces when printing the last column
148
+ if ((((index + 1) % (terminal_width / colwidth))).zero? && !index.zero?) || index + 1 == array.length
149
+ stdout.puts value
150
+ else
151
+ stdout.printf("%-#{colwidth}s", value)
152
+ end
153
+ end
154
+ end
155
+
156
+ # Prints a table.
157
+ #
158
+ # ==== Parameters
159
+ # Array[Array[String, String, ...]]
160
+ #
161
+ # ==== Options
162
+ # indent<Integer>:: Indent the first column by indent value.
163
+ # colwidth<Integer>:: Force the first column to colwidth spaces wide.
164
+ #
165
+ def print_table(array, options = {}) # rubocop:disable MethodLength
166
+ return if array.empty?
167
+
168
+ formats = []
169
+ indent = options[:indent].to_i
170
+ colwidth = options[:colwidth]
171
+ options[:truncate] = terminal_width if options[:truncate] == true
172
+
173
+ formats << "%-#{colwidth + 2}s".dup if colwidth
174
+ start = colwidth ? 1 : 0
175
+
176
+ colcount = array.max { |a, b| a.size <=> b.size }.size
177
+
178
+ maximas = []
179
+
180
+ start.upto(colcount - 1) do |index|
181
+ maxima = array.map { |row| row[index] ? row[index].to_s.size : 0 }.max
182
+ maximas << maxima
183
+ formats << if index == colcount - 1
184
+ # Don't output 2 trailing spaces when printing the last column
185
+ "%-s".dup
186
+ else
187
+ "%-#{maxima + 2}s".dup
188
+ end
189
+ end
190
+
191
+ formats[0] = formats[0].insert(0, " " * indent)
192
+ formats << "%s"
193
+
194
+ array.each do |row|
195
+ sentence = "".dup
196
+
197
+ row.each_with_index do |column, index|
198
+ maxima = maximas[index]
199
+
200
+ f = if column.is_a?(Numeric)
201
+ if index == row.size - 1
202
+ # Don't output 2 trailing spaces when printing the last column
203
+ "%#{maxima}s"
204
+ else
205
+ "%#{maxima}s "
206
+ end
207
+ else
208
+ formats[index]
209
+ end
210
+ sentence << f % column.to_s
211
+ end
212
+
213
+ sentence = truncate(sentence, options[:truncate]) if options[:truncate]
214
+ stdout.puts sentence
215
+ end
216
+ end
217
+
218
+ # Prints a long string, word-wrapping the text to the current width of the
219
+ # terminal display. Ideal for printing heredocs.
220
+ #
221
+ # ==== Parameters
222
+ # String
223
+ #
224
+ # ==== Options
225
+ # indent<Integer>:: Indent each line of the printed paragraph by indent value.
226
+ #
227
+ def print_wrapped(message, options = {})
228
+ indent = options[:indent] || 0
229
+ width = terminal_width - indent
230
+ paras = message.split("\n\n")
231
+
232
+ paras.map! do |unwrapped|
233
+ counter = 0
234
+ unwrapped.split(" ").inject do |memo, word|
235
+ word = word.gsub(/\n\005/, "\n").gsub(/\005/, "\n")
236
+ counter = 0 if word.include? "\n"
237
+ if (counter + word.length + 1) < width
238
+ memo = "#{memo} #{word}"
239
+ counter += (word.length + 1)
240
+ else
241
+ memo = "#{memo}\n#{word}"
242
+ counter = word.length
243
+ end
244
+ memo
245
+ end
246
+ end.compact!
247
+
248
+ paras.each do |para|
249
+ para.split("\n").each do |line|
250
+ stdout.puts line.insert(0, " " * indent)
251
+ end
252
+ stdout.puts unless para == paras.last
253
+ end
254
+ end
255
+
256
+ # Deals with file collision and returns true if the file should be
257
+ # overwritten and false otherwise. If a block is given, it uses the block
258
+ # response as the content for the diff.
259
+ #
260
+ # ==== Parameters
261
+ # destination<String>:: the destination file to solve conflicts
262
+ # block<Proc>:: an optional block that returns the value to be used in diff and merge
263
+ #
264
+ def file_collision(destination)
265
+ return true if @always_force
266
+ options = block_given? ? "[Ynaqdhm]" : "[Ynaqh]"
267
+
268
+ loop do
269
+ answer = ask(
270
+ %[Overwrite #{destination}? (enter "h" for help) #{options}],
271
+ :add_to_history => false
272
+ )
273
+
274
+ case answer
275
+ when nil
276
+ say ""
277
+ return true
278
+ when is?(:yes), is?(:force), ""
279
+ return true
280
+ when is?(:no), is?(:skip)
281
+ return false
282
+ when is?(:always)
283
+ return @always_force = true
284
+ when is?(:quit)
285
+ say "Aborting..."
286
+ raise SystemExit
287
+ when is?(:diff)
288
+ show_diff(destination, yield) if block_given?
289
+ say "Retrying..."
290
+ when is?(:merge)
291
+ if block_given? && !merge_tool.empty?
292
+ merge(destination, yield)
293
+ return nil
294
+ end
295
+
296
+ say "Please specify merge tool to `THOR_MERGE` env."
297
+ else
298
+ say file_collision_help
299
+ end
300
+ end
301
+ end
302
+
303
+ # This code was copied from Rake, available under MIT-LICENSE
304
+ # Copyright (c) 2003, 2004 Jim Weirich
305
+ def terminal_width
306
+ result = if ENV["THOR_COLUMNS"]
307
+ ENV["THOR_COLUMNS"].to_i
308
+ else
309
+ unix? ? dynamic_width : DEFAULT_TERMINAL_WIDTH
310
+ end
311
+ result < 10 ? DEFAULT_TERMINAL_WIDTH : result
312
+ rescue
313
+ DEFAULT_TERMINAL_WIDTH
314
+ end
315
+
316
+ # Called if something goes wrong during the execution. This is used by Bundler::Thor
317
+ # internally and should not be used inside your scripts. If something went
318
+ # wrong, you can always raise an exception. If you raise a Bundler::Thor::Error, it
319
+ # will be rescued and wrapped in the method below.
320
+ #
321
+ def error(statement)
322
+ stderr.puts statement
323
+ end
324
+
325
+ # Apply color to the given string with optional bold. Disabled in the
326
+ # Bundler::Thor::Shell::Basic class.
327
+ #
328
+ def set_color(string, *) #:nodoc:
329
+ string
330
+ end
331
+
332
+ protected
333
+
334
+ def prepare_message(message, *color)
335
+ spaces = " " * padding
336
+ spaces + set_color(message.to_s, *color)
337
+ end
338
+
339
+ def can_display_colors?
340
+ false
341
+ end
342
+
343
+ def lookup_color(color)
344
+ return color unless color.is_a?(Symbol)
345
+ self.class.const_get(color.to_s.upcase)
346
+ end
347
+
348
+ def stdout
349
+ $stdout
350
+ end
351
+
352
+ def stderr
353
+ $stderr
354
+ end
355
+
356
+ def is?(value) #:nodoc:
357
+ value = value.to_s
358
+
359
+ if value.size == 1
360
+ /\A#{value}\z/i
361
+ else
362
+ /\A(#{value}|#{value[0, 1]})\z/i
363
+ end
364
+ end
365
+
366
+ def file_collision_help #:nodoc:
367
+ <<-HELP
368
+ Y - yes, overwrite
369
+ n - no, do not overwrite
370
+ a - all, overwrite this and all others
371
+ q - quit, abort
372
+ d - diff, show the differences between the old and the new
373
+ h - help, show this help
374
+ m - merge, run merge tool
375
+ HELP
376
+ end
377
+
378
+ def show_diff(destination, content) #:nodoc:
379
+ diff_cmd = ENV["THOR_DIFF"] || ENV["RAILS_DIFF"] || "diff -u"
380
+
381
+ require "tempfile"
382
+ Tempfile.open(File.basename(destination), File.dirname(destination)) do |temp|
383
+ temp.write content
384
+ temp.rewind
385
+ system %(#{diff_cmd} "#{destination}" "#{temp.path}")
386
+ end
387
+ end
388
+
389
+ def quiet? #:nodoc:
390
+ mute? || (base && base.options[:quiet])
391
+ end
392
+
393
+ # Calculate the dynamic width of the terminal
394
+ def dynamic_width
395
+ @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput)
396
+ end
397
+
398
+ def dynamic_width_stty
399
+ `stty size 2>/dev/null`.split[1].to_i
400
+ end
401
+
402
+ def dynamic_width_tput
403
+ `tput cols 2>/dev/null`.to_i
404
+ end
405
+
406
+ def unix?
407
+ RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i
408
+ end
409
+
410
+ def truncate(string, width)
411
+ as_unicode do
412
+ chars = string.chars.to_a
413
+ if chars.length <= width
414
+ chars.join
415
+ else
416
+ chars[0, width - 3].join + "..."
417
+ end
418
+ end
419
+ end
420
+
421
+ if "".respond_to?(:encode)
422
+ def as_unicode
423
+ yield
424
+ end
425
+ else
426
+ def as_unicode
427
+ old = $KCODE
428
+ $KCODE = "U"
429
+ yield
430
+ ensure
431
+ $KCODE = old
432
+ end
433
+ end
434
+
435
+ def ask_simply(statement, color, options)
436
+ default = options[:default]
437
+ message = [statement, ("(#{default})" if default), nil].uniq.join(" ")
438
+ message = prepare_message(message, *color)
439
+ result = Bundler::Thor::LineEditor.readline(message, options)
440
+
441
+ return unless result
442
+
443
+ result = result.strip
444
+
445
+ if default && result == ""
446
+ default
447
+ else
448
+ result
449
+ end
450
+ end
451
+
452
+ def ask_filtered(statement, color, options)
453
+ answer_set = options[:limited_to]
454
+ correct_answer = nil
455
+ until correct_answer
456
+ answers = answer_set.join(", ")
457
+ answer = ask_simply("#{statement} [#{answers}]", color, options)
458
+ correct_answer = answer_set.include?(answer) ? answer : nil
459
+ say("Your response must be one of: [#{answers}]. Please try again.") unless correct_answer
460
+ end
461
+ correct_answer
462
+ end
463
+
464
+ def merge(destination, content) #:nodoc:
465
+ require "tempfile"
466
+ Tempfile.open([File.basename(destination), File.extname(destination)], File.dirname(destination)) do |temp|
467
+ temp.write content
468
+ temp.rewind
469
+ system %(#{merge_tool} "#{temp.path}" "#{destination}")
470
+ end
471
+ end
472
+
473
+ def merge_tool #:nodoc:
474
+ @merge_tool ||= ENV["THOR_MERGE"] || git_merge_tool
475
+ end
476
+
477
+ def git_merge_tool #:nodoc:
478
+ `git config merge.tool`.rstrip rescue ""
479
+ end
480
+ end
481
+ end
482
+ end