bundler 2.0.0.pre.3 → 2.1.0.pre.1

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 (217) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +721 -572
  3. data/LICENSE.md +18 -19
  4. data/README.md +9 -8
  5. data/bundler.gemspec +8 -25
  6. data/exe/bundle +19 -3
  7. data/lib/bundler.rb +121 -68
  8. data/lib/bundler/build_metadata.rb +3 -3
  9. data/lib/bundler/capistrano.rb +5 -5
  10. data/lib/bundler/cli.rb +133 -125
  11. data/lib/bundler/cli/add.rb +27 -16
  12. data/lib/bundler/cli/common.rb +11 -12
  13. data/lib/bundler/cli/config.rb +161 -86
  14. data/lib/bundler/cli/console.rb +2 -2
  15. data/lib/bundler/cli/doctor.rb +4 -4
  16. data/lib/bundler/cli/exec.rb +4 -9
  17. data/lib/bundler/cli/gem.rb +5 -5
  18. data/lib/bundler/cli/info.rb +17 -5
  19. data/lib/bundler/cli/init.rb +1 -1
  20. data/lib/bundler/cli/install.rb +12 -11
  21. data/lib/bundler/cli/issue.rb +3 -3
  22. data/lib/bundler/cli/open.rb +10 -6
  23. data/lib/bundler/cli/outdated.rb +85 -81
  24. data/lib/bundler/cli/package.rb +8 -9
  25. data/lib/bundler/cli/plugin.rb +9 -2
  26. data/lib/bundler/cli/pristine.rb +1 -1
  27. data/lib/bundler/cli/show.rb +1 -1
  28. data/lib/bundler/cli/update.rb +32 -12
  29. data/lib/bundler/compact_index_client.rb +25 -9
  30. data/lib/bundler/compact_index_client/updater.rb +2 -6
  31. data/lib/bundler/current_ruby.rb +8 -7
  32. data/lib/bundler/definition.rb +36 -27
  33. data/lib/bundler/dependency.rb +16 -4
  34. data/lib/bundler/deployment.rb +2 -2
  35. data/lib/bundler/dsl.rb +18 -42
  36. data/lib/bundler/env.rb +8 -13
  37. data/lib/bundler/environment_preserver.rb +0 -1
  38. data/lib/bundler/feature_flag.rb +1 -13
  39. data/lib/bundler/fetcher.rb +14 -11
  40. data/lib/bundler/fetcher/compact_index.rb +26 -12
  41. data/lib/bundler/fetcher/dependency.rb +1 -1
  42. data/lib/bundler/fetcher/downloader.rb +4 -1
  43. data/lib/bundler/fetcher/index.rb +4 -2
  44. data/lib/bundler/friendly_errors.rb +4 -5
  45. data/lib/bundler/gem_helper.rb +39 -24
  46. data/lib/bundler/gem_helpers.rb +2 -4
  47. data/lib/bundler/gem_tasks.rb +1 -1
  48. data/lib/bundler/gem_version_promoter.rb +3 -3
  49. data/lib/bundler/graph.rb +2 -2
  50. data/lib/bundler/injector.rb +10 -8
  51. data/lib/bundler/inline.rb +19 -18
  52. data/lib/bundler/installer.rb +7 -14
  53. data/lib/bundler/installer/gem_installer.rb +5 -1
  54. data/lib/bundler/installer/parallel_installer.rb +4 -8
  55. data/lib/bundler/installer/standalone.rb +1 -2
  56. data/lib/bundler/lazy_specification.rb +2 -2
  57. data/lib/bundler/lockfile_parser.rb +13 -21
  58. data/lib/bundler/match_platform.rb +1 -1
  59. data/lib/bundler/plugin.rb +42 -29
  60. data/lib/bundler/plugin/api.rb +1 -1
  61. data/lib/bundler/plugin/api/source.rb +2 -2
  62. data/lib/bundler/plugin/index.rb +14 -3
  63. data/lib/bundler/plugin/installer.rb +28 -15
  64. data/lib/bundler/psyched_yaml.rb +1 -1
  65. data/lib/bundler/resolver.rb +72 -24
  66. data/lib/bundler/resolver/spec_group.rb +2 -2
  67. data/lib/bundler/retry.rb +2 -2
  68. data/lib/bundler/ruby_version.rb +4 -19
  69. data/lib/bundler/rubygems_ext.rb +10 -66
  70. data/lib/bundler/rubygems_gem_installer.rb +1 -1
  71. data/lib/bundler/rubygems_integration.rb +144 -395
  72. data/lib/bundler/runtime.rb +2 -9
  73. data/lib/bundler/settings.rb +15 -48
  74. data/lib/bundler/setup.rb +6 -5
  75. data/lib/bundler/shared_helpers.rb +58 -71
  76. data/lib/bundler/similarity_detector.rb +2 -2
  77. data/lib/bundler/source.rb +5 -5
  78. data/lib/bundler/source/git.rb +19 -12
  79. data/lib/bundler/source/git/git_proxy.rb +35 -39
  80. data/lib/bundler/source/metadata.rb +7 -2
  81. data/lib/bundler/source/path.rb +13 -8
  82. data/lib/bundler/source/rubygems.rb +11 -5
  83. data/lib/bundler/source/rubygems/remote.rb +1 -2
  84. data/lib/bundler/source_list.rb +9 -12
  85. data/lib/bundler/spec_set.rb +1 -6
  86. data/lib/bundler/stub_specification.rb +18 -30
  87. data/lib/bundler/templates/Executable.bundler +23 -14
  88. data/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +3 -3
  89. data/lib/bundler/templates/newgem/Gemfile.tt +8 -0
  90. data/lib/bundler/templates/newgem/README.md.tt +4 -3
  91. data/lib/bundler/templates/newgem/newgem.gemspec.tt +6 -27
  92. data/lib/bundler/templates/newgem/test/test_helper.rb.tt +1 -1
  93. data/lib/bundler/templates/newgem/travis.yml.tt +0 -1
  94. data/lib/bundler/ui.rb +3 -3
  95. data/lib/bundler/ui/rg_proxy.rb +1 -1
  96. data/lib/bundler/ui/shell.rb +4 -8
  97. data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +161 -0
  98. data/lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb +66 -0
  99. data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +176 -0
  100. data/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +3 -0
  101. data/lib/bundler/vendor/fileutils/lib/fileutils.rb +151 -48
  102. data/lib/bundler/vendor/fileutils/lib/fileutils/version.rb +5 -0
  103. data/lib/bundler/vendor/molinillo/lib/molinillo.rb +6 -6
  104. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +2 -2
  105. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +1 -1
  106. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +1 -1
  107. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +1 -1
  108. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +1 -1
  109. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb +6 -6
  110. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb +1 -1
  111. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +1 -1
  112. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +30 -8
  113. data/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +1 -1
  114. data/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +4 -4
  115. data/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb +2 -2
  116. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +248 -279
  117. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/connection.rb +40 -0
  118. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/pool.rb +53 -0
  119. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/timed_stack_multi.rb +79 -0
  120. data/lib/bundler/vendor/thor/lib/thor.rb +1 -1
  121. data/lib/bundler/vendor/thor/lib/thor/actions.rb +21 -11
  122. data/lib/bundler/vendor/thor/lib/thor/actions/create_file.rb +1 -1
  123. data/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb +1 -1
  124. data/lib/bundler/vendor/thor/lib/thor/actions/directory.rb +1 -1
  125. data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +11 -2
  126. data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +1 -1
  127. data/lib/bundler/vendor/thor/lib/thor/base.rb +16 -17
  128. data/lib/bundler/vendor/thor/lib/thor/error.rb +82 -0
  129. data/lib/bundler/vendor/thor/lib/thor/group.rb +3 -3
  130. data/lib/bundler/vendor/thor/lib/thor/line_editor.rb +2 -2
  131. data/lib/bundler/vendor/thor/lib/thor/parser.rb +4 -4
  132. data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +7 -2
  133. data/lib/bundler/vendor/thor/lib/thor/runner.rb +6 -6
  134. data/lib/bundler/vendor/thor/lib/thor/shell.rb +4 -4
  135. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +52 -7
  136. data/lib/bundler/vendor/thor/lib/thor/shell/color.rb +1 -1
  137. data/lib/bundler/vendor/thor/lib/thor/shell/html.rb +1 -1
  138. data/lib/bundler/vendor/thor/lib/thor/util.rb +1 -1
  139. data/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  140. data/lib/bundler/vendored_fileutils.rb +1 -6
  141. data/lib/bundler/vendored_molinillo.rb +1 -1
  142. data/lib/bundler/vendored_persistent.rb +7 -5
  143. data/lib/bundler/vendored_thor.rb +2 -2
  144. data/lib/bundler/version.rb +1 -20
  145. data/lib/bundler/version_ranges.rb +51 -5
  146. data/lib/bundler/vlad.rb +3 -3
  147. data/lib/bundler/worker.rb +1 -3
  148. data/lib/bundler/yaml_serializer.rb +2 -3
  149. data/man/bundle-add.1 +10 -2
  150. data/man/bundle-add.1.txt +11 -5
  151. data/man/bundle-add.ronn +7 -1
  152. data/man/bundle-binstubs.1 +2 -2
  153. data/man/bundle-binstubs.1.txt +2 -2
  154. data/man/bundle-binstubs.ronn +1 -1
  155. data/man/bundle-check.1 +1 -1
  156. data/man/bundle-check.1.txt +6 -6
  157. data/man/bundle-clean.1 +1 -1
  158. data/man/bundle-clean.1.txt +1 -1
  159. data/man/bundle-config.1 +36 -36
  160. data/man/bundle-config.1.txt +66 -67
  161. data/man/bundle-config.ronn +42 -40
  162. data/man/bundle-doctor.1 +1 -1
  163. data/man/bundle-doctor.1.txt +1 -1
  164. data/man/bundle-exec.1 +1 -1
  165. data/man/bundle-exec.1.txt +1 -1
  166. data/man/bundle-gem.1 +1 -1
  167. data/man/bundle-gem.1.txt +3 -3
  168. data/man/bundle-info.1 +1 -1
  169. data/man/bundle-info.1.txt +1 -1
  170. data/man/bundle-init.1 +2 -2
  171. data/man/bundle-init.1.txt +2 -2
  172. data/man/bundle-init.ronn +1 -1
  173. data/man/bundle-inject.1 +1 -1
  174. data/man/bundle-inject.1.txt +1 -1
  175. data/man/bundle-install.1 +8 -5
  176. data/man/bundle-install.1.txt +56 -51
  177. data/man/bundle-install.ronn +9 -4
  178. data/man/bundle-list.1 +1 -1
  179. data/man/bundle-list.1.txt +1 -1
  180. data/man/bundle-lock.1 +1 -1
  181. data/man/bundle-lock.1.txt +16 -16
  182. data/man/bundle-open.1 +1 -1
  183. data/man/bundle-open.1.txt +1 -1
  184. data/man/bundle-outdated.1 +1 -1
  185. data/man/bundle-outdated.1.txt +1 -1
  186. data/man/bundle-package.1 +1 -1
  187. data/man/bundle-package.1.txt +1 -1
  188. data/man/bundle-platform.1 +1 -1
  189. data/man/bundle-platform.1.txt +1 -1
  190. data/man/bundle-pristine.1 +1 -1
  191. data/man/bundle-pristine.1.txt +1 -1
  192. data/man/bundle-remove.1 +1 -1
  193. data/man/bundle-remove.1.txt +1 -1
  194. data/man/bundle-show.1 +1 -1
  195. data/man/bundle-show.1.txt +1 -1
  196. data/man/bundle-update.1 +4 -4
  197. data/man/bundle-update.1.txt +64 -65
  198. data/man/bundle-update.ronn +3 -3
  199. data/man/bundle-viz.1 +1 -1
  200. data/man/bundle-viz.1.txt +1 -1
  201. data/man/bundle.1 +3 -3
  202. data/man/bundle.1.txt +8 -8
  203. data/man/bundle.ronn +2 -2
  204. data/man/gemfile.5 +13 -16
  205. data/man/gemfile.5.ronn +10 -14
  206. data/man/gemfile.5.txt +104 -108
  207. metadata +16 -102
  208. data/exe/bundle_ruby +0 -60
  209. data/lib/bundler/cli/cache.rb +0 -36
  210. data/lib/bundler/compatibility_guard.rb +0 -14
  211. data/lib/bundler/ssl_certs/.document +0 -1
  212. data/lib/bundler/ssl_certs/certificate_manager.rb +0 -66
  213. data/lib/bundler/ssl_certs/index.rubygems.org/GlobalSignRootCA.pem +0 -21
  214. data/lib/bundler/ssl_certs/rubygems.global.ssl.fastly.net/DigiCertHighAssuranceEVRootCA.pem +0 -23
  215. data/lib/bundler/ssl_certs/rubygems.org/AddTrustExternalCARoot.pem +0 -25
  216. data/lib/bundler/vendor/net-http-persistent/lib/net/http/faster.rb +0 -27
  217. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/ssl_reuse.rb +0 -129
@@ -0,0 +1,40 @@
1
+ ##
2
+ # A Net::HTTP connection wrapper that holds extra information for managing the
3
+ # connection's lifetime.
4
+
5
+ class Bundler::Persistent::Net::HTTP::Persistent::Connection # :nodoc:
6
+
7
+ attr_accessor :http
8
+
9
+ attr_accessor :last_use
10
+
11
+ attr_accessor :requests
12
+
13
+ attr_accessor :ssl_generation
14
+
15
+ def initialize http_class, http_args, ssl_generation
16
+ @http = http_class.new(*http_args)
17
+ @ssl_generation = ssl_generation
18
+
19
+ reset
20
+ end
21
+
22
+ def finish
23
+ @http.finish
24
+ rescue IOError
25
+ ensure
26
+ reset
27
+ end
28
+
29
+ def reset
30
+ @last_use = Bundler::Persistent::Net::HTTP::Persistent::EPOCH
31
+ @requests = 0
32
+ end
33
+
34
+ def ressl ssl_generation
35
+ @ssl_generation = ssl_generation
36
+
37
+ finish
38
+ end
39
+
40
+ end
@@ -0,0 +1,53 @@
1
+ class Bundler::Persistent::Net::HTTP::Persistent::Pool < Bundler::ConnectionPool # :nodoc:
2
+
3
+ attr_reader :available # :nodoc:
4
+ attr_reader :key # :nodoc:
5
+
6
+ def initialize(options = {}, &block)
7
+ super
8
+
9
+ @available = Bundler::Persistent::Net::HTTP::Persistent::TimedStackMulti.new(@size, &block)
10
+ @key = "current-#{@available.object_id}"
11
+ end
12
+
13
+ def checkin net_http_args
14
+ stack = Thread.current[@key][net_http_args] ||= []
15
+
16
+ raise Bundler::ConnectionPool::Error, 'no connections are checked out' if
17
+ stack.empty?
18
+
19
+ conn = stack.pop
20
+
21
+ if stack.empty?
22
+ @available.push conn, connection_args: net_http_args
23
+
24
+ Thread.current[@key].delete(net_http_args)
25
+ Thread.current[@key] = nil if Thread.current[@key].empty?
26
+ end
27
+
28
+ nil
29
+ end
30
+
31
+ def checkout net_http_args
32
+ stacks = Thread.current[@key] ||= {}
33
+ stack = stacks[net_http_args] ||= []
34
+
35
+ if stack.empty? then
36
+ conn = @available.pop connection_args: net_http_args
37
+ else
38
+ conn = stack.last
39
+ end
40
+
41
+ stack.push conn
42
+
43
+ conn
44
+ end
45
+
46
+ def shutdown
47
+ Thread.current[@key] = nil
48
+ super
49
+ end
50
+ end
51
+
52
+ require_relative 'timed_stack_multi'
53
+
@@ -0,0 +1,79 @@
1
+ class Bundler::Persistent::Net::HTTP::Persistent::TimedStackMulti < Bundler::ConnectionPool::TimedStack # :nodoc:
2
+
3
+ ##
4
+ # Returns a new hash that has arrays for keys
5
+ #
6
+ # Using a class method to limit the bindings referenced by the hash's
7
+ # default_proc
8
+
9
+ def self.hash_of_arrays # :nodoc:
10
+ Hash.new { |h,k| h[k] = [] }
11
+ end
12
+
13
+ def initialize(size = 0, &block)
14
+ super
15
+
16
+ @enqueued = 0
17
+ @ques = self.class.hash_of_arrays
18
+ @lru = {}
19
+ @key = :"connection_args-#{object_id}"
20
+ end
21
+
22
+ def empty?
23
+ (@created - @enqueued) >= @max
24
+ end
25
+
26
+ def length
27
+ @max - @created + @enqueued
28
+ end
29
+
30
+ private
31
+
32
+ def connection_stored? options = {} # :nodoc:
33
+ !@ques[options[:connection_args]].empty?
34
+ end
35
+
36
+ def fetch_connection options = {} # :nodoc:
37
+ connection_args = options[:connection_args]
38
+
39
+ @enqueued -= 1
40
+ lru_update connection_args
41
+ @ques[connection_args].pop
42
+ end
43
+
44
+ def lru_update connection_args # :nodoc:
45
+ @lru.delete connection_args
46
+ @lru[connection_args] = true
47
+ end
48
+
49
+ def shutdown_connections # :nodoc:
50
+ @ques.each_key do |key|
51
+ super connection_args: key
52
+ end
53
+ end
54
+
55
+ def store_connection obj, options = {} # :nodoc:
56
+ @ques[options[:connection_args]].push obj
57
+ @enqueued += 1
58
+ end
59
+
60
+ def try_create options = {} # :nodoc:
61
+ connection_args = options[:connection_args]
62
+
63
+ if @created >= @max && @enqueued >= 1
64
+ oldest, = @lru.first
65
+ @lru.delete oldest
66
+ @ques[oldest].pop
67
+
68
+ @created -= 1
69
+ end
70
+
71
+ if @created < @max
72
+ @created += 1
73
+ lru_update connection_args
74
+ return @create_block.call(connection_args)
75
+ end
76
+ end
77
+
78
+ end
79
+
@@ -1,5 +1,5 @@
1
1
  require "set"
2
- require "bundler/vendor/thor/lib/thor/base"
2
+ require_relative "thor/base"
3
3
 
4
4
  class Bundler::Thor
5
5
  class << self
@@ -1,11 +1,11 @@
1
1
  require "uri"
2
- require "bundler/vendor/thor/lib/thor/core_ext/io_binary_read"
3
- require "bundler/vendor/thor/lib/thor/actions/create_file"
4
- require "bundler/vendor/thor/lib/thor/actions/create_link"
5
- require "bundler/vendor/thor/lib/thor/actions/directory"
6
- require "bundler/vendor/thor/lib/thor/actions/empty_directory"
7
- require "bundler/vendor/thor/lib/thor/actions/file_manipulation"
8
- require "bundler/vendor/thor/lib/thor/actions/inject_into_file"
2
+ require_relative "core_ext/io_binary_read"
3
+ require_relative "actions/create_file"
4
+ require_relative "actions/create_link"
5
+ require_relative "actions/directory"
6
+ require_relative "actions/empty_directory"
7
+ require_relative "actions/file_manipulation"
8
+ require_relative "actions/inject_into_file"
9
9
 
10
10
  class Bundler::Thor
11
11
  module Actions
@@ -113,8 +113,10 @@ class Bundler::Thor
113
113
  # the script started).
114
114
  #
115
115
  def relative_to_original_destination_root(path, remove_dot = true)
116
- path = path.dup
117
- if path.gsub!(@destination_stack[0], ".")
116
+ root = @destination_stack[0]
117
+ if path.start_with?(root) && [File::SEPARATOR, File::ALT_SEPARATOR, nil, ''].include?(path[root.size..root.size])
118
+ path = path.dup
119
+ path[0...root.size] = '.'
118
120
  remove_dot ? (path[2..-1] || "") : path
119
121
  else
120
122
  path
@@ -217,6 +219,7 @@ class Bundler::Thor
217
219
  shell.padding += 1 if verbose
218
220
 
219
221
  contents = if is_uri
222
+ require "open-uri"
220
223
  open(path, "Accept" => "application/x-thor-template", &:read)
221
224
  else
222
225
  open(path, &:read)
@@ -252,9 +255,16 @@ class Bundler::Thor
252
255
 
253
256
  say_status :run, desc, config.fetch(:verbose, true)
254
257
 
255
- unless options[:pretend]
256
- config[:capture] ? `#{command}` : system(command.to_s)
258
+ return if options[:pretend]
259
+
260
+ result = config[:capture] ? `#{command}` : system(command.to_s)
261
+
262
+ if config[:abort_on_failure]
263
+ success = config[:capture] ? $?.success? : result
264
+ abort unless success
257
265
  end
266
+
267
+ result
258
268
  end
259
269
 
260
270
  # Executes a ruby script (taking into account WIN32 platform quirks).
@@ -1,4 +1,4 @@
1
- require "bundler/vendor/thor/lib/thor/actions/empty_directory"
1
+ require_relative "empty_directory"
2
2
 
3
3
  class Bundler::Thor
4
4
  module Actions
@@ -1,4 +1,4 @@
1
- require "bundler/vendor/thor/lib/thor/actions/create_file"
1
+ require_relative "create_file"
2
2
 
3
3
  class Bundler::Thor
4
4
  module Actions
@@ -1,4 +1,4 @@
1
- require "bundler/vendor/thor/lib/thor/actions/empty_directory"
1
+ require_relative "empty_directory"
2
2
 
3
3
  class Bundler::Thor
4
4
  module Actions
@@ -60,6 +60,9 @@ class Bundler::Thor
60
60
  # destination. If a block is given instead of destination, the content of
61
61
  # the url is yielded and used as location.
62
62
  #
63
+ # +get+ relies on open-uri, so passing application user input would provide
64
+ # a command injection attack vector.
65
+ #
63
66
  # ==== Parameters
64
67
  # source<String>:: the address of the given content.
65
68
  # destination<String>:: the relative path to the destination root.
@@ -117,7 +120,13 @@ class Bundler::Thor
117
120
  context = config.delete(:context) || instance_eval("binding")
118
121
 
119
122
  create_file destination, nil, config do
120
- content = CapturableERB.new(::File.binread(source), nil, "-", "@output_buffer").tap do |erb|
123
+ match = ERB.version.match(/(\d+\.\d+\.\d+)/)
124
+ capturable_erb = if match && match[1] >= "2.2.0" # Ruby 2.6+
125
+ CapturableERB.new(::File.binread(source), :trim_mode => "-", :eoutvar => "@output_buffer")
126
+ else
127
+ CapturableERB.new(::File.binread(source), nil, "-", "@output_buffer")
128
+ end
129
+ content = capturable_erb.tap do |erb|
121
130
  erb.filename = source
122
131
  end.result(context)
123
132
  content = yield(content) if block
@@ -301,7 +310,7 @@ class Bundler::Thor
301
310
  def comment_lines(path, flag, *args)
302
311
  flag = flag.respond_to?(:source) ? flag.source : flag
303
312
 
304
- gsub_file(path, /^(\s*)([^#|\n]*#{flag})/, '\1# \2', *args)
313
+ gsub_file(path, /^(\s*)([^#\n]*#{flag})/, '\1# \2', *args)
305
314
  end
306
315
 
307
316
  # Removes a file at the given location.
@@ -1,4 +1,4 @@
1
- require "bundler/vendor/thor/lib/thor/actions/empty_directory"
1
+ require_relative "empty_directory"
2
2
 
3
3
  class Bundler::Thor
4
4
  module Actions
@@ -1,17 +1,17 @@
1
- require "bundler/vendor/thor/lib/thor/command"
2
- require "bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access"
3
- require "bundler/vendor/thor/lib/thor/core_ext/ordered_hash"
4
- require "bundler/vendor/thor/lib/thor/error"
5
- require "bundler/vendor/thor/lib/thor/invocation"
6
- require "bundler/vendor/thor/lib/thor/parser"
7
- require "bundler/vendor/thor/lib/thor/shell"
8
- require "bundler/vendor/thor/lib/thor/line_editor"
9
- require "bundler/vendor/thor/lib/thor/util"
1
+ require_relative "command"
2
+ require_relative "core_ext/hash_with_indifferent_access"
3
+ require_relative "core_ext/ordered_hash"
4
+ require_relative "error"
5
+ require_relative "invocation"
6
+ require_relative "parser"
7
+ require_relative "shell"
8
+ require_relative "line_editor"
9
+ require_relative "util"
10
10
 
11
11
  class Bundler::Thor
12
- autoload :Actions, "bundler/vendor/thor/lib/thor/actions"
13
- autoload :RakeCompat, "bundler/vendor/thor/lib/thor/rake_compat"
14
- autoload :Group, "bundler/vendor/thor/lib/thor/group"
12
+ autoload :Actions, File.expand_path("actions", __dir__)
13
+ autoload :RakeCompat, File.expand_path("rake_compat", __dir__)
14
+ autoload :Group, File.expand_path("group", __dir__)
15
15
 
16
16
  # Shortcuts for help.
17
17
  HELP_MAPPINGS = %w(-h -? --help -D)
@@ -113,7 +113,7 @@ class Bundler::Thor
113
113
  end
114
114
 
115
115
  # Whenever a class inherits from Bundler::Thor or Bundler::Thor::Group, we should track the
116
- # class and the file on Bundler::Thor::Base. This is the method responsable for it.
116
+ # class and the file on Bundler::Thor::Base. This is the method responsible for it.
117
117
  #
118
118
  def register_klass_file(klass) #:nodoc:
119
119
  file = caller[1].match(/(.*):\d+/)[1]
@@ -466,13 +466,13 @@ class Bundler::Thor
466
466
  dispatch(nil, given_args.dup, nil, config)
467
467
  rescue Bundler::Thor::Error => e
468
468
  config[:debug] || ENV["THOR_DEBUG"] == "1" ? (raise e) : config[:shell].error(e.message)
469
- exit(1) if exit_on_failure?
469
+ exit(false) if exit_on_failure?
470
470
  rescue Errno::EPIPE
471
471
  # This happens if a thor command is piped to something like `head`,
472
472
  # which closes the pipe when it's done reading. This will also
473
473
  # mean that if the pipe is closed, further unnecessary
474
474
  # computation will not occur.
475
- exit(0)
475
+ exit(true)
476
476
  end
477
477
 
478
478
  # Allows to use private methods from parent in child classes as commands.
@@ -493,8 +493,7 @@ class Bundler::Thor
493
493
  alias_method :public_task, :public_command
494
494
 
495
495
  def handle_no_command_error(command, has_namespace = $thor_runner) #:nodoc:
496
- raise UndefinedCommandError, "Could not find command #{command.inspect} in #{namespace.inspect} namespace." if has_namespace
497
- raise UndefinedCommandError, "Could not find command #{command.inspect}."
496
+ raise UndefinedCommandError.new(command, all_commands.keys, (namespace if has_namespace))
498
497
  end
499
498
  alias_method :handle_no_task_error, :handle_no_command_error
500
499
 
@@ -1,4 +1,23 @@
1
1
  class Bundler::Thor
2
+ Correctable =
3
+ begin
4
+ require 'did_you_mean'
5
+
6
+ # In order to support versions of Ruby that don't have keyword
7
+ # arguments, we need our own spell checker class that doesn't take key
8
+ # words. Even though this code wouldn't be hit because of the check
9
+ # above, it's still necessary because the interpreter would otherwise be
10
+ # unable to parse the file.
11
+ class NoKwargSpellChecker < DidYouMean::SpellChecker # :nodoc:
12
+ def initialize(dictionary)
13
+ @dictionary = dictionary
14
+ end
15
+ end
16
+
17
+ DidYouMean::Correctable
18
+ rescue LoadError, NameError
19
+ end
20
+
2
21
  # Bundler::Thor::Error is raised when it's caused by wrong usage of thor classes. Those
3
22
  # errors have their backtrace suppressed and are nicely shown to the user.
4
23
  #
@@ -10,6 +29,35 @@ class Bundler::Thor
10
29
 
11
30
  # Raised when a command was not found.
12
31
  class UndefinedCommandError < Error
32
+ class SpellChecker
33
+ attr_reader :error
34
+
35
+ def initialize(error)
36
+ @error = error
37
+ end
38
+
39
+ def corrections
40
+ @corrections ||= spell_checker.correct(error.command).map(&:inspect)
41
+ end
42
+
43
+ def spell_checker
44
+ NoKwargSpellChecker.new(error.all_commands)
45
+ end
46
+ end
47
+
48
+ attr_reader :command, :all_commands
49
+
50
+ def initialize(command, all_commands, namespace)
51
+ @command = command
52
+ @all_commands = all_commands
53
+
54
+ message = "Could not find command #{command.inspect}"
55
+ message = namespace ? "#{message} in #{namespace.inspect} namespace." : "#{message}."
56
+
57
+ super(message)
58
+ end
59
+
60
+ prepend Correctable if Correctable
13
61
  end
14
62
  UndefinedTaskError = UndefinedCommandError
15
63
 
@@ -22,6 +70,33 @@ class Bundler::Thor
22
70
  end
23
71
 
24
72
  class UnknownArgumentError < Error
73
+ class SpellChecker
74
+ attr_reader :error
75
+
76
+ def initialize(error)
77
+ @error = error
78
+ end
79
+
80
+ def corrections
81
+ @corrections ||=
82
+ error.unknown.flat_map { |unknown| spell_checker.correct(unknown) }.uniq.map(&:inspect)
83
+ end
84
+
85
+ def spell_checker
86
+ @spell_checker ||= NoKwargSpellChecker.new(error.switches)
87
+ end
88
+ end
89
+
90
+ attr_reader :switches, :unknown
91
+
92
+ def initialize(switches, unknown)
93
+ @switches = switches
94
+ @unknown = unknown
95
+
96
+ super("Unknown switches #{unknown.map(&:inspect).join(', ')}")
97
+ end
98
+
99
+ prepend Correctable if Correctable
25
100
  end
26
101
 
27
102
  class RequiredArgumentMissingError < InvocationError
@@ -29,4 +104,11 @@ class Bundler::Thor
29
104
 
30
105
  class MalformattedArgumentError < InvocationError
31
106
  end
107
+
108
+ if Correctable
109
+ DidYouMean::SPELL_CHECKERS.merge!(
110
+ 'Bundler::Thor::UndefinedCommandError' => UndefinedCommandError::SpellChecker,
111
+ 'Bundler::Thor::UnknownArgumentError' => UnknownArgumentError::SpellChecker
112
+ )
113
+ end
32
114
  end