bundler 2.2.3 → 2.3.5

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 (183) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +503 -7
  3. data/README.md +1 -1
  4. data/bundler.gemspec +2 -3
  5. data/exe/bundle +7 -8
  6. data/lib/bundler/.document +1 -0
  7. data/lib/bundler/build_metadata.rb +2 -2
  8. data/lib/bundler/cli/cache.rb +2 -1
  9. data/lib/bundler/cli/check.rb +4 -2
  10. data/lib/bundler/cli/common.rb +15 -2
  11. data/lib/bundler/cli/doctor.rb +15 -4
  12. data/lib/bundler/cli/exec.rb +1 -6
  13. data/lib/bundler/cli/gem.rb +132 -24
  14. data/lib/bundler/cli/info.rb +16 -4
  15. data/lib/bundler/cli/install.rb +12 -27
  16. data/lib/bundler/cli/issue.rb +4 -3
  17. data/lib/bundler/cli/list.rb +7 -1
  18. data/lib/bundler/cli/lock.rb +5 -1
  19. data/lib/bundler/cli/open.rb +1 -2
  20. data/lib/bundler/cli/outdated.rb +10 -11
  21. data/lib/bundler/cli/remove.rb +1 -2
  22. data/lib/bundler/cli/update.rb +17 -8
  23. data/lib/bundler/cli.rb +44 -60
  24. data/lib/bundler/compact_index_client/cache.rb +0 -9
  25. data/lib/bundler/compact_index_client/updater.rb +10 -19
  26. data/lib/bundler/compact_index_client.rb +2 -8
  27. data/lib/bundler/current_ruby.rb +5 -4
  28. data/lib/bundler/definition.rb +158 -316
  29. data/lib/bundler/dep_proxy.rb +15 -8
  30. data/lib/bundler/dependency.rb +5 -7
  31. data/lib/bundler/digest.rb +71 -0
  32. data/lib/bundler/dsl.rb +67 -66
  33. data/lib/bundler/endpoint_specification.rb +21 -11
  34. data/lib/bundler/environment_preserver.rb +4 -1
  35. data/lib/bundler/errors.rb +19 -3
  36. data/lib/bundler/feature_flag.rb +0 -5
  37. data/lib/bundler/fetcher/compact_index.rb +10 -15
  38. data/lib/bundler/fetcher/downloader.rb +9 -6
  39. data/lib/bundler/fetcher/index.rb +0 -27
  40. data/lib/bundler/fetcher.rb +10 -17
  41. data/lib/bundler/friendly_errors.rb +5 -32
  42. data/lib/bundler/gem_helper.rb +28 -21
  43. data/lib/bundler/gem_version_promoter.rb +2 -2
  44. data/lib/bundler/index.rb +8 -12
  45. data/lib/bundler/injector.rb +12 -3
  46. data/lib/bundler/inline.rb +2 -1
  47. data/lib/bundler/installer/gem_installer.rb +4 -22
  48. data/lib/bundler/installer/parallel_installer.rb +36 -15
  49. data/lib/bundler/installer/standalone.rb +29 -9
  50. data/lib/bundler/installer.rb +8 -34
  51. data/lib/bundler/lazy_specification.rb +32 -20
  52. data/lib/bundler/lockfile_generator.rb +1 -1
  53. data/lib/bundler/lockfile_parser.rb +16 -45
  54. data/{man → lib/bundler/man}/bundle-add.1 +10 -2
  55. data/lib/bundler/man/bundle-add.1.ronn +7 -1
  56. data/{man → lib/bundler/man}/bundle-binstubs.1 +1 -1
  57. data/{man → lib/bundler/man}/bundle-cache.1 +1 -1
  58. data/{man → lib/bundler/man}/bundle-check.1 +1 -1
  59. data/{man → lib/bundler/man}/bundle-clean.1 +1 -1
  60. data/{man → lib/bundler/man}/bundle-config.1 +27 -19
  61. data/lib/bundler/man/bundle-config.1.ronn +33 -25
  62. data/{man → lib/bundler/man}/bundle-doctor.1 +1 -1
  63. data/{man → lib/bundler/man}/bundle-exec.1 +1 -1
  64. data/{man → lib/bundler/man}/bundle-gem.1 +14 -1
  65. data/lib/bundler/man/bundle-gem.1.ronn +16 -0
  66. data/{man → lib/bundler/man}/bundle-info.1 +1 -1
  67. data/{man → lib/bundler/man}/bundle-init.1 +1 -1
  68. data/{man → lib/bundler/man}/bundle-inject.1 +1 -1
  69. data/{man → lib/bundler/man}/bundle-install.1 +2 -2
  70. data/lib/bundler/man/bundle-install.1.ronn +2 -2
  71. data/{man → lib/bundler/man}/bundle-list.1 +1 -1
  72. data/{man → lib/bundler/man}/bundle-lock.1 +1 -1
  73. data/{man → lib/bundler/man}/bundle-open.1 +1 -1
  74. data/{man → lib/bundler/man}/bundle-outdated.1 +1 -1
  75. data/{man → lib/bundler/man}/bundle-platform.1 +1 -1
  76. data/{man → lib/bundler/man}/bundle-pristine.1 +1 -1
  77. data/{man → lib/bundler/man}/bundle-remove.1 +1 -1
  78. data/{man → lib/bundler/man}/bundle-show.1 +1 -1
  79. data/{man → lib/bundler/man}/bundle-update.1 +5 -5
  80. data/lib/bundler/man/bundle-update.1.ronn +5 -4
  81. data/{man → lib/bundler/man}/bundle-viz.1 +1 -1
  82. data/{man → lib/bundler/man}/bundle.1 +1 -1
  83. data/{man → lib/bundler/man}/gemfile.5 +28 -2
  84. data/lib/bundler/man/gemfile.5.ronn +9 -1
  85. data/{man → lib/bundler/man}/index.txt +0 -0
  86. data/lib/bundler/plugin/api/source.rb +22 -0
  87. data/lib/bundler/plugin/index.rb +4 -1
  88. data/lib/bundler/plugin/installer.rb +10 -10
  89. data/lib/bundler/plugin/source_list.rb +4 -0
  90. data/lib/bundler/plugin.rb +28 -8
  91. data/lib/bundler/process_lock.rb +1 -1
  92. data/lib/bundler/psyched_yaml.rb +1 -13
  93. data/lib/bundler/resolver/spec_group.rb +36 -48
  94. data/lib/bundler/resolver.rb +97 -151
  95. data/lib/bundler/retry.rb +1 -1
  96. data/lib/bundler/ruby_version.rb +1 -1
  97. data/lib/bundler/rubygems_ext.rb +46 -8
  98. data/lib/bundler/rubygems_gem_installer.rb +68 -1
  99. data/lib/bundler/rubygems_integration.rb +43 -60
  100. data/lib/bundler/runtime.rb +18 -11
  101. data/lib/bundler/self_manager.rb +168 -0
  102. data/lib/bundler/settings.rb +97 -21
  103. data/lib/bundler/setup.rb +2 -2
  104. data/lib/bundler/shared_helpers.rb +6 -21
  105. data/lib/bundler/source/git/git_proxy.rb +60 -53
  106. data/lib/bundler/source/git.rb +38 -18
  107. data/lib/bundler/source/metadata.rb +1 -5
  108. data/lib/bundler/source/path/installer.rb +3 -1
  109. data/lib/bundler/source/path.rb +3 -1
  110. data/lib/bundler/source/rubygems.rb +113 -100
  111. data/lib/bundler/source/rubygems_aggregate.rb +68 -0
  112. data/lib/bundler/source.rb +21 -0
  113. data/lib/bundler/source_list.rb +100 -62
  114. data/lib/bundler/source_map.rb +58 -0
  115. data/lib/bundler/spec_set.rb +21 -34
  116. data/lib/bundler/stub_specification.rb +8 -0
  117. data/lib/bundler/templates/Executable.bundler +7 -7
  118. data/lib/bundler/templates/Gemfile +0 -2
  119. data/lib/bundler/templates/gems.rb +0 -3
  120. data/lib/bundler/templates/newgem/CHANGELOG.md.tt +5 -0
  121. data/lib/bundler/templates/newgem/Gemfile.tt +5 -2
  122. data/lib/bundler/templates/newgem/README.md.tt +5 -3
  123. data/lib/bundler/templates/newgem/Rakefile.tt +15 -2
  124. data/lib/bundler/templates/newgem/github/workflows/main.yml.tt +15 -6
  125. data/lib/bundler/templates/newgem/newgem.gemspec.tt +18 -16
  126. data/lib/bundler/templates/newgem/rubocop.yml.tt +3 -0
  127. data/lib/bundler/templates/newgem/sig/newgem.rbs.tt +8 -0
  128. data/lib/bundler/templates/newgem/standard.yml.tt +2 -0
  129. data/lib/bundler/templates/newgem/test/minitest/{newgem_test.rb.tt → test_newgem.rb.tt} +1 -1
  130. data/lib/bundler/ui/shell.rb +1 -1
  131. data/lib/bundler/vendor/.document +1 -0
  132. data/lib/bundler/vendor/connection_pool/LICENSE +20 -0
  133. data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +19 -21
  134. data/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +1 -1
  135. data/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +57 -0
  136. data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +39 -74
  137. data/lib/bundler/vendor/fileutils/LICENSE.txt +22 -0
  138. data/lib/bundler/vendor/molinillo/LICENSE +9 -0
  139. data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb +7 -0
  140. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +11 -5
  141. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +2 -3
  142. data/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +2 -2
  143. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +12 -1
  144. data/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +11 -7
  145. data/lib/bundler/vendor/net-http-persistent/README.rdoc +82 -0
  146. data/lib/bundler/vendor/thor/LICENSE.md +20 -0
  147. data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +9 -7
  148. data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +1 -2
  149. data/lib/bundler/vendor/thor/lib/thor/actions.rb +7 -3
  150. data/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +6 -0
  151. data/lib/bundler/vendor/thor/lib/thor/error.rb +10 -5
  152. data/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb +5 -1
  153. data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +28 -9
  154. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +27 -6
  155. data/lib/bundler/vendor/thor/lib/thor/shell/color.rb +5 -1
  156. data/lib/bundler/vendor/thor/lib/thor/shell.rb +1 -1
  157. data/lib/bundler/vendor/thor/lib/thor/util.rb +1 -1
  158. data/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  159. data/lib/bundler/vendor/thor/lib/thor.rb +5 -6
  160. data/lib/bundler/vendor/tmpdir/lib/tmpdir.rb +1 -1
  161. data/lib/bundler/vendor/tsort/LICENSE.txt +22 -0
  162. data/lib/bundler/vendor/tsort/lib/tsort.rb +453 -0
  163. data/lib/bundler/vendor/uri/LICENSE.txt +22 -0
  164. data/lib/bundler/vendor/uri/lib/uri/common.rb +17 -80
  165. data/lib/bundler/vendor/uri/lib/uri/ftp.rb +0 -1
  166. data/lib/bundler/vendor/uri/lib/uri/generic.rb +5 -6
  167. data/lib/bundler/vendor/uri/lib/uri/http.rb +0 -1
  168. data/lib/bundler/vendor/uri/lib/uri/https.rb +0 -1
  169. data/lib/bundler/vendor/uri/lib/uri/ldap.rb +1 -1
  170. data/lib/bundler/vendor/uri/lib/uri/mailto.rb +0 -1
  171. data/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +1 -14
  172. data/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb +1 -12
  173. data/lib/bundler/vendor/uri/lib/uri/version.rb +1 -1
  174. data/lib/bundler/vendor/uri/lib/uri/ws.rb +84 -0
  175. data/lib/bundler/vendor/uri/lib/uri/wss.rb +22 -0
  176. data/lib/bundler/vendor/uri/lib/uri.rb +0 -1
  177. data/lib/bundler/vendored_tsort.rb +4 -0
  178. data/lib/bundler/version.rb +1 -1
  179. data/lib/bundler/worker.rb +19 -4
  180. data/lib/bundler.rb +29 -33
  181. metadata +54 -35
  182. data/lib/bundler/gemdeps.rb +0 -29
  183. data/lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb +0 -66
@@ -1,12 +1,16 @@
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
8
7
  include GemHelpers
9
8
 
9
+ class << self
10
+ # Do not create or modify a lockfile (Makes #lock a noop)
11
+ attr_accessor :no_lock
12
+ end
13
+
10
14
  attr_reader(
11
15
  :dependencies,
12
16
  :locked_deps,
@@ -57,10 +61,8 @@ module Bundler
57
61
  @unlocking_bundler = false
58
62
  @unlocking = unlock
59
63
  else
60
- unlock = unlock.dup
61
64
  @unlocking_bundler = unlock.delete(:bundler)
62
- unlock.delete_if {|_k, v| Array(v).empty? }
63
- @unlocking = !unlock.empty?
65
+ @unlocking = unlock.any? {|_k, v| !Array(v).empty? }
64
66
  end
65
67
 
66
68
  @dependencies = dependencies
@@ -76,18 +78,13 @@ module Bundler
76
78
  @lockfile_contents = String.new
77
79
  @locked_bundler_version = nil
78
80
  @locked_ruby_version = nil
79
- @locked_specs_incomplete_for_platform = false
80
81
  @new_platform = nil
81
82
 
82
83
  if lockfile && File.exist?(lockfile)
83
84
  @lockfile_contents = Bundler.read_file(lockfile)
84
85
  @locked_gems = LockfileParser.new(@lockfile_contents)
85
86
  @locked_platforms = @locked_gems.platforms
86
- if Bundler.settings[:force_ruby_platform]
87
- @platforms = [Gem::Platform::RUBY]
88
- else
89
- @platforms = @locked_platforms.dup
90
- end
87
+ @platforms = @locked_platforms.dup
91
88
  @locked_bundler_version = @locked_gems.bundler_version
92
89
  @locked_ruby_version = @locked_gems.ruby_version
93
90
 
@@ -111,7 +108,19 @@ module Bundler
111
108
  @locked_platforms = []
112
109
  end
113
110
 
114
- @unlock[:gems] ||= []
111
+ locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
112
+ @multisource_allowed = locked_gem_sources.size == 1 && locked_gem_sources.first.multiple_remotes? && Bundler.frozen_bundle?
113
+
114
+ if @multisource_allowed
115
+ unless sources.aggregate_global_source?
116
+ msg = "Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. Make sure you run `bundle install` in non frozen mode and commit the result to make your lockfile secure."
117
+
118
+ Bundler::SharedHelpers.major_deprecation 2, msg
119
+ end
120
+
121
+ @sources.merged_gem_lockfile_sections!(locked_gem_sources.first)
122
+ end
123
+
115
124
  @unlock[:sources] ||= []
116
125
  @unlock[:ruby] ||= if @ruby_version && locked_ruby_version_object
117
126
  @ruby_version.diff(locked_ruby_version_object)
@@ -124,14 +133,18 @@ module Bundler
124
133
  @path_changes = converge_paths
125
134
  @source_changes = converge_sources
126
135
 
127
- unless @unlock[:lock_shared_dependencies]
128
- eager_unlock = expand_dependencies(@unlock[:gems], true)
129
- @unlock[:gems] = @locked_specs.for(eager_unlock, [], false, false, false).map(&:name)
136
+ if @unlock[:conservative]
137
+ @unlock[:gems] ||= @dependencies.map(&:name)
138
+ else
139
+ eager_unlock = expand_dependencies(@unlock[:gems] || [], true)
140
+ @unlock[:gems] = @locked_specs.for(eager_unlock, false, false).map(&:name)
130
141
  end
131
142
 
132
143
  @dependency_changes = converge_dependencies
133
144
  @local_changes = converge_locals
134
145
 
146
+ @locked_specs_incomplete_for_platform = !@locked_specs.for(requested_dependencies & expand_dependencies(locked_dependencies), true, true)
147
+
135
148
  @requires = compute_requires
136
149
  end
137
150
 
@@ -150,17 +163,21 @@ module Bundler
150
163
  end
151
164
  end
152
165
 
166
+ def resolve_only_locally!
167
+ @remote = false
168
+ sources.local_only!
169
+ resolve
170
+ end
171
+
153
172
  def resolve_with_cache!
154
- raise "Specs already loaded" if @specs
155
173
  sources.cached!
156
- specs
174
+ resolve
157
175
  end
158
176
 
159
177
  def resolve_remotely!
160
- return if @specs
161
178
  @remote = true
162
179
  sources.remote!
163
- specs
180
+ resolve
164
181
  end
165
182
 
166
183
  # For given dependency list returns a SpecSet with Gemspec of all the required
@@ -170,25 +187,7 @@ module Bundler
170
187
  #
171
188
  # @return [Bundler::SpecSet]
172
189
  def specs
173
- @specs ||= begin
174
- begin
175
- specs = resolve.materialize(requested_dependencies)
176
- rescue GemNotFound => e # Handle yanked gem
177
- gem_name, gem_version = extract_gem_info(e)
178
- locked_gem = @locked_specs[gem_name].last
179
- raise if locked_gem.nil? || locked_gem.version.to_s != gem_version || !@remote
180
- raise GemNotFound, "Your bundle is locked to #{locked_gem}, but that version could not " \
181
- "be found in any of the sources listed in your Gemfile. If you haven't changed sources, " \
182
- "that means the author of #{locked_gem} has removed it. You'll need to update your bundle " \
183
- "to a version other than #{locked_gem} that hasn't been removed in order to install."
184
- end
185
- unless specs["bundler"].any?
186
- bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last
187
- specs["bundler"] = bundler
188
- end
189
-
190
- specs
191
- end
190
+ @specs ||= materialize(requested_dependencies)
192
191
  end
193
192
 
194
193
  def new_specs
@@ -200,9 +199,7 @@ module Bundler
200
199
  end
201
200
 
202
201
  def missing_specs
203
- missing = []
204
- resolve.materialize(requested_dependencies, missing)
205
- missing
202
+ resolve.materialize(requested_dependencies).missing_specs
206
203
  end
207
204
 
208
205
  def missing_specs?
@@ -211,7 +208,6 @@ module Bundler
211
208
  Bundler.ui.debug "The definition is missing #{missing.map(&:full_name)}"
212
209
  true
213
210
  rescue BundlerError => e
214
- @index = nil
215
211
  @resolve = nil
216
212
  @specs = nil
217
213
  @gem_version_promoter = nil
@@ -221,17 +217,11 @@ module Bundler
221
217
  end
222
218
 
223
219
  def requested_specs
224
- @requested_specs ||= begin
225
- groups = requested_groups
226
- groups.map!(&:to_sym)
227
- specs_for(groups)
228
- end
220
+ specs_for(requested_groups)
229
221
  end
230
222
 
231
223
  def requested_dependencies
232
- groups = requested_groups
233
- groups.map!(&:to_sym)
234
- dependencies_for(groups)
224
+ dependencies_for(requested_groups)
235
225
  end
236
226
 
237
227
  def current_dependencies
@@ -240,15 +230,22 @@ module Bundler
240
230
  end
241
231
  end
242
232
 
233
+ def locked_dependencies
234
+ @locked_deps.values
235
+ end
236
+
243
237
  def specs_for(groups)
238
+ return specs if groups.empty?
244
239
  deps = dependencies_for(groups)
245
- specs.for(expand_dependencies(deps))
240
+ materialize(deps)
246
241
  end
247
242
 
248
243
  def dependencies_for(groups)
249
- current_dependencies.reject do |d|
244
+ groups.map!(&:to_sym)
245
+ deps = current_dependencies.reject do |d|
250
246
  (d.groups & groups).empty?
251
247
  end
248
+ expand_dependencies(deps)
252
249
  end
253
250
 
254
251
  # Resolve all the dependencies specified in Gemfile. It ensures that
@@ -259,73 +256,20 @@ module Bundler
259
256
  def resolve
260
257
  @resolve ||= begin
261
258
  last_resolve = converge_locked_specs
262
- resolve =
263
- if Bundler.frozen_bundle?
264
- Bundler.ui.debug "Frozen, using resolution from the lockfile"
265
- last_resolve
266
- elsif !unlocking? && nothing_changed?
267
- Bundler.ui.debug("Found no changes, using resolution from the lockfile")
268
- last_resolve
269
- else
270
- # Run a resolve against the locally available gems
271
- Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}")
272
- expanded_dependencies = expand_dependencies(dependencies + metadata_dependencies, @remote)
273
- last_resolve.merge Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
274
- end
275
-
276
- # filter out gems that _can_ be installed on multiple platforms, but don't need
277
- # to be
278
- resolve.for(expand_dependencies(dependencies, true), [], false, false, false)
279
- end
280
- end
281
-
282
- def index
283
- @index ||= Index.build do |idx|
284
- dependency_names = @dependencies.map(&:name)
285
-
286
- sources.all_sources.each do |source|
287
- source.dependency_names = dependency_names - pinned_spec_names(source)
288
- idx.add_source source.specs
289
- dependency_names.concat(source.unmet_deps).uniq!
290
- end
291
-
292
- double_check_for_index(idx, dependency_names)
293
- end
294
- end
295
-
296
- # Suppose the gem Foo depends on the gem Bar. Foo exists in Source A. Bar has some versions that exist in both
297
- # sources A and B. At this point, the API request will have found all the versions of Bar in source A,
298
- # but will not have found any versions of Bar from source B, which is a problem if the requested version
299
- # of Foo specifically depends on a version of Bar that is only found in source B. This ensures that for
300
- # each spec we found, we add all possible versions from all sources to the index.
301
- def double_check_for_index(idx, dependency_names)
302
- pinned_names = pinned_spec_names
303
- loop do
304
- idxcount = idx.size
305
-
306
- names = :names # do this so we only have to traverse to get dependency_names from the index once
307
- unmet_dependency_names = lambda do
308
- return names unless names == :names
309
- new_names = sources.all_sources.map(&:dependency_names_to_double_check)
310
- return names = nil if new_names.compact!
311
- names = new_names.flatten(1).concat(dependency_names)
312
- names.uniq!
313
- names -= pinned_names
314
- names
315
- end
316
-
317
- sources.all_sources.each do |source|
318
- source.double_check_for(unmet_dependency_names)
259
+ if Bundler.frozen_bundle?
260
+ Bundler.ui.debug "Frozen, using resolution from the lockfile"
261
+ last_resolve
262
+ elsif !unlocking? && nothing_changed?
263
+ Bundler.ui.debug("Found no changes, using resolution from the lockfile")
264
+ last_resolve
265
+ else
266
+ # Run a resolve against the locally available gems
267
+ Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}")
268
+ expanded_dependencies = expand_dependencies(dependencies + metadata_dependencies, @remote)
269
+ Resolver.resolve(expanded_dependencies, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
319
270
  end
320
-
321
- break if idxcount == idx.size
322
271
  end
323
272
  end
324
- private :double_check_for_index
325
-
326
- def has_rubygems_remotes?
327
- sources.rubygems_sources.any? {|s| s.remotes.any? }
328
- end
329
273
 
330
274
  def spec_git_paths
331
275
  sources.git_sources.map {|s| File.realpath(s.path) if File.exist?(s.path) }.compact
@@ -336,6 +280,8 @@ module Bundler
336
280
  end
337
281
 
338
282
  def lock(file, preserve_unknown_sections = false)
283
+ return if Definition.no_lock
284
+
339
285
  contents = to_lock
340
286
 
341
287
  # Convert to \r\n if the existing lock has them
@@ -346,10 +292,7 @@ module Bundler
346
292
  locked_major = @locked_bundler_version.segments.first
347
293
  current_major = Gem::Version.create(Bundler::VERSION).segments.first
348
294
 
349
- if updating_major = locked_major < current_major
350
- Bundler.ui.warn "Warning: the lockfile is being updated to Bundler #{current_major}, " \
351
- "after which you will be unable to return to Bundler #{@locked_bundler_version.segments.first}."
352
- end
295
+ updating_major = locked_major < current_major
353
296
  end
354
297
 
355
298
  preserve_unknown_sections ||= !updating_major && (Bundler.frozen_bundle? || !(unlocking? || @unlocking_bundler))
@@ -366,14 +309,6 @@ module Bundler
366
309
  end
367
310
  end
368
311
 
369
- def locked_bundler_version
370
- if @locked_bundler_version && @locked_bundler_version < Gem::Version.new(Bundler::VERSION)
371
- new_version = Bundler::VERSION
372
- end
373
-
374
- new_version || @locked_bundler_version || Bundler::VERSION
375
- end
376
-
377
312
  def locked_ruby_version
378
313
  return unless ruby_version
379
314
  if @unlock[:ruby] || !@locked_ruby_version
@@ -425,44 +360,31 @@ module Bundler
425
360
  added.concat new_platforms.map {|p| "* platform: #{p}" }
426
361
  deleted.concat deleted_platforms.map {|p| "* platform: #{p}" }
427
362
 
428
- gemfile_sources = sources.lock_sources
363
+ new_deps = @dependencies - locked_dependencies
364
+ deleted_deps = locked_dependencies - @dependencies
429
365
 
430
- new_sources = gemfile_sources - @locked_sources
431
- deleted_sources = @locked_sources - gemfile_sources
432
-
433
- new_deps = @dependencies - @locked_deps.values
434
- deleted_deps = @locked_deps.values - @dependencies
366
+ added.concat new_deps.map {|d| "* #{pretty_dep(d)}" } if new_deps.any?
367
+ deleted.concat deleted_deps.map {|d| "* #{pretty_dep(d)}" } if deleted_deps.any?
435
368
 
436
- # Check if it is possible that the source is only changed thing
437
- if (new_deps.empty? && deleted_deps.empty?) && (!new_sources.empty? && !deleted_sources.empty?)
438
- new_sources.reject! {|source| (source.path? && source.path.exist?) || equivalent_rubygems_remotes?(source) }
439
- deleted_sources.reject! {|source| (source.path? && source.path.exist?) || equivalent_rubygems_remotes?(source) }
440
- end
369
+ both_sources = Hash.new {|h, k| h[k] = [] }
370
+ @dependencies.each {|d| both_sources[d.name][0] = d }
441
371
 
442
- if @locked_sources != gemfile_sources
443
- if new_sources.any?
444
- added.concat new_sources.map {|source| "* source: #{source}" }
445
- end
372
+ locked_dependencies.each do |d|
373
+ next if !Bundler.feature_flag.bundler_3_mode? && @locked_specs[d.name].empty?
446
374
 
447
- if deleted_sources.any?
448
- deleted.concat deleted_sources.map {|source| "* source: #{source}" }
449
- end
375
+ both_sources[d.name][1] = d
450
376
  end
451
377
 
452
- added.concat new_deps.map {|d| "* #{pretty_dep(d)}" } if new_deps.any?
453
- if deleted_deps.any?
454
- deleted.concat deleted_deps.map {|d| "* #{pretty_dep(d)}" }
455
- end
378
+ both_sources.each do |name, (dep, lock_dep)|
379
+ next if dep.nil? || lock_dep.nil?
456
380
 
457
- both_sources = Hash.new {|h, k| h[k] = [] }
458
- @dependencies.each {|d| both_sources[d.name][0] = d }
459
- @locked_deps.each {|name, d| both_sources[name][1] = d.source }
381
+ gemfile_source = dep.source || sources.default_source
382
+ lock_source = lock_dep.source || sources.default_source
383
+ next if lock_source.include?(gemfile_source)
460
384
 
461
- both_sources.each do |name, (dep, lock_source)|
462
- next if lock_source.nil? || (dep && lock_source.can_lock?(dep))
463
- gemfile_source_name = (dep && dep.source) || "no specified source"
464
- lockfile_source_name = lock_source
465
- changed << "* #{name} from `#{gemfile_source_name}` to `#{lockfile_source_name}`"
385
+ gemfile_source_name = dep.source ? gemfile_source.identifier : "no specified source"
386
+ lockfile_source_name = lock_dep.source ? lock_source.identifier : "no specified source"
387
+ changed << "* #{name} from `#{lockfile_source_name}` to `#{gemfile_source_name}`"
466
388
  end
467
389
 
468
390
  reason = change_reason
@@ -529,14 +451,6 @@ module Bundler
529
451
  end
530
452
  end
531
453
 
532
- def find_resolved_spec(current_spec)
533
- specs.find_by_name_and_platform(current_spec.name, current_spec.platform)
534
- end
535
-
536
- def find_indexed_specs(current_spec)
537
- index[current_spec.name].select {|spec| spec.match_platform(current_spec.platform) }.sort_by(&:version)
538
- end
539
-
540
454
  attr_reader :sources
541
455
  private :sources
542
456
 
@@ -550,6 +464,35 @@ module Bundler
550
464
 
551
465
  private
552
466
 
467
+ def materialize(dependencies)
468
+ specs = resolve.materialize(dependencies)
469
+ missing_specs = specs.missing_specs
470
+
471
+ if missing_specs.any?
472
+ missing_specs.each do |s|
473
+ locked_gem = @locked_specs[s.name].last
474
+ next if locked_gem.nil? || locked_gem.version != s.version || !@remote
475
+ raise GemNotFound, "Your bundle is locked to #{locked_gem} from #{locked_gem.source}, but that version can " \
476
+ "no longer be found in that source. That means the author of #{locked_gem} has removed it. " \
477
+ "You'll need to update your bundle to a version other than #{locked_gem} that hasn't been " \
478
+ "removed in order to install."
479
+ end
480
+
481
+ raise GemNotFound, "Could not find #{missing_specs.map(&:full_name).join(", ")} in any of the sources"
482
+ end
483
+
484
+ unless specs["bundler"].any?
485
+ bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last
486
+ specs["bundler"] = bundler
487
+ end
488
+
489
+ specs
490
+ end
491
+
492
+ def precompute_source_requirements_for_indirect_dependencies?
493
+ @remote && sources.non_global_rubygems_sources.all?(&:dependency_api_available?) && !sources.aggregate_global_source?
494
+ end
495
+
553
496
  def current_ruby_platform_locked?
554
497
  return false unless generic_local_platform == Gem::Platform::RUBY
555
498
 
@@ -602,9 +545,9 @@ module Bundler
602
545
 
603
546
  def dependencies_for_source_changed?(source, locked_source = source)
604
547
  deps_for_source = @dependencies.select {|s| s.source == source }
605
- locked_deps_for_source = @locked_deps.values.select {|dep| dep.source == locked_source }
548
+ locked_deps_for_source = locked_dependencies.select {|dep| dep.source == locked_source }
606
549
 
607
- Set.new(deps_for_source) != Set.new(locked_deps_for_source)
550
+ deps_for_source.uniq.sort != locked_deps_for_source.sort
608
551
  end
609
552
 
610
553
  def specs_for_source_changed?(source)
@@ -663,36 +606,11 @@ module Bundler
663
606
  end
664
607
  end
665
608
 
666
- def converge_rubygems_sources
667
- return false if Bundler.feature_flag.disable_multisource?
668
-
669
- changes = false
670
-
671
- # Get the RubyGems sources from the Gemfile.lock
672
- locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
673
- # Get the RubyGems remotes from the Gemfile
674
- actual_remotes = sources.rubygems_remotes
675
-
676
- # If there is a RubyGems source in both
677
- if !locked_gem_sources.empty? && !actual_remotes.empty?
678
- locked_gem_sources.each do |locked_gem|
679
- # Merge the remotes from the Gemfile into the Gemfile.lock
680
- changes |= locked_gem.replace_remotes(actual_remotes, Bundler.settings[:allow_deployment_source_credential_changes])
681
- end
682
- end
683
-
684
- changes
685
- end
686
-
687
609
  def converge_sources
688
- changes = false
689
-
690
- changes |= converge_rubygems_sources
691
-
692
610
  # Replace the sources from the Gemfile with the sources from the Gemfile.lock,
693
611
  # if they exist in the Gemfile.lock and are `==`. If you can't find an equivalent
694
612
  # source in the Gemfile.lock, use the one from the Gemfile.
695
- changes |= sources.replace_sources!(@locked_sources)
613
+ changes = sources.replace_sources!(@locked_sources)
696
614
 
697
615
  sources.all_sources.each do |source|
698
616
  # If the source is unlockable and the current command allows an unlock of
@@ -710,25 +628,14 @@ module Bundler
710
628
  end
711
629
 
712
630
  def converge_dependencies
713
- frozen = Bundler.frozen_bundle?
714
- (@dependencies + @locked_deps.values).each do |dep|
715
- locked_source = @locked_deps[dep.name]
716
- # This is to make sure that if bundler is installing in deployment mode and
717
- # after locked_source and sources don't match, we still use locked_source.
718
- if frozen && !locked_source.nil? &&
719
- locked_source.respond_to?(:source) && locked_source.source.instance_of?(Source::Path) && locked_source.source.path.exist?
720
- dep.source = locked_source.source
721
- elsif dep.source
631
+ changes = false
632
+
633
+ @dependencies.each do |dep|
634
+ if dep.source
722
635
  dep.source = sources.get(dep.source)
723
636
  end
724
- end
725
637
 
726
- changes = false
727
- # We want to know if all match, but don't want to check all entries
728
- # This means we need to return false if any dependency doesn't match
729
- # the lock or doesn't exist in the lock.
730
- @dependencies.each do |dependency|
731
- unless locked_dep = @locked_deps[dependency.name]
638
+ unless locked_dep = @locked_deps[dep.name]
732
639
  changes = true
733
640
  next
734
641
  end
@@ -739,11 +646,11 @@ module Bundler
739
646
  # directive, the lockfile dependencies and resolved dependencies end up
740
647
  # with a mismatch on #type. Work around that by setting the type on the
741
648
  # dep from the lockfile.
742
- locked_dep.instance_variable_set(:@type, dependency.type)
649
+ locked_dep.instance_variable_set(:@type, dep.type)
743
650
 
744
651
  # We already know the name matches from the hash lookup
745
652
  # so we only need to check the requirement now
746
- changes ||= dependency.requirement != locked_dep.requirement
653
+ changes ||= dep.requirement != locked_dep.requirement
747
654
  end
748
655
 
749
656
  changes
@@ -753,47 +660,37 @@ module Bundler
753
660
  # commonly happen if the Gemfile has changed since the lockfile was last
754
661
  # generated
755
662
  def converge_locked_specs
756
- deps = []
663
+ resolve = converge_specs(@locked_specs)
757
664
 
758
- # Build a list of dependencies that are the same in the Gemfile
759
- # and Gemfile.lock. If the Gemfile modified a dependency, but
760
- # the gem in the Gemfile.lock still satisfies it, this is fine
761
- # too.
762
- @dependencies.each do |dep|
763
- locked_dep = @locked_deps[dep.name]
764
-
765
- # If the locked_dep doesn't match the dependency we're looking for then we ignore the locked_dep
766
- locked_dep = nil unless locked_dep == dep
665
+ diff = nil
767
666
 
768
- if in_locked_deps?(dep, locked_dep) || satisfies_locked_spec?(dep)
769
- deps << dep
770
- elsif dep.source.is_a?(Source::Path) && dep.current_platform? && (!locked_dep || dep.source != locked_dep.source)
771
- @locked_specs.each do |s|
772
- @unlock[:gems] << s.name if s.source == dep.source
773
- end
667
+ # Now, we unlock any sources that do not have anymore gems pinned to it
668
+ sources.all_sources.each do |source|
669
+ next unless source.respond_to?(:unlock!)
774
670
 
775
- dep.source.unlock! if dep.source.respond_to?(:unlock!)
776
- dep.source.specs.each {|s| @unlock[:gems] << s.name }
671
+ unless resolve.any? {|s| s.source == source }
672
+ diff ||= @locked_specs.to_a - resolve.to_a
673
+ source.unlock! if diff.any? {|s| s.source == source }
777
674
  end
778
675
  end
779
676
 
780
- unlock_source_unlocks_spec = Bundler.feature_flag.unlock_source_unlocks_spec?
677
+ resolve
678
+ end
781
679
 
680
+ def converge_specs(specs)
681
+ deps = []
782
682
  converged = []
783
- @locked_specs.each do |s|
683
+ specs.each do |s|
784
684
  # Replace the locked dependency's source with the equivalent source from the Gemfile
785
685
  dep = @dependencies.find {|d| s.satisfies?(d) }
786
- s.source = (dep && dep.source) || sources.get(s.source)
787
686
 
788
- # Don't add a spec to the list if its source is expired. For example,
789
- # if you change a Git gem to RubyGems.
790
- next if s.source.nil?
791
- next if @unlock[:sources].include?(s.source.name)
687
+ if dep && (!dep.source || s.source.include?(dep.source))
688
+ deps << dep
689
+ end
792
690
 
793
- # XXX This is a backwards-compatibility fix to preserve the ability to
794
- # unlock a single gem by passing its name via `--source`. See issue #3759
795
- # TODO: delete in Bundler 2
796
- next if unlock_source_unlocks_spec && @unlock[:sources].include?(s.name)
691
+ s.source = (dep && dep.source) || sources.get(s.source) || sources.default_source unless Bundler.frozen_bundle?
692
+
693
+ next if @unlock[:sources].include?(s.source.name)
797
694
 
798
695
  # If the spec is from a path source and it doesn't exist anymore
799
696
  # then we unlock it.
@@ -805,8 +702,8 @@ module Bundler
805
702
  rescue PathError, GitError
806
703
  # if we won't need the source (according to the lockfile),
807
704
  # don't error if the path/git source isn't available
808
- next if @locked_specs.
809
- for(requested_dependencies, [], false, true, false).
705
+ next if specs.
706
+ for(requested_dependencies, false, true).
810
707
  none? {|locked_spec| locked_spec.source == s.source }
811
708
 
812
709
  raise
@@ -818,44 +715,18 @@ module Bundler
818
715
  # commonly happens if the version changed in the gemspec
819
716
  next unless new_spec
820
717
 
821
- new_runtime_deps = new_spec.dependencies.select {|d| d.type != :development }
822
- old_runtime_deps = s.dependencies.select {|d| d.type != :development }
823
- # If the dependencies of the path source have changed and locked spec can't satisfy new dependencies, unlock it
824
- next unless new_runtime_deps.sort == old_runtime_deps.sort || new_runtime_deps.all? {|d| satisfies_locked_spec?(d) }
825
-
826
718
  s.dependencies.replace(new_spec.dependencies)
827
719
  end
828
720
 
829
- converged << s
830
- end
831
-
832
- resolve = SpecSet.new(converged)
833
- @locked_specs_incomplete_for_platform = !resolve.for(expand_dependencies(requested_dependencies & deps), @unlock[:gems], true, true)
834
- resolve = resolve.for(expand_dependencies(deps, true), @unlock[:gems], false, false, false)
835
- diff = nil
836
-
837
- # Now, we unlock any sources that do not have anymore gems pinned to it
838
- sources.all_sources.each do |source|
839
- next unless source.respond_to?(:unlock!)
840
-
841
- unless resolve.any? {|s| s.source == source }
842
- diff ||= @locked_specs.to_a - resolve.to_a
843
- source.unlock! if diff.any? {|s| s.source == source }
721
+ if dep.nil? && requested_dependencies.find {|d| s.name == d.name }
722
+ @unlock[:gems] << s.name
723
+ else
724
+ converged << s
844
725
  end
845
726
  end
846
727
 
847
- resolve
848
- end
849
-
850
- def in_locked_deps?(dep, locked_dep)
851
- # Because the lockfile can't link a dep to a specific remote, we need to
852
- # treat sources as equivalent anytime the locked dep has all the remotes
853
- # that the Gemfile dep does.
854
- locked_dep && locked_dep.source && dep.source && locked_dep.source.include?(dep.source)
855
- end
856
-
857
- def satisfies_locked_spec?(dep)
858
- @locked_specs[dep].any? {|s| s.satisfies?(dep) && (!dep.source || s.source.include?(dep.source)) }
728
+ resolve = SpecSet.new(converged)
729
+ SpecSet.new(resolve.for(expand_dependencies(deps, true), false, false).reject{|s| @unlock[:gems].include?(s.name) })
859
730
  end
860
731
 
861
732
  def metadata_dependencies
@@ -889,7 +760,7 @@ module Bundler
889
760
  dependencies.each do |dep|
890
761
  dep = Dependency.new(dep, ">= 0") unless dep.respond_to?(:name)
891
762
  next unless remote || dep.current_platform?
892
- target_platforms = dep.gem_platforms(remote ? Resolver.sort_platforms(@platforms) : [generic_local_platform])
763
+ target_platforms = dep.gem_platforms(remote ? @platforms : [generic_local_platform])
893
764
  deps += expand_dependency_with_platforms(dep, target_platforms)
894
765
  end
895
766
  deps
@@ -897,42 +768,27 @@ module Bundler
897
768
 
898
769
  def expand_dependency_with_platforms(dep, platforms)
899
770
  platforms.map do |p|
900
- DepProxy.new(dep, p)
771
+ DepProxy.get_proxy(dep, p)
901
772
  end
902
773
  end
903
774
 
904
775
  def source_requirements
905
- # Load all specs from remote sources
906
- index
907
-
908
776
  # Record the specs available in each gem's source, so that those
909
777
  # specs will be available later when the resolver knows where to
910
778
  # look for that gemspec (or its dependencies)
911
- default = sources.default_source
912
- source_requirements = { :default => default }
913
- default = nil unless Bundler.feature_flag.disable_multisource?
914
- dependencies.each do |dep|
915
- next unless source = dep.source || default
916
- source_requirements[dep.name] = source
779
+ source_requirements = if precompute_source_requirements_for_indirect_dependencies?
780
+ { :default => sources.default_source }.merge(source_map.all_requirements)
781
+ else
782
+ { :default => Source::RubygemsAggregate.new(sources, source_map) }.merge(source_map.direct_requirements)
917
783
  end
918
784
  metadata_dependencies.each do |dep|
919
785
  source_requirements[dep.name] = sources.metadata_source
920
786
  end
787
+ source_requirements[:default_bundler] = source_requirements["bundler"] || sources.default_source
921
788
  source_requirements["bundler"] = sources.metadata_source # needs to come last to override
922
789
  source_requirements
923
790
  end
924
791
 
925
- def pinned_spec_names(skip = nil)
926
- pinned_names = []
927
- default = Bundler.feature_flag.disable_multisource? && sources.default_source
928
- @dependencies.each do |dep|
929
- next unless dep_source = dep.source || default
930
- next if dep_source == skip
931
- pinned_names << dep.name
932
- end
933
- pinned_names
934
- end
935
-
936
792
  def requested_groups
937
793
  groups - Bundler.settings[:without] - @optional_groups + Bundler.settings[:with]
938
794
  end
@@ -950,12 +806,6 @@ module Bundler
950
806
  current == proposed
951
807
  end
952
808
 
953
- def extract_gem_info(error)
954
- # This method will extract the error message like "Could not find foo-1.2.3 in any of the sources"
955
- # to an array. The first element will be the gem name (e.g. foo), the second will be the version number.
956
- error.message.scan(/Could not find (\w+)-(\d+(?:\.\d+)+)/).flatten
957
- end
958
-
959
809
  def compute_requires
960
810
  dependencies.reduce({}) do |requires, dep|
961
811
  next requires unless dep.should_include?
@@ -968,24 +818,16 @@ module Bundler
968
818
  end
969
819
 
970
820
  def additional_base_requirements_for_resolve
971
- return [] unless @locked_gems && Bundler.feature_flag.only_update_to_newer_versions?
972
- dependencies_by_name = dependencies.inject({}) {|memo, dep| memo.update(dep.name => dep) }
973
- @locked_gems.specs.reduce({}) do |requirements, locked_spec|
821
+ return [] unless @locked_gems && unlocking? && !sources.expired_sources?(@locked_gems.sources)
822
+ converge_specs(@locked_gems.specs).map do |locked_spec|
974
823
  name = locked_spec.name
975
- dependency = dependencies_by_name[name]
976
- next requirements unless dependency
977
- next requirements if @locked_gems.dependencies[name] != dependency
978
- next requirements if dependency.source.is_a?(Source::Path)
979
824
  dep = Gem::Dependency.new(name, ">= #{locked_spec.version}")
980
- requirements[name] = DepProxy.new(dep, locked_spec.platform)
981
- requirements
982
- end.values
825
+ DepProxy.get_proxy(dep, locked_spec.platform)
826
+ end
983
827
  end
984
828
 
985
- def equivalent_rubygems_remotes?(source)
986
- return false unless source.is_a?(Source::Rubygems)
987
-
988
- Bundler.settings[:allow_deployment_source_credential_changes] && source.equivalent_remotes?(sources.rubygems_remotes)
829
+ def source_map
830
+ @source_map ||= SourceMap.new(sources, dependencies)
989
831
  end
990
832
  end
991
833
  end