bundler 2.1.4 → 2.2.18

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 (227) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1790 -1430
  3. data/README.md +6 -8
  4. data/bundler.gemspec +5 -6
  5. data/exe/bundle +3 -0
  6. data/lib/bundler/build_metadata.rb +3 -11
  7. data/lib/bundler/cli/add.rb +1 -1
  8. data/lib/bundler/cli/binstubs.rb +6 -2
  9. data/lib/bundler/cli/cache.rb +2 -7
  10. data/lib/bundler/cli/clean.rb +1 -1
  11. data/lib/bundler/cli/common.rb +29 -2
  12. data/lib/bundler/cli/console.rb +1 -1
  13. data/lib/bundler/cli/doctor.rb +1 -1
  14. data/lib/bundler/cli/exec.rb +4 -4
  15. data/lib/bundler/cli/fund.rb +36 -0
  16. data/lib/bundler/cli/gem.rb +129 -28
  17. data/lib/bundler/cli/info.rb +15 -4
  18. data/lib/bundler/cli/init.rb +2 -2
  19. data/lib/bundler/cli/inject.rb +1 -1
  20. data/lib/bundler/cli/install.rb +13 -11
  21. data/lib/bundler/cli/issue.rb +2 -2
  22. data/lib/bundler/cli/list.rb +12 -10
  23. data/lib/bundler/cli/outdated.rb +94 -76
  24. data/lib/bundler/cli/plugin.rb +10 -0
  25. data/lib/bundler/cli/pristine.rb +5 -0
  26. data/lib/bundler/cli/show.rb +1 -1
  27. data/lib/bundler/cli/update.rb +3 -1
  28. data/lib/bundler/cli.rb +72 -56
  29. data/lib/bundler/compact_index_client/cache.rb +6 -14
  30. data/lib/bundler/compact_index_client/gem_parser.rb +28 -0
  31. data/lib/bundler/compact_index_client/updater.rb +13 -17
  32. data/lib/bundler/compact_index_client.rb +1 -1
  33. data/lib/bundler/current_ruby.rb +1 -0
  34. data/lib/bundler/definition.rb +117 -188
  35. data/lib/bundler/dep_proxy.rb +16 -9
  36. data/lib/bundler/dependency.rb +3 -10
  37. data/lib/bundler/dsl.rb +40 -33
  38. data/lib/bundler/endpoint_specification.rb +1 -1
  39. data/lib/bundler/env.rb +1 -1
  40. data/lib/bundler/environment_preserver.rb +26 -2
  41. data/lib/bundler/errors.rb +1 -0
  42. data/lib/bundler/feature_flag.rb +0 -6
  43. data/lib/bundler/fetcher/base.rb +1 -1
  44. data/lib/bundler/fetcher/compact_index.rb +1 -1
  45. data/lib/bundler/fetcher/downloader.rb +9 -5
  46. data/lib/bundler/fetcher/index.rb +3 -4
  47. data/lib/bundler/fetcher.rb +5 -4
  48. data/lib/bundler/friendly_errors.rb +22 -13
  49. data/lib/bundler/gem_helper.rb +51 -18
  50. data/lib/bundler/gem_helpers.rb +36 -25
  51. data/lib/bundler/gem_version_promoter.rb +4 -4
  52. data/lib/bundler/graph.rb +1 -1
  53. data/lib/bundler/index.rb +13 -9
  54. data/lib/bundler/injector.rb +23 -5
  55. data/lib/bundler/inline.rb +3 -2
  56. data/lib/bundler/installer/gem_installer.rb +3 -3
  57. data/lib/bundler/installer/parallel_installer.rb +46 -25
  58. data/lib/bundler/installer/standalone.rb +17 -2
  59. data/lib/bundler/installer.rb +37 -49
  60. data/lib/bundler/lazy_specification.rb +45 -25
  61. data/lib/bundler/lockfile_generator.rb +1 -1
  62. data/lib/bundler/lockfile_parser.rb +4 -14
  63. data/lib/bundler/man/.document +1 -0
  64. data/{man → lib/bundler/man}/bundle-add.1 +1 -1
  65. data/{man/bundle-add.ronn → lib/bundler/man/bundle-add.1.ronn} +0 -0
  66. data/{man → lib/bundler/man}/bundle-binstubs.1 +5 -3
  67. data/{man/bundle-binstubs.ronn → lib/bundler/man/bundle-binstubs.1.ronn} +2 -4
  68. data/{man → lib/bundler/man}/bundle-cache.1 +1 -1
  69. data/{man/bundle-cache.ronn → lib/bundler/man/bundle-cache.1.ronn} +0 -0
  70. data/{man → lib/bundler/man}/bundle-check.1 +1 -1
  71. data/{man/bundle-check.ronn → lib/bundler/man/bundle-check.1.ronn} +0 -0
  72. data/{man → lib/bundler/man}/bundle-clean.1 +1 -1
  73. data/{man/bundle-clean.ronn → lib/bundler/man/bundle-clean.1.ronn} +0 -0
  74. data/{man → lib/bundler/man}/bundle-config.1 +40 -38
  75. data/{man/bundle-config.ronn → lib/bundler/man/bundle-config.1.ronn} +50 -50
  76. data/{man → lib/bundler/man}/bundle-doctor.1 +1 -1
  77. data/{man/bundle-doctor.ronn → lib/bundler/man/bundle-doctor.1.ronn} +0 -0
  78. data/{man → lib/bundler/man}/bundle-exec.1 +1 -1
  79. data/{man/bundle-exec.ronn → lib/bundler/man/bundle-exec.1.ronn} +0 -0
  80. data/{man → lib/bundler/man}/bundle-gem.1 +25 -3
  81. data/{man/bundle-gem.ronn → lib/bundler/man/bundle-gem.1.ronn} +30 -7
  82. data/{man → lib/bundler/man}/bundle-info.1 +1 -1
  83. data/{man/bundle-info.ronn → lib/bundler/man/bundle-info.1.ronn} +0 -0
  84. data/{man → lib/bundler/man}/bundle-init.1 +1 -1
  85. data/{man/bundle-init.ronn → lib/bundler/man/bundle-init.1.ronn} +0 -0
  86. data/{man → lib/bundler/man}/bundle-inject.1 +1 -1
  87. data/{man/bundle-inject.ronn → lib/bundler/man/bundle-inject.1.ronn} +0 -0
  88. data/{man → lib/bundler/man}/bundle-install.1 +30 -3
  89. data/{man/bundle-install.ronn → lib/bundler/man/bundle-install.1.ronn} +25 -3
  90. data/{man → lib/bundler/man}/bundle-list.1 +7 -7
  91. data/{man/bundle-list.ronn → lib/bundler/man/bundle-list.1.ronn} +6 -6
  92. data/{man → lib/bundler/man}/bundle-lock.1 +1 -1
  93. data/{man/bundle-lock.ronn → lib/bundler/man/bundle-lock.1.ronn} +0 -0
  94. data/{man → lib/bundler/man}/bundle-open.1 +1 -1
  95. data/{man/bundle-open.ronn → lib/bundler/man/bundle-open.1.ronn} +0 -0
  96. data/{man → lib/bundler/man}/bundle-outdated.1 +1 -1
  97. data/{man/bundle-outdated.ronn → lib/bundler/man/bundle-outdated.1.ronn} +0 -0
  98. data/{man → lib/bundler/man}/bundle-platform.1 +1 -1
  99. data/{man/bundle-platform.ronn → lib/bundler/man/bundle-platform.1.ronn} +0 -0
  100. data/{man → lib/bundler/man}/bundle-pristine.1 +1 -1
  101. data/{man/bundle-pristine.ronn → lib/bundler/man/bundle-pristine.1.ronn} +0 -0
  102. data/{man → lib/bundler/man}/bundle-remove.1 +1 -1
  103. data/{man/bundle-remove.ronn → lib/bundler/man/bundle-remove.1.ronn} +0 -0
  104. data/{man → lib/bundler/man}/bundle-show.1 +1 -1
  105. data/{man/bundle-show.ronn → lib/bundler/man/bundle-show.1.ronn} +0 -0
  106. data/{man → lib/bundler/man}/bundle-update.1 +1 -1
  107. data/{man/bundle-update.ronn → lib/bundler/man/bundle-update.1.ronn} +0 -0
  108. data/{man → lib/bundler/man}/bundle-viz.1 +1 -1
  109. data/{man/bundle-viz.ronn → lib/bundler/man/bundle-viz.1.ronn} +0 -0
  110. data/{man → lib/bundler/man}/bundle.1 +1 -1
  111. data/{man/bundle.ronn → lib/bundler/man/bundle.1.ronn} +0 -0
  112. data/{man → lib/bundler/man}/gemfile.5 +4 -4
  113. data/{man → lib/bundler/man}/gemfile.5.ronn +4 -4
  114. data/{man → lib/bundler/man}/index.txt +0 -0
  115. data/lib/bundler/mirror.rb +2 -2
  116. data/lib/bundler/plugin/api/source.rb +22 -1
  117. data/lib/bundler/plugin/dsl.rb +1 -1
  118. data/lib/bundler/plugin/index.rb +10 -1
  119. data/lib/bundler/plugin/installer/rubygems.rb +1 -1
  120. data/lib/bundler/plugin/installer.rb +9 -11
  121. data/lib/bundler/plugin/source_list.rb +5 -1
  122. data/lib/bundler/plugin.rb +33 -7
  123. data/lib/bundler/psyched_yaml.rb +0 -15
  124. data/lib/bundler/remote_specification.rb +5 -2
  125. data/lib/bundler/resolver/spec_group.rb +56 -53
  126. data/lib/bundler/resolver.rb +88 -115
  127. data/lib/bundler/retry.rb +2 -2
  128. data/lib/bundler/ruby_version.rb +1 -1
  129. data/lib/bundler/rubygems_ext.rb +71 -11
  130. data/lib/bundler/rubygems_gem_installer.rb +50 -9
  131. data/lib/bundler/rubygems_integration.rb +25 -60
  132. data/lib/bundler/runtime.rb +4 -14
  133. data/lib/bundler/settings.rb +107 -55
  134. data/lib/bundler/shared_helpers.rb +3 -3
  135. data/lib/bundler/similarity_detector.rb +1 -1
  136. data/lib/bundler/source/git/git_proxy.rb +82 -80
  137. data/lib/bundler/source/git.rb +24 -22
  138. data/lib/bundler/source/metadata.rb +0 -4
  139. data/lib/bundler/source/path/installer.rb +10 -10
  140. data/lib/bundler/source/path.rb +10 -4
  141. data/lib/bundler/source/rubygems/remote.rb +1 -1
  142. data/lib/bundler/source/rubygems.rb +60 -28
  143. data/lib/bundler/source/rubygems_aggregate.rb +64 -0
  144. data/lib/bundler/source.rb +16 -1
  145. data/lib/bundler/source_list.rb +52 -28
  146. data/lib/bundler/source_map.rb +58 -0
  147. data/lib/bundler/spec_set.rb +29 -17
  148. data/lib/bundler/stub_specification.rb +25 -7
  149. data/lib/bundler/templates/Gemfile +1 -1
  150. data/lib/bundler/templates/gems.rb +1 -1
  151. data/lib/bundler/templates/newgem/CHANGELOG.md.tt +5 -0
  152. data/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +57 -47
  153. data/lib/bundler/templates/newgem/Gemfile.tt +9 -1
  154. data/lib/bundler/templates/newgem/README.md.tt +6 -5
  155. data/lib/bundler/templates/newgem/Rakefile.tt +19 -5
  156. data/lib/bundler/templates/newgem/bin/console.tt +1 -0
  157. data/lib/bundler/templates/newgem/circleci/config.yml.tt +13 -0
  158. data/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt +2 -0
  159. data/lib/bundler/templates/newgem/github/workflows/main.yml.tt +16 -0
  160. data/lib/bundler/templates/newgem/gitlab-ci.yml.tt +9 -0
  161. data/lib/bundler/templates/newgem/lib/newgem/version.rb.tt +2 -0
  162. data/lib/bundler/templates/newgem/lib/newgem.rb.tt +4 -2
  163. data/lib/bundler/templates/newgem/newgem.gemspec.tt +15 -7
  164. data/lib/bundler/templates/newgem/rubocop.yml.tt +13 -0
  165. data/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +2 -0
  166. data/lib/bundler/templates/newgem/spec/spec_helper.rb.tt +2 -1
  167. data/lib/bundler/templates/newgem/test/{newgem_test.rb.tt → minitest/newgem_test.rb.tt} +2 -0
  168. data/lib/bundler/templates/newgem/test/{test_helper.rb.tt → minitest/test_helper.rb.tt} +2 -0
  169. data/lib/bundler/templates/newgem/test/test-unit/newgem_test.rb.tt +15 -0
  170. data/lib/bundler/templates/newgem/test/test-unit/test_helper.rb.tt +6 -0
  171. data/lib/bundler/ui/shell.rb +5 -5
  172. data/lib/bundler/uri_credentials_filter.rb +3 -1
  173. data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb +7 -0
  174. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +2 -2
  175. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +11 -5
  176. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +34 -2
  177. data/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +3 -3
  178. data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +1 -1
  179. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +12 -1
  180. data/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +49 -47
  181. data/lib/bundler/vendor/molinillo/lib/molinillo.rb +0 -1
  182. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +82 -189
  183. data/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb +2 -1
  184. data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +4 -2
  185. data/lib/bundler/vendor/thor/lib/thor/actions.rb +1 -1
  186. data/lib/bundler/vendor/thor/lib/thor/base.rb +9 -0
  187. data/lib/bundler/vendor/thor/lib/thor/error.rb +1 -1
  188. data/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb +5 -1
  189. data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +9 -8
  190. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +5 -2
  191. data/lib/bundler/vendor/thor/lib/thor/shell/color.rb +5 -1
  192. data/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  193. data/lib/bundler/vendor/thor/lib/thor.rb +5 -13
  194. data/lib/bundler/vendor/tmpdir/lib/tmpdir.rb +154 -0
  195. data/lib/bundler/vendored_persistent.rb +0 -7
  196. data/lib/bundler/vendored_tmpdir.rb +4 -0
  197. data/lib/bundler/version.rb +1 -1
  198. data/lib/bundler/worker.rb +1 -1
  199. data/lib/bundler/yaml_serializer.rb +1 -1
  200. data/lib/bundler.rb +34 -9
  201. metadata +77 -86
  202. data/lib/bundler/vendor/molinillo/lib/molinillo/compatibility.rb +0 -26
  203. data/man/bundle-add.1.txt +0 -58
  204. data/man/bundle-binstubs.1.txt +0 -48
  205. data/man/bundle-cache.1.txt +0 -78
  206. data/man/bundle-check.1.txt +0 -33
  207. data/man/bundle-clean.1.txt +0 -26
  208. data/man/bundle-config.1.txt +0 -528
  209. data/man/bundle-doctor.1.txt +0 -44
  210. data/man/bundle-exec.1.txt +0 -178
  211. data/man/bundle-gem.1.txt +0 -91
  212. data/man/bundle-info.1.txt +0 -21
  213. data/man/bundle-init.1.txt +0 -34
  214. data/man/bundle-inject.1.txt +0 -32
  215. data/man/bundle-install.1.txt +0 -401
  216. data/man/bundle-list.1.txt +0 -43
  217. data/man/bundle-lock.1.txt +0 -93
  218. data/man/bundle-open.1.txt +0 -29
  219. data/man/bundle-outdated.1.txt +0 -131
  220. data/man/bundle-platform.1.txt +0 -57
  221. data/man/bundle-pristine.1.txt +0 -44
  222. data/man/bundle-remove.1.txt +0 -34
  223. data/man/bundle-show.1.txt +0 -27
  224. data/man/bundle-update.1.txt +0 -390
  225. data/man/bundle-viz.1.txt +0 -39
  226. data/man/bundle.1.txt +0 -116
  227. data/man/gemfile.5.txt +0 -649
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "lockfile_parser"
4
- require "set"
5
4
 
6
5
  module Bundler
7
6
  class Definition
@@ -77,6 +76,7 @@ module Bundler
77
76
  @locked_bundler_version = nil
78
77
  @locked_ruby_version = nil
79
78
  @locked_specs_incomplete_for_platform = false
79
+ @new_platform = nil
80
80
 
81
81
  if lockfile && File.exist?(lockfile)
82
82
  @lockfile_contents = Bundler.read_file(lockfile)
@@ -106,6 +106,17 @@ module Bundler
106
106
  @locked_platforms = []
107
107
  end
108
108
 
109
+ @locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
110
+ @disable_multisource = @locked_gem_sources.all?(&:disable_multisource?)
111
+
112
+ unless @disable_multisource
113
+ msg = "Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. You should run `bundle update` or generate your lockfile from scratch."
114
+
115
+ Bundler::SharedHelpers.major_deprecation 2, msg
116
+
117
+ @sources.merged_gem_lockfile_sections!
118
+ end
119
+
109
120
  @unlock[:gems] ||= []
110
121
  @unlock[:sources] ||= []
111
122
  @unlock[:ruby] ||= if @ruby_version && locked_ruby_version_object
@@ -113,7 +124,7 @@ module Bundler
113
124
  end
114
125
  @unlocking ||= @unlock[:ruby] ||= (!@locked_ruby_version ^ !@ruby_version)
115
126
 
116
- add_current_platform unless Bundler.frozen_bundle?
127
+ add_current_platform unless current_ruby_platform_locked? || Bundler.frozen_bundle?
117
128
 
118
129
  converge_path_sources_to_gemspec_sources
119
130
  @path_changes = converge_paths
@@ -145,17 +156,19 @@ module Bundler
145
156
  end
146
157
  end
147
158
 
159
+ def disable_multisource?
160
+ @disable_multisource
161
+ end
162
+
148
163
  def resolve_with_cache!
149
- raise "Specs already loaded" if @specs
150
164
  sources.cached!
151
- specs
165
+ resolve
152
166
  end
153
167
 
154
168
  def resolve_remotely!
155
- raise "Specs already loaded" if @specs
156
169
  @remote = true
157
170
  sources.remote!
158
- specs
171
+ resolve
159
172
  end
160
173
 
161
174
  # For given dependency list returns a SpecSet with Gemspec of all the required
@@ -172,10 +185,10 @@ module Bundler
172
185
  gem_name, gem_version = extract_gem_info(e)
173
186
  locked_gem = @locked_specs[gem_name].last
174
187
  raise if locked_gem.nil? || locked_gem.version.to_s != gem_version || !@remote
175
- raise GemNotFound, "Your bundle is locked to #{locked_gem}, but that version could not " \
176
- "be found in any of the sources listed in your Gemfile. If you haven't changed sources, " \
177
- "that means the author of #{locked_gem} has removed it. You'll need to update your bundle " \
178
- "to a version other than #{locked_gem} that hasn't been removed in order to install."
188
+ raise GemNotFound, "Your bundle is locked to #{locked_gem} from #{locked_gem.source}, but that version can " \
189
+ "no longer be found in that source. That means the author of #{locked_gem} has removed it. " \
190
+ "You'll need to update your bundle to a version other than #{locked_gem} that hasn't been " \
191
+ "removed in order to install."
179
192
  end
180
193
  unless specs["bundler"].any?
181
194
  bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last
@@ -194,10 +207,6 @@ module Bundler
194
207
  @locked_specs - specs
195
208
  end
196
209
 
197
- def new_platform?
198
- @new_platform
199
- end
200
-
201
210
  def missing_specs
202
211
  missing = []
203
212
  resolve.materialize(requested_dependencies, missing)
@@ -210,7 +219,6 @@ module Bundler
210
219
  Bundler.ui.debug "The definition is missing #{missing.map(&:full_name)}"
211
220
  true
212
221
  rescue BundlerError => e
213
- @index = nil
214
222
  @resolve = nil
215
223
  @specs = nil
216
224
  @gem_version_promoter = nil
@@ -227,16 +235,29 @@ module Bundler
227
235
  end
228
236
  end
229
237
 
238
+ def requested_dependencies
239
+ groups = requested_groups
240
+ groups.map!(&:to_sym)
241
+ dependencies_for(groups)
242
+ end
243
+
230
244
  def current_dependencies
231
- dependencies.select(&:should_include?)
245
+ dependencies.select do |d|
246
+ d.should_include? && !d.gem_platforms(@platforms).empty?
247
+ end
232
248
  end
233
249
 
234
250
  def specs_for(groups)
235
- deps = dependencies.select {|d| (d.groups & groups).any? }
236
- deps.delete_if {|d| !d.should_include? }
251
+ deps = dependencies_for(groups)
237
252
  specs.for(expand_dependencies(deps))
238
253
  end
239
254
 
255
+ def dependencies_for(groups)
256
+ current_dependencies.reject do |d|
257
+ (d.groups & groups).empty?
258
+ end
259
+ end
260
+
240
261
  # Resolve all the dependencies specified in Gemfile. It ensures that
241
262
  # dependencies that have been already resolved via locked file and are fresh
242
263
  # are reused when resolving dependencies
@@ -245,77 +266,25 @@ module Bundler
245
266
  def resolve
246
267
  @resolve ||= begin
247
268
  last_resolve = converge_locked_specs
248
- resolve =
249
- if Bundler.frozen_bundle?
250
- Bundler.ui.debug "Frozen, using resolution from the lockfile"
251
- last_resolve
252
- elsif !unlocking? && nothing_changed?
253
- Bundler.ui.debug("Found no changes, using resolution from the lockfile")
254
- last_resolve
255
- else
256
- # Run a resolve against the locally available gems
257
- Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}")
258
- last_resolve.merge Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
259
- end
260
-
261
- # filter out gems that _can_ be installed on multiple platforms, but don't need
262
- # to be
263
- resolve.for(expand_dependencies(dependencies, true), [], false, false, false)
264
- end
265
- end
266
-
267
- def index
268
- @index ||= Index.build do |idx|
269
- dependency_names = @dependencies.map(&:name)
270
-
271
- sources.all_sources.each do |source|
272
- source.dependency_names = dependency_names - pinned_spec_names(source)
273
- idx.add_source source.specs
274
- dependency_names.concat(source.unmet_deps).uniq!
275
- end
276
-
277
- double_check_for_index(idx, dependency_names)
278
- end
279
- end
280
-
281
- # Suppose the gem Foo depends on the gem Bar. Foo exists in Source A. Bar has some versions that exist in both
282
- # sources A and B. At this point, the API request will have found all the versions of Bar in source A,
283
- # but will not have found any versions of Bar from source B, which is a problem if the requested version
284
- # of Foo specifically depends on a version of Bar that is only found in source B. This ensures that for
285
- # each spec we found, we add all possible versions from all sources to the index.
286
- def double_check_for_index(idx, dependency_names)
287
- pinned_names = pinned_spec_names
288
- loop do
289
- idxcount = idx.size
290
-
291
- names = :names # do this so we only have to traverse to get dependency_names from the index once
292
- unmet_dependency_names = lambda do
293
- return names unless names == :names
294
- new_names = sources.all_sources.map(&:dependency_names_to_double_check)
295
- return names = nil if new_names.compact!
296
- names = new_names.flatten(1).concat(dependency_names)
297
- names.uniq!
298
- names -= pinned_names
299
- names
300
- end
301
-
302
- sources.all_sources.each do |source|
303
- source.double_check_for(unmet_dependency_names)
269
+ if Bundler.frozen_bundle?
270
+ Bundler.ui.debug "Frozen, using resolution from the lockfile"
271
+ last_resolve
272
+ elsif !unlocking? && nothing_changed?
273
+ Bundler.ui.debug("Found no changes, using resolution from the lockfile")
274
+ last_resolve
275
+ else
276
+ # Run a resolve against the locally available gems
277
+ Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}")
278
+ expanded_dependencies = expand_dependencies(dependencies + metadata_dependencies, @remote)
279
+ Resolver.resolve(expanded_dependencies, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
304
280
  end
305
-
306
- break if idxcount == idx.size
307
281
  end
308
282
  end
309
- private :double_check_for_index
310
283
 
311
284
  def has_rubygems_remotes?
312
285
  sources.rubygems_sources.any? {|s| s.remotes.any? }
313
286
  end
314
287
 
315
- def has_local_dependencies?
316
- !sources.path_sources.empty? || !sources.git_sources.empty?
317
- end
318
-
319
288
  def spec_git_paths
320
289
  sources.git_sources.map {|s| File.realpath(s.path) if File.exist?(s.path) }.compact
321
290
  end
@@ -396,12 +365,10 @@ module Bundler
396
365
  "updated #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} to version control."
397
366
 
398
367
  unless explicit_flag
399
- suggested_command = if Bundler.settings.locations("frozen")[:global]
368
+ suggested_command = if Bundler.settings.locations("frozen").keys.&([:global, :local]).any?
400
369
  "bundle config unset frozen"
401
370
  elsif Bundler.settings.locations("deployment").keys.&([:global, :local]).any?
402
371
  "bundle config unset deployment"
403
- else
404
- "bundle install --no-deployment"
405
372
  end
406
373
  msg << "\n\nIf this is a development machine, remove the #{Bundler.default_gemfile} " \
407
374
  "freeze \nby running `#{suggested_command}`."
@@ -450,9 +417,9 @@ module Bundler
450
417
  @locked_deps.each {|name, d| both_sources[name][1] = d.source }
451
418
 
452
419
  both_sources.each do |name, (dep, lock_source)|
453
- next unless (dep.nil? && !lock_source.nil?) || (!dep.nil? && !lock_source.nil? && !lock_source.can_lock?(dep))
420
+ next if lock_source.nil? || (dep && lock_source.can_lock?(dep))
454
421
  gemfile_source_name = (dep && dep.source) || "no specified source"
455
- lockfile_source_name = lock_source || "no specified source"
422
+ lockfile_source_name = lock_source
456
423
  changed << "* #{name} from `#{gemfile_source_name}` to `#{lockfile_source_name}`"
457
424
  end
458
425
 
@@ -497,15 +464,11 @@ module Bundler
497
464
  end
498
465
 
499
466
  def validate_platforms!
500
- return if @platforms.any? do |bundle_platform|
501
- Bundler.rubygems.platforms.any? do |local_platform|
502
- MatchPlatform.platforms_match?(bundle_platform, local_platform)
503
- end
504
- end
467
+ return if current_platform_locked?
505
468
 
506
469
  raise ProductionError, "Your bundle only supports platforms #{@platforms.map(&:to_s)} " \
507
- "but your local platforms are #{Bundler.rubygems.platforms.map(&:to_s)}, and " \
508
- "there's no compatible match between those two lists."
470
+ "but your local platform is #{Bundler.local_platform}. " \
471
+ "Add the current platform to the lockfile with `bundle lock --add-platform #{Bundler.local_platform}` and try again."
509
472
  end
510
473
 
511
474
  def add_platform(platform)
@@ -518,21 +481,18 @@ module Bundler
518
481
  raise InvalidOption, "Unable to remove the platform `#{platform}` since the only platforms are #{@platforms.join ", "}"
519
482
  end
520
483
 
521
- def add_current_platform
522
- current_platforms.each {|platform| add_platform(platform) }
523
- end
524
-
525
- def find_resolved_spec(current_spec)
526
- specs.find_by_name_and_platform(current_spec.name, current_spec.platform)
527
- end
528
-
529
- def find_indexed_specs(current_spec)
530
- index[current_spec.name].select {|spec| spec.match_platform(current_spec.platform) }.sort_by(&:version)
484
+ def most_specific_locked_platform
485
+ @platforms.min_by do |bundle_platform|
486
+ platform_specificity_match(bundle_platform, local_platform)
487
+ end
531
488
  end
532
489
 
533
490
  attr_reader :sources
534
491
  private :sources
535
492
 
493
+ attr_reader :locked_gem_sources
494
+ private :locked_gem_sources
495
+
536
496
  def nothing_changed?
537
497
  !@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes && !@locked_specs_incomplete_for_platform
538
498
  end
@@ -541,16 +501,28 @@ module Bundler
541
501
  @unlocking
542
502
  end
543
503
 
544
- private
504
+ private
505
+
506
+ def precompute_source_requirements_for_indirect_dependencies?
507
+ sources.non_global_rubygems_sources.all?(&:dependency_api_available?) && sources.no_aggregate_global_source?
508
+ end
509
+
510
+ def current_ruby_platform_locked?
511
+ return false unless generic_local_platform == Gem::Platform::RUBY
512
+
513
+ current_platform_locked?
514
+ end
545
515
 
546
- def current_platforms
547
- current_platform = Bundler.local_platform
548
- [].tap do |platforms|
549
- platforms << current_platform if Bundler.feature_flag.specific_platform?
550
- platforms << generic(current_platform)
516
+ def current_platform_locked?
517
+ @platforms.any? do |bundle_platform|
518
+ MatchPlatform.platforms_match?(bundle_platform, Bundler.local_platform)
551
519
  end
552
520
  end
553
521
 
522
+ def add_current_platform
523
+ add_platform(local_platform)
524
+ end
525
+
554
526
  def change_reason
555
527
  if unlocking?
556
528
  unlock_reason = @unlock.reject {|_k, v| Array(v).empty? }.map do |k, v|
@@ -589,7 +561,7 @@ module Bundler
589
561
  deps_for_source = @dependencies.select {|s| s.source == source }
590
562
  locked_deps_for_source = @locked_deps.values.select {|dep| dep.source == locked_source }
591
563
 
592
- Set.new(deps_for_source) != Set.new(locked_deps_for_source)
564
+ deps_for_source.uniq.sort != locked_deps_for_source.sort
593
565
  end
594
566
 
595
567
  def specs_for_source_changed?(source)
@@ -649,21 +621,20 @@ module Bundler
649
621
  end
650
622
 
651
623
  def converge_rubygems_sources
652
- return false if Bundler.feature_flag.disable_multisource?
624
+ return false if disable_multisource?
653
625
 
654
- changes = false
626
+ return false if locked_gem_sources.empty?
655
627
 
656
- # Get the RubyGems sources from the Gemfile.lock
657
- locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
658
628
  # Get the RubyGems remotes from the Gemfile
659
629
  actual_remotes = sources.rubygems_remotes
630
+ return false if actual_remotes.empty?
631
+
632
+ changes = false
660
633
 
661
634
  # If there is a RubyGems source in both
662
- if !locked_gem_sources.empty? && !actual_remotes.empty?
663
- locked_gem_sources.each do |locked_gem|
664
- # Merge the remotes from the Gemfile into the Gemfile.lock
665
- changes |= locked_gem.replace_remotes(actual_remotes, Bundler.settings[:allow_deployment_source_credential_changes])
666
- end
635
+ locked_gem_sources.each do |locked_gem_source|
636
+ # Merge the remotes from the Gemfile into the Gemfile.lock
637
+ changes |= locked_gem_source.replace_remotes(actual_remotes, Bundler.settings[:allow_deployment_source_credential_changes])
667
638
  end
668
639
 
669
640
  changes
@@ -706,9 +677,6 @@ module Bundler
706
677
  elsif dep.source
707
678
  dep.source = sources.get(dep.source)
708
679
  end
709
- if dep.source.is_a?(Source::Gemspec)
710
- dep.platforms.concat(@platforms.map {|p| Dependency::REVERSE_PLATFORM_MAP[p] }.flatten(1)).uniq!
711
- end
712
680
  end
713
681
 
714
682
  changes = false
@@ -806,11 +774,6 @@ module Bundler
806
774
  # commonly happens if the version changed in the gemspec
807
775
  next unless new_spec
808
776
 
809
- new_runtime_deps = new_spec.dependencies.select {|d| d.type != :development }
810
- old_runtime_deps = s.dependencies.select {|d| d.type != :development }
811
- # If the dependencies of the path source have changed and locked spec can't satisfy new dependencies, unlock it
812
- next unless new_runtime_deps.sort == old_runtime_deps.sort || new_runtime_deps.all? {|d| satisfies_locked_spec?(d) }
813
-
814
777
  s.dependencies.replace(new_spec.dependencies)
815
778
  end
816
779
 
@@ -818,7 +781,7 @@ module Bundler
818
781
  end
819
782
 
820
783
  resolve = SpecSet.new(converged)
821
- @locked_specs_incomplete_for_platform = !resolve.for(expand_dependencies(deps), @unlock[:gems], true, true)
784
+ @locked_specs_incomplete_for_platform = !resolve.for(expand_dependencies(requested_dependencies & deps), @unlock[:gems], true, true)
822
785
  resolve = resolve.for(expand_dependencies(deps, true), @unlock[:gems], false, false, false)
823
786
  diff = nil
824
787
 
@@ -846,21 +809,9 @@ module Bundler
846
809
  @locked_specs[dep].any? {|s| s.satisfies?(dep) && (!dep.source || s.source.include?(dep.source)) }
847
810
  end
848
811
 
849
- # This list of dependencies is only used in #resolve, so it's OK to add
850
- # the metadata dependencies here
851
- def expanded_dependencies
852
- @expanded_dependencies ||= begin
853
- expand_dependencies(dependencies + metadata_dependencies, @remote)
854
- end
855
- end
856
-
857
812
  def metadata_dependencies
858
813
  @metadata_dependencies ||= begin
859
- ruby_versions = concat_ruby_version_requirements(@ruby_version)
860
- if ruby_versions.empty? || !@ruby_version.exact?
861
- concat_ruby_version_requirements(RubyVersion.system)
862
- concat_ruby_version_requirements(locked_ruby_version_object) unless @unlock[:ruby]
863
- end
814
+ ruby_versions = ruby_version_requirements(@ruby_version)
864
815
  [
865
816
  Dependency.new("Ruby\0", ruby_versions),
866
817
  Dependency.new("RubyGems\0", Gem::VERSION),
@@ -868,83 +819,56 @@ module Bundler
868
819
  end
869
820
  end
870
821
 
871
- def concat_ruby_version_requirements(ruby_version, ruby_versions = [])
872
- return ruby_versions unless ruby_version
822
+ def ruby_version_requirements(ruby_version)
823
+ return [] unless ruby_version
873
824
  if ruby_version.patchlevel
874
- ruby_versions << ruby_version.to_gem_version_with_patchlevel
825
+ [ruby_version.to_gem_version_with_patchlevel]
875
826
  else
876
- ruby_versions.concat(ruby_version.versions.map do |version|
827
+ ruby_version.versions.map do |version|
877
828
  requirement = Gem::Requirement.new(version)
878
829
  if requirement.exact?
879
830
  "~> #{version}.0"
880
831
  else
881
832
  requirement
882
833
  end
883
- end)
834
+ end
884
835
  end
885
836
  end
886
837
 
887
838
  def expand_dependencies(dependencies, remote = false)
888
- sorted_platforms = Resolver.sort_platforms(@platforms)
889
839
  deps = []
890
840
  dependencies.each do |dep|
891
841
  dep = Dependency.new(dep, ">= 0") unless dep.respond_to?(:name)
892
- next if !remote && !dep.current_platform?
893
- platforms = dep.gem_platforms(sorted_platforms)
894
- if platforms.empty? && !Bundler.settings[:disable_platform_warnings]
895
- mapped_platforms = dep.expanded_platforms
896
- Bundler.ui.warn \
897
- "The dependency #{dep} will be unused by any of the platforms Bundler is installing for. " \
898
- "Bundler is installing for #{@platforms.join ", "} but the dependency " \
899
- "is only for #{mapped_platforms.join ", "}. " \
900
- "To add those platforms to the bundle, " \
901
- "run `bundle lock --add-platform #{mapped_platforms.join " "}`."
902
- end
903
- platforms.each do |p|
904
- deps << DepProxy.new(dep, p) if remote || p == generic_local_platform
905
- end
842
+ next unless remote || dep.current_platform?
843
+ target_platforms = dep.gem_platforms(remote ? @platforms : [generic_local_platform])
844
+ deps += expand_dependency_with_platforms(dep, target_platforms)
906
845
  end
907
846
  deps
908
847
  end
909
848
 
910
- def requested_dependencies
911
- groups = requested_groups
912
- groups.map!(&:to_sym)
913
- dependencies.reject {|d| !d.should_include? || (d.groups & groups).empty? }
849
+ def expand_dependency_with_platforms(dep, platforms)
850
+ platforms.map do |p|
851
+ DepProxy.get_proxy(dep, p)
852
+ end
914
853
  end
915
854
 
916
855
  def source_requirements
917
- # Load all specs from remote sources
918
- index
919
-
920
856
  # Record the specs available in each gem's source, so that those
921
857
  # specs will be available later when the resolver knows where to
922
858
  # look for that gemspec (or its dependencies)
923
- default = sources.default_source
924
- source_requirements = { :default => default }
925
- default = nil unless Bundler.feature_flag.disable_multisource?
926
- dependencies.each do |dep|
927
- next unless source = dep.source || default
928
- source_requirements[dep.name] = source
859
+ source_requirements = if precompute_source_requirements_for_indirect_dependencies?
860
+ { :default => sources.default_source }.merge(source_map.all_requirements)
861
+ else
862
+ { :default => Source::RubygemsAggregate.new(sources, source_map) }.merge(source_map.direct_requirements)
929
863
  end
930
864
  metadata_dependencies.each do |dep|
931
865
  source_requirements[dep.name] = sources.metadata_source
932
866
  end
867
+ source_requirements[:default_bundler] = source_requirements["bundler"] || sources.default_source
933
868
  source_requirements["bundler"] = sources.metadata_source # needs to come last to override
934
869
  source_requirements
935
870
  end
936
871
 
937
- def pinned_spec_names(skip = nil)
938
- pinned_names = []
939
- default = Bundler.feature_flag.disable_multisource? && sources.default_source
940
- @dependencies.each do |dep|
941
- next unless dep_source = dep.source || default
942
- next if dep_source == skip
943
- pinned_names << dep.name
944
- end
945
- pinned_names
946
- end
947
-
948
872
  def requested_groups
949
873
  groups - Bundler.settings[:without] - @optional_groups + Bundler.settings[:with]
950
874
  end
@@ -980,15 +904,16 @@ module Bundler
980
904
  end
981
905
 
982
906
  def additional_base_requirements_for_resolve
983
- return [] unless @locked_gems && Bundler.feature_flag.only_update_to_newer_versions?
907
+ return [] unless @locked_gems
984
908
  dependencies_by_name = dependencies.inject({}) {|memo, dep| memo.update(dep.name => dep) }
985
909
  @locked_gems.specs.reduce({}) do |requirements, locked_spec|
986
910
  name = locked_spec.name
987
911
  dependency = dependencies_by_name[name]
912
+ next requirements unless dependency
988
913
  next requirements if @locked_gems.dependencies[name] != dependency
989
- next requirements if dependency && dependency.source.is_a?(Source::Path)
914
+ next requirements if dependency.source.is_a?(Source::Path)
990
915
  dep = Gem::Dependency.new(name, ">= #{locked_spec.version}")
991
- requirements[name] = DepProxy.new(dep, locked_spec.platform)
916
+ requirements[name] = DepProxy.get_proxy(dep, locked_spec.platform)
992
917
  requirements
993
918
  end.values
994
919
  end
@@ -998,5 +923,9 @@ module Bundler
998
923
 
999
924
  Bundler.settings[:allow_deployment_source_credential_changes] && source.equivalent_remotes?(sources.rubygems_remotes)
1000
925
  end
926
+
927
+ def source_map
928
+ @source_map ||= SourceMap.new(sources, dependencies)
929
+ end
1001
930
  end
1002
931
  end
@@ -4,19 +4,18 @@ module Bundler
4
4
  class DepProxy
5
5
  attr_reader :__platform, :dep
6
6
 
7
+ @proxies = {}
8
+
9
+ def self.get_proxy(dep, platform)
10
+ @proxies[[dep, platform]] ||= new(dep, platform).freeze
11
+ end
12
+
7
13
  def initialize(dep, platform)
8
14
  @dep = dep
9
15
  @__platform = platform
10
16
  end
11
17
 
12
- def hash
13
- @hash ||= [dep, __platform].hash
14
- end
15
-
16
- def ==(other)
17
- return false if other.class != self.class
18
- dep == other.dep && __platform == other.__platform
19
- end
18
+ private_class_method :new
20
19
 
21
20
  alias_method :eql?, :==
22
21
 
@@ -39,7 +38,15 @@ module Bundler
39
38
  s
40
39
  end
41
40
 
42
- private
41
+ def dup
42
+ raise NoMethodError.new("DepProxy cannot be duplicated")
43
+ end
44
+
45
+ def clone
46
+ raise NoMethodError.new("DepProxy cannot be cloned")
47
+ end
48
+
49
+ private
43
50
 
44
51
  def method_missing(*args, &blk)
45
52
  @dep.send(*args, &blk)
@@ -74,15 +74,6 @@ module Bundler
74
74
  :x64_mingw_26 => Gem::Platform::X64_MINGW,
75
75
  }.freeze
76
76
 
77
- REVERSE_PLATFORM_MAP = {}.tap do |reverse_platform_map|
78
- PLATFORM_MAP.each do |key, value|
79
- reverse_platform_map[value] ||= []
80
- reverse_platform_map[value] << key
81
- end
82
-
83
- reverse_platform_map.each {|_, platforms| platforms.freeze }
84
- end.freeze
85
-
86
77
  def initialize(name, version, options = {}, &blk)
87
78
  type = options["type"] || :runtime
88
79
  super(name, version, type)
@@ -105,9 +96,11 @@ module Bundler
105
96
  def gem_platforms(valid_platforms)
106
97
  return valid_platforms if @platforms.empty?
107
98
 
99
+ valid_generic_platforms = valid_platforms.map {|p| [p, GemHelpers.generic(p)] }.to_h
108
100
  @gem_platforms ||= expanded_platforms.compact.uniq
109
101
 
110
- valid_platforms & @gem_platforms
102
+ filtered_generic_platforms = valid_generic_platforms.values & @gem_platforms
103
+ valid_generic_platforms.select {|_, v| filtered_generic_platforms.include?(v) }.keys
111
104
  end
112
105
 
113
106
  def expanded_platforms