bundler 2.2.11 → 2.3.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +721 -5
  3. data/README.md +1 -1
  4. data/bundler.gemspec +8 -11
  5. data/exe/bundle +7 -8
  6. data/exe/bundler +1 -1
  7. data/lib/bundler/.document +1 -0
  8. data/lib/bundler/build_metadata.rb +3 -3
  9. data/lib/bundler/cli/cache.rb +1 -1
  10. data/lib/bundler/cli/check.rb +4 -2
  11. data/lib/bundler/cli/common.rb +17 -3
  12. data/lib/bundler/cli/config.rb +10 -1
  13. data/lib/bundler/cli/doctor.rb +24 -5
  14. data/lib/bundler/cli/exec.rb +1 -6
  15. data/lib/bundler/cli/gem.rb +130 -26
  16. data/lib/bundler/cli/info.rb +27 -6
  17. data/lib/bundler/cli/init.rb +5 -1
  18. data/lib/bundler/cli/install.rb +23 -54
  19. data/lib/bundler/cli/issue.rb +4 -3
  20. data/lib/bundler/cli/list.rb +7 -1
  21. data/lib/bundler/cli/lock.rb +5 -1
  22. data/lib/bundler/cli/open.rb +1 -2
  23. data/lib/bundler/cli/outdated.rb +22 -14
  24. data/lib/bundler/cli/platform.rb +2 -2
  25. data/lib/bundler/cli/remove.rb +1 -2
  26. data/lib/bundler/cli/show.rb +1 -1
  27. data/lib/bundler/cli/update.rb +17 -8
  28. data/lib/bundler/cli.rb +51 -63
  29. data/lib/bundler/compact_index_client/cache.rb +0 -9
  30. data/lib/bundler/compact_index_client/updater.rb +26 -14
  31. data/lib/bundler/compact_index_client.rb +2 -8
  32. data/lib/bundler/current_ruby.rb +17 -6
  33. data/lib/bundler/definition.rb +260 -362
  34. data/lib/bundler/dependency.rb +23 -71
  35. data/lib/bundler/digest.rb +71 -0
  36. data/lib/bundler/dsl.rb +72 -76
  37. data/lib/bundler/endpoint_specification.rb +19 -13
  38. data/lib/bundler/env.rb +1 -1
  39. data/lib/bundler/environment_preserver.rb +4 -1
  40. data/lib/bundler/errors.rb +29 -3
  41. data/lib/bundler/feature_flag.rb +0 -5
  42. data/lib/bundler/fetcher/base.rb +6 -8
  43. data/lib/bundler/fetcher/compact_index.rb +10 -15
  44. data/lib/bundler/fetcher/downloader.rb +9 -6
  45. data/lib/bundler/fetcher/index.rb +0 -27
  46. data/lib/bundler/fetcher.rb +22 -23
  47. data/lib/bundler/friendly_errors.rb +26 -36
  48. data/lib/bundler/gem_helper.rb +21 -16
  49. data/lib/bundler/gem_helpers.rb +9 -2
  50. data/lib/bundler/gem_version_promoter.rb +14 -25
  51. data/lib/bundler/index.rb +11 -46
  52. data/lib/bundler/injector.rb +18 -4
  53. data/lib/bundler/inline.rb +4 -13
  54. data/lib/bundler/installer/gem_installer.rb +16 -21
  55. data/lib/bundler/installer/parallel_installer.rb +36 -15
  56. data/lib/bundler/installer/standalone.rb +42 -10
  57. data/lib/bundler/installer.rb +25 -41
  58. data/lib/bundler/lazy_specification.rb +52 -30
  59. data/lib/bundler/lockfile_generator.rb +2 -2
  60. data/lib/bundler/lockfile_parser.rb +18 -43
  61. data/lib/bundler/man/bundle-add.1 +21 -5
  62. data/lib/bundler/man/bundle-add.1.ronn +16 -4
  63. data/lib/bundler/man/bundle-binstubs.1 +1 -1
  64. data/lib/bundler/man/bundle-cache.1 +7 -1
  65. data/lib/bundler/man/bundle-cache.1.ronn +7 -0
  66. data/lib/bundler/man/bundle-check.1 +1 -1
  67. data/lib/bundler/man/bundle-clean.1 +2 -2
  68. data/lib/bundler/man/bundle-clean.1.ronn +1 -1
  69. data/lib/bundler/man/bundle-config.1 +49 -22
  70. data/lib/bundler/man/bundle-config.1.ronn +49 -30
  71. data/lib/bundler/man/bundle-console.1 +53 -0
  72. data/lib/bundler/man/bundle-console.1.ronn +44 -0
  73. data/lib/bundler/man/bundle-doctor.1 +1 -1
  74. data/lib/bundler/man/bundle-exec.1 +2 -2
  75. data/lib/bundler/man/bundle-exec.1.ronn +1 -1
  76. data/lib/bundler/man/bundle-gem.1 +14 -1
  77. data/lib/bundler/man/bundle-gem.1.ronn +16 -0
  78. data/lib/bundler/man/bundle-help.1 +13 -0
  79. data/lib/bundler/man/bundle-help.1.ronn +12 -0
  80. data/lib/bundler/man/bundle-info.1 +1 -1
  81. data/lib/bundler/man/bundle-init.1 +1 -1
  82. data/lib/bundler/man/bundle-inject.1 +5 -2
  83. data/lib/bundler/man/bundle-inject.1.ronn +3 -1
  84. data/lib/bundler/man/bundle-install.1 +6 -2
  85. data/lib/bundler/man/bundle-install.1.ronn +8 -2
  86. data/lib/bundler/man/bundle-list.1 +1 -1
  87. data/lib/bundler/man/bundle-lock.1 +1 -1
  88. data/lib/bundler/man/bundle-open.1 +1 -1
  89. data/lib/bundler/man/bundle-outdated.1 +3 -10
  90. data/lib/bundler/man/bundle-outdated.1.ronn +1 -10
  91. data/lib/bundler/man/bundle-platform.1 +16 -6
  92. data/lib/bundler/man/bundle-platform.1.ronn +14 -7
  93. data/lib/bundler/man/bundle-plugin.1 +81 -0
  94. data/lib/bundler/man/bundle-plugin.1.ronn +59 -0
  95. data/lib/bundler/man/bundle-pristine.1 +1 -1
  96. data/lib/bundler/man/bundle-remove.1 +1 -1
  97. data/lib/bundler/man/bundle-show.1 +1 -1
  98. data/lib/bundler/man/bundle-update.1 +5 -5
  99. data/lib/bundler/man/bundle-update.1.ronn +5 -4
  100. data/lib/bundler/man/bundle-version.1 +35 -0
  101. data/lib/bundler/man/bundle-version.1.ronn +24 -0
  102. data/lib/bundler/man/bundle-viz.1 +4 -1
  103. data/lib/bundler/man/bundle-viz.1.ronn +2 -0
  104. data/lib/bundler/man/bundle.1 +15 -10
  105. data/lib/bundler/man/bundle.1.ronn +12 -7
  106. data/lib/bundler/man/gemfile.5 +117 -80
  107. data/lib/bundler/man/gemfile.5.ronn +105 -84
  108. data/lib/bundler/man/index.txt +4 -0
  109. data/lib/bundler/match_metadata.rb +13 -0
  110. data/lib/bundler/match_platform.rb +0 -1
  111. data/lib/bundler/match_remote_metadata.rb +29 -0
  112. data/lib/bundler/plugin/api/source.rb +24 -8
  113. data/lib/bundler/plugin/index.rb +4 -1
  114. data/lib/bundler/plugin/installer/git.rb +0 -4
  115. data/lib/bundler/plugin/installer/rubygems.rb +0 -4
  116. data/lib/bundler/plugin/installer.rb +10 -10
  117. data/lib/bundler/plugin/source_list.rb +4 -0
  118. data/lib/bundler/plugin.rb +30 -8
  119. data/lib/bundler/process_lock.rb +1 -1
  120. data/lib/bundler/remote_specification.rb +10 -4
  121. data/lib/bundler/resolver/base.rb +50 -0
  122. data/lib/bundler/resolver/spec_group.rb +31 -73
  123. data/lib/bundler/resolver.rb +193 -292
  124. data/lib/bundler/retry.rb +1 -1
  125. data/lib/bundler/ruby_dsl.rb +1 -1
  126. data/lib/bundler/ruby_version.rb +5 -18
  127. data/lib/bundler/rubygems_ext.rb +160 -26
  128. data/lib/bundler/rubygems_gem_installer.rb +86 -9
  129. data/lib/bundler/rubygems_integration.rb +46 -93
  130. data/lib/bundler/runtime.rb +18 -12
  131. data/lib/bundler/self_manager.rb +168 -0
  132. data/lib/bundler/settings.rb +98 -22
  133. data/lib/bundler/setup.rb +2 -2
  134. data/lib/bundler/shared_helpers.rb +15 -31
  135. data/lib/bundler/source/git/git_proxy.rb +8 -6
  136. data/lib/bundler/source/git.rb +29 -13
  137. data/lib/bundler/source/metadata.rb +3 -7
  138. data/lib/bundler/source/path/installer.rb +1 -1
  139. data/lib/bundler/source/path.rb +3 -1
  140. data/lib/bundler/source/rubygems.rb +199 -182
  141. data/lib/bundler/source/rubygems_aggregate.rb +68 -0
  142. data/lib/bundler/source.rb +24 -4
  143. data/lib/bundler/source_list.rb +104 -60
  144. data/lib/bundler/source_map.rb +71 -0
  145. data/lib/bundler/spec_set.rb +58 -52
  146. data/lib/bundler/stub_specification.rb +13 -3
  147. data/lib/bundler/templates/Executable +2 -4
  148. data/lib/bundler/templates/Executable.bundler +8 -8
  149. data/lib/bundler/templates/Executable.standalone +2 -4
  150. data/lib/bundler/templates/Gemfile +0 -2
  151. data/lib/bundler/templates/gems.rb +0 -3
  152. data/lib/bundler/templates/newgem/Gemfile.tt +5 -2
  153. data/lib/bundler/templates/newgem/README.md.tt +8 -12
  154. data/lib/bundler/templates/newgem/Rakefile.tt +15 -2
  155. data/lib/bundler/templates/newgem/github/workflows/main.yml.tt +16 -7
  156. data/lib/bundler/templates/newgem/gitlab-ci.yml.tt +5 -4
  157. data/lib/bundler/templates/newgem/newgem.gemspec.tt +19 -17
  158. data/lib/bundler/templates/newgem/sig/newgem.rbs.tt +8 -0
  159. data/lib/bundler/templates/newgem/standard.yml.tt +3 -0
  160. data/lib/bundler/templates/newgem/test/minitest/{newgem_test.rb.tt → test_newgem.rb.tt} +1 -1
  161. data/lib/bundler/ui/shell.rb +1 -1
  162. data/lib/bundler/vendor/.document +1 -0
  163. data/lib/bundler/vendor/connection_pool/LICENSE +20 -0
  164. data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +19 -21
  165. data/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +1 -1
  166. data/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +57 -0
  167. data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +39 -74
  168. data/lib/bundler/vendor/fileutils/LICENSE.txt +22 -0
  169. data/lib/bundler/vendor/molinillo/LICENSE +9 -0
  170. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +3 -3
  171. data/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +32 -26
  172. data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +1 -1
  173. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +1 -1
  174. data/lib/bundler/vendor/net-http-persistent/README.rdoc +82 -0
  175. data/lib/bundler/vendor/thor/LICENSE.md +20 -0
  176. data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +5 -5
  177. data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +1 -2
  178. data/lib/bundler/vendor/thor/lib/thor/actions.rb +6 -2
  179. data/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +6 -0
  180. data/lib/bundler/vendor/thor/lib/thor/error.rb +9 -4
  181. data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +19 -1
  182. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +22 -4
  183. data/lib/bundler/vendor/thor/lib/thor/shell.rb +1 -1
  184. data/lib/bundler/vendor/thor/lib/thor/util.rb +1 -1
  185. data/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  186. data/lib/bundler/vendor/tmpdir/lib/tmpdir.rb +1 -1
  187. data/lib/bundler/vendor/tsort/LICENSE.txt +22 -0
  188. data/lib/bundler/vendor/tsort/lib/tsort.rb +452 -0
  189. data/lib/bundler/vendor/uri/LICENSE.txt +22 -0
  190. data/lib/bundler/vendor/uri/lib/uri/common.rb +17 -80
  191. data/lib/bundler/vendor/uri/lib/uri/ftp.rb +0 -1
  192. data/lib/bundler/vendor/uri/lib/uri/generic.rb +5 -6
  193. data/lib/bundler/vendor/uri/lib/uri/http.rb +0 -1
  194. data/lib/bundler/vendor/uri/lib/uri/https.rb +0 -1
  195. data/lib/bundler/vendor/uri/lib/uri/ldap.rb +1 -1
  196. data/lib/bundler/vendor/uri/lib/uri/mailto.rb +0 -1
  197. data/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +1 -14
  198. data/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb +1 -12
  199. data/lib/bundler/vendor/uri/lib/uri/version.rb +1 -1
  200. data/lib/bundler/vendor/uri/lib/uri/ws.rb +84 -0
  201. data/lib/bundler/vendor/uri/lib/uri/wss.rb +22 -0
  202. data/lib/bundler/vendor/uri/lib/uri.rb +0 -1
  203. data/lib/bundler/vendored_tsort.rb +4 -0
  204. data/lib/bundler/version.rb +1 -1
  205. data/lib/bundler/worker.rb +19 -4
  206. data/lib/bundler.rb +46 -39
  207. metadata +39 -12
  208. data/lib/bundler/dep_proxy.rb +0 -55
  209. data/lib/bundler/gemdeps.rb +0 -29
  210. data/lib/bundler/psyched_yaml.rb +0 -22
  211. data/lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb +0 -66
data/lib/bundler/index.rb CHANGED
@@ -56,45 +56,21 @@ module Bundler
56
56
 
57
57
  # Search this index's specs, and any source indexes that this index knows
58
58
  # about, returning all of the results.
59
- def search(query, base = nil)
60
- sort_specs(unsorted_search(query, base))
61
- end
62
-
63
- def unsorted_search(query, base)
64
- results = local_search(query, base)
65
-
66
- seen = results.map(&:full_name).uniq unless @sources.empty?
59
+ def search(query)
60
+ results = local_search(query)
61
+ return results unless @sources.any?
67
62
 
68
63
  @sources.each do |source|
69
- source.unsorted_search(query, base).each do |spec|
70
- next if seen.include?(spec.full_name)
71
-
72
- seen << spec.full_name
73
- results << spec
74
- end
64
+ results.concat(source.search(query))
75
65
  end
76
-
77
- results
78
- end
79
- protected :unsorted_search
80
-
81
- def self.sort_specs(specs)
82
- specs.sort_by do |s|
83
- platform_string = s.platform.to_s
84
- [s.version, platform_string == RUBY ? NULL : platform_string]
85
- end
86
- end
87
-
88
- def sort_specs(specs)
89
- self.class.sort_specs(specs)
66
+ results.uniq(&:full_name)
90
67
  end
91
68
 
92
- def local_search(query, base = nil)
69
+ def local_search(query)
93
70
  case query
94
71
  when Gem::Specification, RemoteSpecification, LazySpecification, EndpointSpecification then search_by_spec(query)
95
72
  when String then specs_by_name(query)
96
- when Gem::Dependency then search_by_dependency(query, base)
97
- when DepProxy then search_by_dependency(query.dep, base)
73
+ when Gem::Dependency then search_by_dependency(query)
98
74
  else
99
75
  raise "You can't search for a #{query.inspect}."
100
76
  end
@@ -122,10 +98,9 @@ module Bundler
122
98
  names
123
99
  end
124
100
 
125
- # returns a list of the dependencies
126
101
  def unmet_dependency_names
127
102
  dependency_names.select do |name|
128
- name != "bundler" && search(name).empty?
103
+ search(name).empty?
129
104
  end
130
105
  end
131
106
 
@@ -186,22 +161,12 @@ module Bundler
186
161
  @specs[name].values
187
162
  end
188
163
 
189
- def search_by_dependency(dependency, base = nil)
190
- @cache[base || false] ||= {}
191
- @cache[base || false][dependency] ||= begin
164
+ def search_by_dependency(dependency)
165
+ @cache[dependency] ||= begin
192
166
  specs = specs_by_name(dependency.name)
193
- specs += base if base
194
167
  found = specs.select do |spec|
195
168
  next true if spec.source.is_a?(Source::Gemspec)
196
- if base # allow all platforms when searching from a lockfile
197
- dependency.matches_spec?(spec)
198
- else
199
- if Gem::Platform.respond_to? :match_spec?
200
- dependency.matches_spec?(spec) && Gem::Platform.match_spec?(spec)
201
- else
202
- dependency.matches_spec?(spec) && Gem::Platform.match(spec.platform)
203
- end
204
- end
169
+ dependency.matches_spec?(spec)
205
170
  end
206
171
 
207
172
  found
@@ -70,8 +70,12 @@ module Bundler
70
70
 
71
71
  show_warning("No gems were removed from the gemfile.") if deps.empty?
72
72
 
73
- deps.each {|dep| Bundler.ui.confirm "#{SharedHelpers.pretty_dependency(dep, false)} was removed." }
73
+ deps.each {|dep| Bundler.ui.confirm "#{SharedHelpers.pretty_dependency(dep)} was removed." }
74
74
  end
75
+
76
+ # Invalidate the cached Bundler.definition.
77
+ # This prevents e.g. `bundle remove ...` from using outdated information.
78
+ Bundler.reset_paths!
75
79
  end
76
80
 
77
81
  private
@@ -111,10 +115,14 @@ module Bundler
111
115
  end
112
116
 
113
117
  source = ", :source => \"#{d.source}\"" unless d.source.nil?
118
+ path = ", :path => \"#{d.path}\"" unless d.path.nil?
114
119
  git = ", :git => \"#{d.git}\"" unless d.git.nil?
120
+ github = ", :github => \"#{d.github}\"" unless d.github.nil?
115
121
  branch = ", :branch => \"#{d.branch}\"" unless d.branch.nil?
122
+ ref = ", :ref => \"#{d.ref}\"" unless d.ref.nil?
123
+ require_path = ", :require => #{convert_autorequire(d.autorequire)}" unless d.autorequire.nil?
116
124
 
117
- %(gem #{name}#{requirement}#{group}#{source}#{git}#{branch})
125
+ %(gem #{name}#{requirement}#{group}#{source}#{path}#{git}#{github}#{branch}#{ref}#{require_path})
118
126
  end.join("\n")
119
127
  end
120
128
 
@@ -128,7 +136,7 @@ module Bundler
128
136
  # evaluates a gemfile to remove the specified gem
129
137
  # from it.
130
138
  def remove_deps(gemfile_path)
131
- initial_gemfile = IO.readlines(gemfile_path)
139
+ initial_gemfile = File.readlines(gemfile_path)
132
140
 
133
141
  Bundler.ui.info "Removing gems from #{gemfile_path}"
134
142
 
@@ -181,7 +189,7 @@ module Bundler
181
189
  patterns = /gem\s+(['"])#{Regexp.union(gems)}\1|gem\s*\((['"])#{Regexp.union(gems)}\2\)/
182
190
  new_gemfile = []
183
191
  multiline_removal = false
184
- IO.readlines(gemfile_path).each do |line|
192
+ File.readlines(gemfile_path).each do |line|
185
193
  match_data = line.match(patterns)
186
194
  if match_data && is_not_within_comment?(line, match_data)
187
195
  multiline_removal = line.rstrip.end_with?(",")
@@ -269,5 +277,11 @@ module Bundler
269
277
  def show_warning(message)
270
278
  Bundler.ui.info Bundler.ui.add_color(message, :yellow)
271
279
  end
280
+
281
+ def convert_autorequire(autorequire)
282
+ autorequire = autorequire.first
283
+ return autorequire if autorequire == "false"
284
+ autorequire.inspect
285
+ end
272
286
  end
273
287
  end
@@ -38,27 +38,23 @@ def gemfile(install = false, options = {}, &gemfile)
38
38
  raise ArgumentError, "Unknown options: #{opts.keys.join(", ")}" unless opts.empty?
39
39
 
40
40
  begin
41
- old_root = Bundler.method(:root)
42
- bundler_module = class << Bundler; self; end
43
- bundler_module.send(:remove_method, :root)
44
- def Bundler.root
45
- Bundler::SharedHelpers.pwd.expand_path
46
- end
41
+ Bundler.instance_variable_set(:@bundle_path, Pathname.new(Gem.dir))
47
42
  old_gemfile = ENV["BUNDLE_GEMFILE"]
48
43
  Bundler::SharedHelpers.set_env "BUNDLE_GEMFILE", "Gemfile"
49
44
 
50
45
  Bundler::Plugin.gemfile_install(&gemfile) if Bundler.feature_flag.plugins?
51
46
  builder = Bundler::Dsl.new
52
47
  builder.instance_eval(&gemfile)
48
+ builder.check_primary_source_safety
53
49
 
54
- Bundler.settings.temporary(:frozen => false) do
50
+ Bundler.settings.temporary(:deployment => false, :frozen => false) do
55
51
  definition = builder.to_definition(nil, true)
56
52
  def definition.lock(*); end
57
53
  definition.validate_runtime!
58
54
 
59
55
  Bundler.ui = install ? ui : Bundler::UI::Silent.new
60
56
  if install || definition.missing_specs?
61
- Bundler.settings.temporary(:inline => true) do
57
+ Bundler.settings.temporary(:inline => true, :no_install => false) do
62
58
  installer = Bundler::Installer.install(Bundler.root, definition, :system => true)
63
59
  installer.post_install_messages.each do |name, message|
64
60
  Bundler.ui.info "Post-install message from #{name}:\n#{message}"
@@ -70,11 +66,6 @@ def gemfile(install = false, options = {}, &gemfile)
70
66
  runtime.setup.require
71
67
  end
72
68
  ensure
73
- if bundler_module
74
- bundler_module.send(:remove_method, :root)
75
- bundler_module.send(:define_method, :root, old_root)
76
- end
77
-
78
69
  if old_gemfile
79
70
  ENV["BUNDLE_GEMFILE"] = old_gemfile
80
71
  else
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "shellwords"
4
-
5
3
  module Bundler
6
4
  class GemInstaller
7
5
  attr_reader :spec, :standalone, :worker, :force, :installer
@@ -15,7 +13,7 @@ module Bundler
15
13
  end
16
14
 
17
15
  def install_from_spec
18
- post_install_message = spec_settings ? install_with_settings : install
16
+ post_install_message = install
19
17
  Bundler.ui.debug "#{worker}: #{spec.name} (#{spec.version}) from #{spec.loaded_from}"
20
18
  generate_executable_stubs
21
19
  return true, post_install_message
@@ -31,45 +29,42 @@ module Bundler
31
29
 
32
30
  def specific_failure_message(e)
33
31
  message = "#{e.class}: #{e.message}\n"
34
- message += " " + e.backtrace.join("\n ") + "\n\n" if Bundler.ui.debug?
32
+ message += " " + e.backtrace.join("\n ") + "\n\n"
35
33
  message = message.lines.first + Bundler.ui.add_color(message.lines.drop(1).join, :clear)
36
34
  message + Bundler.ui.add_color(failure_message, :red)
37
35
  end
38
36
 
39
37
  def failure_message
40
- return install_error_message if spec.source.options["git"]
41
- "#{install_error_message}\n#{gem_install_message}"
38
+ install_error_message
42
39
  end
43
40
 
44
41
  def install_error_message
45
42
  "An error occurred while installing #{spec.name} (#{spec.version}), and Bundler cannot continue."
46
43
  end
47
44
 
48
- def gem_install_message
49
- source = spec.source
50
- return unless source.respond_to?(:remotes)
51
-
52
- if source.remotes.size == 1
53
- "Make sure that `gem install #{spec.name} -v '#{spec.version}' --source '#{source.remotes.first}'` succeeds before bundling."
54
- else
55
- "Make sure that `gem install #{spec.name} -v '#{spec.version}'` succeeds before bundling."
56
- end
57
- end
58
-
59
45
  def spec_settings
60
46
  # Fetch the build settings, if there are any
61
47
  if settings = Bundler.settings["build.#{spec.name}"]
48
+ require "shellwords"
62
49
  Shellwords.shellsplit(settings)
63
50
  end
64
51
  end
65
52
 
66
53
  def install
67
- spec.source.install(spec, :force => force, :ensure_builtin_gems_cached => standalone, :build_args => Array(spec_settings))
54
+ spec.source.install(
55
+ spec,
56
+ :force => force,
57
+ :ensure_builtin_gems_cached => standalone,
58
+ :build_args => Array(spec_settings),
59
+ :previous_spec => previous_spec,
60
+ )
68
61
  end
69
62
 
70
- def install_with_settings
71
- # Build arguments are global, so this is mutexed
72
- Bundler.rubygems.install_with_build_args([spec_settings]) { install }
63
+ def previous_spec
64
+ locked_gems = installer.definition.locked_gems
65
+ return unless locked_gems
66
+
67
+ locked_gems.specs.find {|s| s.name == spec.name }
73
68
  end
74
69
 
75
70
  def out_of_space_message
@@ -6,10 +6,11 @@ require_relative "gem_installer"
6
6
  module Bundler
7
7
  class ParallelInstaller
8
8
  class SpecInstallation
9
- attr_accessor :spec, :name, :post_install_message, :state, :error
9
+ attr_accessor :spec, :name, :full_name, :post_install_message, :state, :error
10
10
  def initialize(spec)
11
11
  @spec = spec
12
12
  @name = spec.name
13
+ @full_name = spec.full_name
13
14
  @state = :none
14
15
  @post_install_message = ""
15
16
  @error = nil
@@ -27,13 +28,8 @@ module Bundler
27
28
  state == :failed
28
29
  end
29
30
 
30
- def installation_attempted?
31
- installed? || failed?
32
- end
33
-
34
- # Only true when spec in neither installed nor already enqueued
35
31
  def ready_to_enqueue?
36
- !enqueued? && !installation_attempted?
32
+ state == :none
37
33
  end
38
34
 
39
35
  def has_post_install_message?
@@ -54,14 +50,11 @@ module Bundler
54
50
  # Represents only the non-development dependencies, the ones that are
55
51
  # itself and are in the total list.
56
52
  def dependencies
57
- @dependencies ||= begin
58
- all_dependencies.reject {|dep| ignorable_dependency? dep }
59
- end
53
+ @dependencies ||= all_dependencies.reject {|dep| ignorable_dependency? dep }
60
54
  end
61
55
 
62
56
  def missing_lockfile_dependencies(all_spec_names)
63
- deps = all_dependencies.reject {|dep| ignorable_dependency? dep }
64
- deps.reject {|dep| all_spec_names.include? dep.name }
57
+ dependencies.reject {|dep| all_spec_names.include? dep.name }
65
58
  end
66
59
 
67
60
  # Represents all dependencies
@@ -70,7 +63,7 @@ module Bundler
70
63
  end
71
64
 
72
65
  def to_s
73
- "#<#{self.class} #{@spec.full_name} (#{state})>"
66
+ "#<#{self.class} #{full_name} (#{state})>"
74
67
  end
75
68
  end
76
69
 
@@ -93,18 +86,48 @@ module Bundler
93
86
  def call
94
87
  check_for_corrupt_lockfile
95
88
 
89
+ if @rake
90
+ do_install(@rake, 0)
91
+ Gem::Specification.reset
92
+ end
93
+
96
94
  if @size > 1
97
95
  install_with_worker
98
96
  else
99
97
  install_serially
100
98
  end
101
99
 
100
+ check_for_unmet_dependencies
101
+
102
102
  handle_error if failed_specs.any?
103
103
  @specs
104
104
  ensure
105
105
  worker_pool && worker_pool.stop
106
106
  end
107
107
 
108
+ def check_for_unmet_dependencies
109
+ unmet_dependencies = @specs.map do |s|
110
+ [
111
+ s,
112
+ s.dependencies.reject {|dep| @specs.any? {|spec| dep.matches_spec?(spec.spec) } },
113
+ ]
114
+ end.reject {|a| a.last.empty? }
115
+ return if unmet_dependencies.empty?
116
+
117
+ warning = []
118
+ warning << "Your lockfile doesn't include a valid resolution."
119
+ warning << "You can fix this by regenerating your lockfile or trying to manually editing the bad locked gems to a version that satisfies all dependencies."
120
+ warning << "The unmet dependencies are:"
121
+
122
+ unmet_dependencies.each do |spec, unmet_spec_dependencies|
123
+ unmet_spec_dependencies.each do |unmet_spec_dependency|
124
+ warning << "* #{unmet_spec_dependency}, depended upon #{spec.full_name}, unsatisfied by #{@specs.find {|s| s.name == unmet_spec_dependency.name && !unmet_spec_dependency.matches_spec?(s.spec) }.full_name}"
125
+ end
126
+ end
127
+
128
+ Bundler.ui.warn(warning.join("\n"))
129
+ end
130
+
108
131
  def check_for_corrupt_lockfile
109
132
  missing_dependencies = @specs.map do |s|
110
133
  [
@@ -217,8 +240,6 @@ module Bundler
217
240
  # are installed.
218
241
  def enqueue_specs
219
242
  @specs.select(&:ready_to_enqueue?).each do |spec|
220
- next if @rake && !@rake.installed? && spec.name != @rake.name
221
-
222
243
  if spec.dependencies_installed? @specs
223
244
  spec.state = :enqueued
224
245
  worker_pool.enq spec
@@ -3,7 +3,7 @@
3
3
  module Bundler
4
4
  class Standalone
5
5
  def initialize(groups, definition)
6
- @specs = groups.empty? ? definition.requested_specs : definition.specs_for(groups.map(&:to_sym))
6
+ @specs = definition.specs_for(groups)
7
7
  end
8
8
 
9
9
  def generate
@@ -12,12 +12,14 @@ module Bundler
12
12
  end
13
13
  File.open File.join(bundler_path, "setup.rb"), "w" do |file|
14
14
  file.puts "require 'rbconfig'"
15
- file.puts "ruby_engine = RUBY_ENGINE"
16
- file.puts "ruby_version = RbConfig::CONFIG[\"ruby_version\"]"
17
- file.puts "path = File.expand_path('..', __FILE__)"
15
+ file.puts define_path_helpers
18
16
  file.puts reverse_rubygems_kernel_mixin
19
17
  paths.each do |path|
20
- file.puts %($:.unshift File.expand_path("\#{path}/#{path}"))
18
+ if Pathname.new(path).absolute?
19
+ file.puts %($:.unshift "#{path}")
20
+ else
21
+ file.puts %($:.unshift File.expand_path("\#{__dir__}/#{path}"))
22
+ end
21
23
  end
22
24
  end
23
25
  end
@@ -28,28 +30,58 @@ module Bundler
28
30
  @specs.map do |spec|
29
31
  next if spec.name == "bundler"
30
32
  Array(spec.require_paths).map do |path|
31
- gem_path(path, spec).sub(version_dir, '#{ruby_engine}/#{ruby_version}')
33
+ gem_path(path, spec).
34
+ sub(version_dir, '#{RUBY_ENGINE}/#{Gem.ruby_api_version}').
35
+ sub(extensions_dir, 'extensions/\k<platform>/#{Gem.extension_api_version}')
32
36
  # This is a static string intentionally. It's interpolated at a later time.
33
37
  end
34
- end.flatten
38
+ end.flatten.compact
35
39
  end
36
40
 
37
41
  def version_dir
38
- "#{Bundler::RubyVersion.system.engine}/#{RbConfig::CONFIG["ruby_version"]}"
42
+ "#{RUBY_ENGINE}/#{Gem.ruby_api_version}"
43
+ end
44
+
45
+ def extensions_dir
46
+ %r{extensions/(?<platform>[^/]+)/#{Regexp.escape(Gem.extension_api_version)}}
39
47
  end
40
48
 
41
49
  def bundler_path
42
- Bundler.root.join(Bundler.settings[:path], "bundler")
50
+ Bundler.root.join(Bundler.settings[:path].to_s, "bundler")
43
51
  end
44
52
 
45
53
  def gem_path(path, spec)
46
54
  full_path = Pathname.new(path).absolute? ? path : File.join(spec.full_gem_path, path)
47
- Pathname.new(full_path).relative_path_from(Bundler.root.join(bundler_path)).to_s
55
+ if spec.source.instance_of?(Source::Path)
56
+ full_path
57
+ else
58
+ Pathname.new(full_path).relative_path_from(Bundler.root.join(bundler_path)).to_s
59
+ end
48
60
  rescue TypeError
49
61
  error_message = "#{spec.name} #{spec.version} has an invalid gemspec"
50
62
  raise Gem::InvalidSpecificationException.new(error_message)
51
63
  end
52
64
 
65
+ def define_path_helpers
66
+ <<~'END'
67
+ unless defined?(Gem)
68
+ module Gem
69
+ def self.ruby_api_version
70
+ RbConfig::CONFIG["ruby_version"]
71
+ end
72
+
73
+ def self.extension_api_version
74
+ if 'no' == RbConfig::CONFIG['ENABLE_SHARED']
75
+ "#{ruby_api_version}-static"
76
+ else
77
+ ruby_api_version
78
+ end
79
+ end
80
+ end
81
+ end
82
+ END
83
+ end
84
+
53
85
  def reverse_rubygems_kernel_mixin
54
86
  <<~END
55
87
  kernel = (class << ::Kernel; self; end)
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "rubygems/dependency_installer"
4
3
  require_relative "worker"
5
4
  require_relative "installer/parallel_installer"
6
5
  require_relative "installer/standalone"
@@ -14,7 +13,7 @@ module Bundler
14
13
  Installer.ambiguous_gems = []
15
14
  end
16
15
 
17
- attr_reader :post_install_messages
16
+ attr_reader :post_install_messages, :definition
18
17
 
19
18
  # Begins the installation process for Bundler.
20
19
  # For more information see the #run method on this class.
@@ -67,7 +66,7 @@ module Bundler
67
66
  # require paths and save them in a `setup.rb` file. See `bundle standalone --help` for more
68
67
  # information.
69
68
  def run(options)
70
- create_bundle_path
69
+ Bundler.create_bundle_path
71
70
 
72
71
  ProcessLock.lock do
73
72
  if Bundler.frozen_bundle?
@@ -89,6 +88,8 @@ module Bundler
89
88
  end
90
89
  install(options)
91
90
 
91
+ Gem::Specification.reset # invalidate gem specification cache so that installed gems are immediately available
92
+
92
93
  lock unless Bundler.frozen_bundle?
93
94
  Standalone.new(options[:standalone], @definition).generate if options[:standalone]
94
95
  end
@@ -118,7 +119,7 @@ module Bundler
118
119
  relative_gemfile_path = relative_gemfile_path
119
120
  ruby_command = Thor::Util.ruby_command
120
121
  ruby_command = ruby_command
121
- template_path = File.expand_path("../templates/Executable", __FILE__)
122
+ template_path = File.expand_path("templates/Executable", __dir__)
122
123
  if spec.name == "bundler"
123
124
  template_path += ".bundler"
124
125
  spec.executables = %(bundle)
@@ -133,7 +134,7 @@ module Bundler
133
134
  next
134
135
  end
135
136
 
136
- mode = Bundler::WINDOWS ? "wb:UTF-8" : "w"
137
+ mode = Gem.win_platform? ? "wb:UTF-8" : "w"
137
138
  require "erb"
138
139
  content = if RUBY_VERSION >= "2.6"
139
140
  ERB.new(template, :trim_mode => "-").result(binding)
@@ -142,7 +143,7 @@ module Bundler
142
143
  end
143
144
 
144
145
  File.write(binstub_path, content, :mode => mode, :perm => 0o777 & ~File.umask)
145
- if Bundler::WINDOWS || options[:all_platforms]
146
+ if Gem.win_platform? || options[:all_platforms]
146
147
  prefix = "@ruby -x \"%~f0\" %*\n@exit /b %ERRORLEVEL%\n\n"
147
148
  File.write("#{binstub_path}.cmd", prefix + content, :mode => mode)
148
149
  end
@@ -171,7 +172,7 @@ module Bundler
171
172
  end
172
173
  standalone_path = Bundler.root.join(path).relative_path_from(bin_path)
173
174
  standalone_path = standalone_path
174
- template = File.read(File.expand_path("../templates/Executable.standalone", __FILE__))
175
+ template = File.read(File.expand_path("templates/Executable.standalone", __dir__))
175
176
  ruby_command = Thor::Util.ruby_command
176
177
  ruby_command = ruby_command
177
178
 
@@ -180,7 +181,7 @@ module Bundler
180
181
  executable_path = Pathname(spec.full_gem_path).join(spec.bindir, executable).relative_path_from(bin_path)
181
182
  executable_path = executable_path
182
183
 
183
- mode = Bundler::WINDOWS ? "wb:UTF-8" : "w"
184
+ mode = Gem.win_platform? ? "wb:UTF-8" : "w"
184
185
  require "erb"
185
186
  content = if RUBY_VERSION >= "2.6"
186
187
  ERB.new(template, :trim_mode => "-").result(binding)
@@ -189,7 +190,7 @@ module Bundler
189
190
  end
190
191
 
191
192
  File.write("#{bin_path}/#{executable}", content, :mode => mode, :perm => 0o755)
192
- if Bundler::WINDOWS || options[:all_platforms]
193
+ if Gem.win_platform? || options[:all_platforms]
193
194
  prefix = "@ruby -x \"%~f0\" %*\n@exit /b %ERRORLEVEL%\n\n"
194
195
  File.write("#{bin_path}/#{executable}.cmd", prefix + content, :mode => mode)
195
196
  end
@@ -217,17 +218,7 @@ module Bundler
217
218
  return jobs
218
219
  end
219
220
 
220
- # Parallelization has some issues on Windows, so it's not yet the default
221
- return 1 if Gem.win_platform?
222
-
223
- processor_count
224
- end
225
-
226
- def processor_count
227
- require "etc"
228
- Etc.nprocessors
229
- rescue StandardError
230
- 1
221
+ Bundler.settings.processor_count
231
222
  end
232
223
 
233
224
  def load_plugins
@@ -247,19 +238,14 @@ module Bundler
247
238
  end
248
239
 
249
240
  def ensure_specs_are_compatible!
250
- system_ruby = Bundler::RubyVersion.system
251
- rubygems_version = Gem::Version.create(Gem::VERSION)
252
241
  @definition.specs.each do |spec|
253
- if required_ruby_version = spec.required_ruby_version
254
- unless required_ruby_version.satisfied_by?(system_ruby.gem_version)
255
- raise InstallError, "#{spec.full_name} requires ruby version #{required_ruby_version}, " \
256
- "which is incompatible with the current version, #{system_ruby}"
257
- end
242
+ unless spec.matches_current_ruby?
243
+ raise InstallError, "#{spec.full_name} requires ruby version #{spec.required_ruby_version}, " \
244
+ "which is incompatible with the current version, #{Gem.ruby_version}"
258
245
  end
259
- next unless required_rubygems_version = spec.required_rubygems_version
260
- unless required_rubygems_version.satisfied_by?(rubygems_version)
261
- raise InstallError, "#{spec.full_name} requires rubygems version #{required_rubygems_version}, " \
262
- "which is incompatible with the current version, #{rubygems_version}"
246
+ unless spec.matches_current_rubygems?
247
+ raise InstallError, "#{spec.full_name} requires rubygems version #{spec.required_rubygems_version}, " \
248
+ "which is incompatible with the current version, #{Gem.rubygems_version}"
263
249
  end
264
250
  end
265
251
  end
@@ -271,22 +257,20 @@ module Bundler
271
257
  end
272
258
  end
273
259
 
274
- def create_bundle_path
275
- SharedHelpers.filesystem_access(Bundler.bundle_path.to_s) do |p|
276
- Bundler.mkdir_p(p)
277
- end unless Bundler.bundle_path.exist?
278
- rescue Errno::EEXIST
279
- raise PathError, "Could not install to path `#{Bundler.bundle_path}` " \
280
- "because a file already exists at that path. Either remove or rename the file so the directory can be created."
281
- end
282
-
283
260
  # returns whether or not a re-resolve was needed
284
261
  def resolve_if_needed(options)
285
262
  if !@definition.unlocking? && !options["force"] && !Bundler.settings[:inline] && Bundler.default_lockfile.file?
286
263
  return false if @definition.nothing_changed? && !@definition.missing_specs?
287
264
  end
288
265
 
289
- options["local"] ? @definition.resolve_with_cache! : @definition.resolve_remotely!
266
+ if options["local"]
267
+ @definition.resolve_with_cache!
268
+ elsif options["prefer-local"]
269
+ @definition.resolve_prefering_local!
270
+ else
271
+ @definition.resolve_remotely!
272
+ end
273
+
290
274
  true
291
275
  end
292
276