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
@@ -6,6 +6,11 @@ module Bundler
6
6
  class Definition
7
7
  include GemHelpers
8
8
 
9
+ class << self
10
+ # Do not create or modify a lockfile (Makes #lock a noop)
11
+ attr_accessor :no_lock
12
+ end
13
+
9
14
  attr_reader(
10
15
  :dependencies,
11
16
  :locked_deps,
@@ -56,10 +61,8 @@ module Bundler
56
61
  @unlocking_bundler = false
57
62
  @unlocking = unlock
58
63
  else
59
- unlock = unlock.dup
60
64
  @unlocking_bundler = unlock.delete(:bundler)
61
- unlock.delete_if {|_k, v| Array(v).empty? }
62
- @unlocking = !unlock.empty?
65
+ @unlocking = unlock.any? {|_k, v| !Array(v).empty? }
63
66
  end
64
67
 
65
68
  @dependencies = dependencies
@@ -67,6 +70,7 @@ module Bundler
67
70
  @unlock = unlock
68
71
  @optional_groups = optional_groups
69
72
  @remote = false
73
+ @prefer_local = false
70
74
  @specs = nil
71
75
  @ruby_version = ruby_version
72
76
  @gemfiles = gemfiles
@@ -75,7 +79,6 @@ module Bundler
75
79
  @lockfile_contents = String.new
76
80
  @locked_bundler_version = nil
77
81
  @locked_ruby_version = nil
78
- @locked_specs_incomplete_for_platform = false
79
82
  @new_platform = nil
80
83
 
81
84
  if lockfile && File.exist?(lockfile)
@@ -85,10 +88,11 @@ module Bundler
85
88
  @platforms = @locked_platforms.dup
86
89
  @locked_bundler_version = @locked_gems.bundler_version
87
90
  @locked_ruby_version = @locked_gems.ruby_version
91
+ @originally_locked_specs = SpecSet.new(@locked_gems.specs)
88
92
 
89
93
  if unlock != true
90
94
  @locked_deps = @locked_gems.dependencies
91
- @locked_specs = SpecSet.new(@locked_gems.specs)
95
+ @locked_specs = @originally_locked_specs
92
96
  @locked_sources = @locked_gems.sources
93
97
  else
94
98
  @unlock = {}
@@ -102,11 +106,24 @@ module Bundler
102
106
  @locked_gems = nil
103
107
  @locked_deps = {}
104
108
  @locked_specs = SpecSet.new([])
109
+ @originally_locked_specs = @locked_specs
105
110
  @locked_sources = []
106
111
  @locked_platforms = []
107
112
  end
108
113
 
109
- @unlock[:gems] ||= []
114
+ locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
115
+ @multisource_allowed = locked_gem_sources.size == 1 && locked_gem_sources.first.multiple_remotes? && Bundler.frozen_bundle?
116
+
117
+ if @multisource_allowed
118
+ unless sources.aggregate_global_source?
119
+ 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."
120
+
121
+ Bundler::SharedHelpers.major_deprecation 2, msg
122
+ end
123
+
124
+ @sources.merged_gem_lockfile_sections!(locked_gem_sources.first)
125
+ end
126
+
110
127
  @unlock[:sources] ||= []
111
128
  @unlock[:ruby] ||= if @ruby_version && locked_ruby_version_object
112
129
  @ruby_version.diff(locked_ruby_version_object)
@@ -119,9 +136,11 @@ module Bundler
119
136
  @path_changes = converge_paths
120
137
  @source_changes = converge_sources
121
138
 
122
- unless @unlock[:lock_shared_dependencies]
123
- eager_unlock = expand_dependencies(@unlock[:gems], true)
124
- @unlock[:gems] = @locked_specs.for(eager_unlock, [], false, false, false).map(&:name)
139
+ if @unlock[:conservative]
140
+ @unlock[:gems] ||= @dependencies.map(&:name)
141
+ else
142
+ eager_unlock = (@unlock[:gems] || []).map {|name| Dependency.new(name, ">= 0") }
143
+ @unlock[:gems] = @locked_specs.for(eager_unlock, false, platforms).map(&:name).uniq
125
144
  end
126
145
 
127
146
  @dependency_changes = converge_dependencies
@@ -131,31 +150,31 @@ module Bundler
131
150
  end
132
151
 
133
152
  def gem_version_promoter
134
- @gem_version_promoter ||= begin
135
- locked_specs =
136
- if unlocking? && @locked_specs.empty? && !@lockfile_contents.empty?
137
- # Definition uses an empty set of locked_specs to indicate all gems
138
- # are unlocked, but GemVersionPromoter needs the locked_specs
139
- # for conservative comparison.
140
- Bundler::SpecSet.new(@locked_gems.specs)
141
- else
142
- @locked_specs
143
- end
144
- GemVersionPromoter.new(locked_specs, @unlock[:gems])
145
- end
153
+ @gem_version_promoter ||= GemVersionPromoter.new(@originally_locked_specs, @unlock[:gems])
154
+ end
155
+
156
+ def resolve_only_locally!
157
+ @remote = false
158
+ sources.local_only!
159
+ resolve
160
+ end
161
+
162
+ def resolve_prefering_local!
163
+ @prefer_local = true
164
+ @remote = true
165
+ sources.remote!
166
+ resolve
146
167
  end
147
168
 
148
169
  def resolve_with_cache!
149
- raise "Specs already loaded" if @specs
150
170
  sources.cached!
151
- specs
171
+ resolve
152
172
  end
153
173
 
154
174
  def resolve_remotely!
155
- return if @specs
156
175
  @remote = true
157
176
  sources.remote!
158
- specs
177
+ resolve
159
178
  end
160
179
 
161
180
  # For given dependency list returns a SpecSet with Gemspec of all the required
@@ -165,25 +184,7 @@ module Bundler
165
184
  #
166
185
  # @return [Bundler::SpecSet]
167
186
  def specs
168
- @specs ||= begin
169
- begin
170
- specs = resolve.materialize(requested_dependencies)
171
- rescue GemNotFound => e # Handle yanked gem
172
- gem_name, gem_version = extract_gem_info(e)
173
- locked_gem = @locked_specs[gem_name].last
174
- 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."
179
- end
180
- unless specs["bundler"].any?
181
- bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last
182
- specs["bundler"] = bundler
183
- end
184
-
185
- specs
186
- end
187
+ @specs ||= materialize(requested_dependencies)
187
188
  end
188
189
 
189
190
  def new_specs
@@ -195,9 +196,7 @@ module Bundler
195
196
  end
196
197
 
197
198
  def missing_specs
198
- missing = []
199
- resolve.materialize(requested_dependencies, missing)
200
- missing
199
+ resolve.materialize(requested_dependencies).missing_specs
201
200
  end
202
201
 
203
202
  def missing_specs?
@@ -206,8 +205,8 @@ module Bundler
206
205
  Bundler.ui.debug "The definition is missing #{missing.map(&:full_name)}"
207
206
  true
208
207
  rescue BundlerError => e
209
- @index = nil
210
208
  @resolve = nil
209
+ @resolver = nil
211
210
  @specs = nil
212
211
  @gem_version_promoter = nil
213
212
 
@@ -216,31 +215,39 @@ module Bundler
216
215
  end
217
216
 
218
217
  def requested_specs
219
- @requested_specs ||= begin
220
- groups = requested_groups
221
- groups.map!(&:to_sym)
222
- specs_for(groups)
223
- end
218
+ specs_for(requested_groups)
224
219
  end
225
220
 
226
221
  def requested_dependencies
227
- groups = requested_groups
228
- groups.map!(&:to_sym)
229
- dependencies_for(groups)
222
+ dependencies_for(requested_groups)
230
223
  end
231
224
 
232
225
  def current_dependencies
233
226
  dependencies.select do |d|
234
- d.should_include? && !d.gem_platforms(@platforms).empty?
227
+ d.should_include? && !d.gem_platforms([generic_local_platform]).empty?
235
228
  end
236
229
  end
237
230
 
231
+ def locked_dependencies
232
+ @locked_deps.values
233
+ end
234
+
235
+ def new_deps
236
+ @new_deps ||= @dependencies - locked_dependencies
237
+ end
238
+
239
+ def deleted_deps
240
+ @deleted_deps ||= locked_dependencies - @dependencies
241
+ end
242
+
238
243
  def specs_for(groups)
244
+ return specs if groups.empty?
239
245
  deps = dependencies_for(groups)
240
- specs.for(expand_dependencies(deps))
246
+ materialize(deps)
241
247
  end
242
248
 
243
249
  def dependencies_for(groups)
250
+ groups.map!(&:to_sym)
244
251
  current_dependencies.reject do |d|
245
252
  (d.groups & groups).empty?
246
253
  end
@@ -252,70 +259,26 @@ module Bundler
252
259
  #
253
260
  # @return [SpecSet] resolved dependencies
254
261
  def resolve
255
- @resolve ||= begin
256
- last_resolve = converge_locked_specs
257
- if Bundler.frozen_bundle?
258
- Bundler.ui.debug "Frozen, using resolution from the lockfile"
259
- last_resolve
260
- elsif !unlocking? && nothing_changed?
261
- Bundler.ui.debug("Found no changes, using resolution from the lockfile")
262
- last_resolve
262
+ @resolve ||= if Bundler.frozen_bundle?
263
+ Bundler.ui.debug "Frozen, using resolution from the lockfile"
264
+ @locked_specs
265
+ elsif !unlocking? && nothing_changed?
266
+ if deleted_deps.any?
267
+ Bundler.ui.debug("Some dependencies were deleted, using a subset of the resolution from the lockfile")
268
+ SpecSet.new(filter_specs(@locked_specs, @dependencies - deleted_deps))
263
269
  else
264
- # Run a resolve against the locally available gems
265
- Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}")
266
- expanded_dependencies = expand_dependencies(dependencies + metadata_dependencies, @remote)
267
- Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
268
- end
269
- end
270
- end
271
-
272
- def index
273
- @index ||= Index.build do |idx|
274
- dependency_names = @dependencies.map(&:name)
275
-
276
- sources.all_sources.each do |source|
277
- source.dependency_names = dependency_names - pinned_spec_names(source)
278
- idx.add_source source.specs
279
- dependency_names.concat(source.unmet_deps).uniq!
280
- end
281
-
282
- double_check_for_index(idx, dependency_names)
283
- end
284
- end
285
-
286
- # Suppose the gem Foo depends on the gem Bar. Foo exists in Source A. Bar has some versions that exist in both
287
- # sources A and B. At this point, the API request will have found all the versions of Bar in source A,
288
- # but will not have found any versions of Bar from source B, which is a problem if the requested version
289
- # of Foo specifically depends on a version of Bar that is only found in source B. This ensures that for
290
- # each spec we found, we add all possible versions from all sources to the index.
291
- def double_check_for_index(idx, dependency_names)
292
- pinned_names = pinned_spec_names
293
- loop do
294
- idxcount = idx.size
295
-
296
- names = :names # do this so we only have to traverse to get dependency_names from the index once
297
- unmet_dependency_names = lambda do
298
- return names unless names == :names
299
- new_names = sources.all_sources.map(&:dependency_names_to_double_check)
300
- return names = nil if new_names.compact!
301
- names = new_names.flatten(1).concat(dependency_names)
302
- names.uniq!
303
- names -= pinned_names
304
- names
305
- end
306
-
307
- sources.all_sources.each do |source|
308
- source.double_check_for(unmet_dependency_names)
270
+ Bundler.ui.debug("Found no changes, using resolution from the lockfile")
271
+ if @locked_gems.may_include_redundant_platform_specific_gems?
272
+ SpecSet.new(filter_specs(@locked_specs, @dependencies))
273
+ else
274
+ @locked_specs
275
+ end
309
276
  end
310
-
311
- break if idxcount == idx.size
277
+ else
278
+ Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}")
279
+ resolver.start(expanded_dependencies)
312
280
  end
313
281
  end
314
- private :double_check_for_index
315
-
316
- def has_rubygems_remotes?
317
- sources.rubygems_sources.any? {|s| s.remotes.any? }
318
- end
319
282
 
320
283
  def spec_git_paths
321
284
  sources.git_sources.map {|s| File.realpath(s.path) if File.exist?(s.path) }.compact
@@ -326,6 +289,8 @@ module Bundler
326
289
  end
327
290
 
328
291
  def lock(file, preserve_unknown_sections = false)
292
+ return if Definition.no_lock
293
+
329
294
  contents = to_lock
330
295
 
331
296
  # Convert to \r\n if the existing lock has them
@@ -336,10 +301,7 @@ module Bundler
336
301
  locked_major = @locked_bundler_version.segments.first
337
302
  current_major = Gem::Version.create(Bundler::VERSION).segments.first
338
303
 
339
- if updating_major = locked_major < current_major
340
- Bundler.ui.warn "Warning: the lockfile is being updated to Bundler #{current_major}, " \
341
- "after which you will be unable to return to Bundler #{@locked_bundler_version.segments.first}."
342
- end
304
+ updating_major = locked_major < current_major
343
305
  end
344
306
 
345
307
  preserve_unknown_sections ||= !updating_major && (Bundler.frozen_bundle? || !(unlocking? || @unlocking_bundler))
@@ -356,14 +318,6 @@ module Bundler
356
318
  end
357
319
  end
358
320
 
359
- def locked_bundler_version
360
- if @locked_bundler_version && @locked_bundler_version < Gem::Version.new(Bundler::VERSION)
361
- new_version = Bundler::VERSION
362
- end
363
-
364
- new_version || @locked_bundler_version || Bundler::VERSION
365
- end
366
-
367
321
  def locked_ruby_version
368
322
  return unless ruby_version
369
323
  if @unlock[:ruby] || !@locked_ruby_version
@@ -403,7 +357,7 @@ module Bundler
403
357
  "bundle config unset deployment"
404
358
  end
405
359
  msg << "\n\nIf this is a development machine, remove the #{Bundler.default_gemfile} " \
406
- "freeze \nby running `#{suggested_command}`."
360
+ "freeze \nby running `#{suggested_command}`." if suggested_command
407
361
  end
408
362
 
409
363
  added = []
@@ -415,44 +369,28 @@ module Bundler
415
369
  added.concat new_platforms.map {|p| "* platform: #{p}" }
416
370
  deleted.concat deleted_platforms.map {|p| "* platform: #{p}" }
417
371
 
418
- gemfile_sources = sources.lock_sources
419
-
420
- new_sources = gemfile_sources - @locked_sources
421
- deleted_sources = @locked_sources - gemfile_sources
422
-
423
- new_deps = @dependencies - @locked_deps.values
424
- deleted_deps = @locked_deps.values - @dependencies
372
+ added.concat new_deps.map {|d| "* #{pretty_dep(d)}" } if new_deps.any?
373
+ deleted.concat deleted_deps.map {|d| "* #{pretty_dep(d)}" } if deleted_deps.any?
425
374
 
426
- # Check if it is possible that the source is only changed thing
427
- if (new_deps.empty? && deleted_deps.empty?) && (!new_sources.empty? && !deleted_sources.empty?)
428
- new_sources.reject! {|source| (source.path? && source.path.exist?) || equivalent_rubygems_remotes?(source) }
429
- deleted_sources.reject! {|source| (source.path? && source.path.exist?) || equivalent_rubygems_remotes?(source) }
430
- end
375
+ both_sources = Hash.new {|h, k| h[k] = [] }
376
+ @dependencies.each {|d| both_sources[d.name][0] = d }
431
377
 
432
- if @locked_sources != gemfile_sources
433
- if new_sources.any?
434
- added.concat new_sources.map {|source| "* source: #{source}" }
435
- end
378
+ locked_dependencies.each do |d|
379
+ next if !Bundler.feature_flag.bundler_3_mode? && @locked_specs[d.name].empty?
436
380
 
437
- if deleted_sources.any?
438
- deleted.concat deleted_sources.map {|source| "* source: #{source}" }
439
- end
381
+ both_sources[d.name][1] = d
440
382
  end
441
383
 
442
- added.concat new_deps.map {|d| "* #{pretty_dep(d)}" } if new_deps.any?
443
- if deleted_deps.any?
444
- deleted.concat deleted_deps.map {|d| "* #{pretty_dep(d)}" }
445
- end
384
+ both_sources.each do |name, (dep, lock_dep)|
385
+ next if dep.nil? || lock_dep.nil?
446
386
 
447
- both_sources = Hash.new {|h, k| h[k] = [] }
448
- @dependencies.each {|d| both_sources[d.name][0] = d }
449
- @locked_deps.each {|name, d| both_sources[name][1] = d.source }
387
+ gemfile_source = dep.source || sources.default_source
388
+ lock_source = lock_dep.source || sources.default_source
389
+ next if lock_source.include?(gemfile_source)
450
390
 
451
- both_sources.each do |name, (dep, lock_source)|
452
- next if lock_source.nil? || (dep && lock_source.can_lock?(dep))
453
- gemfile_source_name = (dep && dep.source) || "no specified source"
454
- lockfile_source_name = lock_source
455
- changed << "* #{name} from `#{gemfile_source_name}` to `#{lockfile_source_name}`"
391
+ gemfile_source_name = dep.source ? gemfile_source.identifier : "no specified source"
392
+ lockfile_source_name = lock_dep.source ? lock_source.identifier : "no specified source"
393
+ changed << "* #{name} from `#{lockfile_source_name}` to `#{gemfile_source_name}`"
456
394
  end
457
395
 
458
396
  reason = change_reason
@@ -500,7 +438,7 @@ module Bundler
500
438
 
501
439
  raise ProductionError, "Your bundle only supports platforms #{@platforms.map(&:to_s)} " \
502
440
  "but your local platform is #{Bundler.local_platform}. " \
503
- "Add the current platform to the lockfile with `bundle lock --add-platform #{Bundler.local_platform}` and try again."
441
+ "Add the current platform to the lockfile with\n`bundle lock --add-platform #{Bundler.local_platform}` and try again."
504
442
  end
505
443
 
506
444
  def add_platform(platform)
@@ -519,19 +457,11 @@ module Bundler
519
457
  end
520
458
  end
521
459
 
522
- def find_resolved_spec(current_spec)
523
- specs.find_by_name_and_platform(current_spec.name, current_spec.platform)
524
- end
525
-
526
- def find_indexed_specs(current_spec)
527
- index[current_spec.name].select {|spec| spec.match_platform(current_spec.platform) }.sort_by(&:version)
528
- end
529
-
530
460
  attr_reader :sources
531
461
  private :sources
532
462
 
533
463
  def nothing_changed?
534
- !@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes && !@locked_specs_incomplete_for_platform
464
+ !@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes
535
465
  end
536
466
 
537
467
  def unlocking?
@@ -540,8 +470,78 @@ module Bundler
540
470
 
541
471
  private
542
472
 
473
+ def resolver
474
+ @resolver ||= begin
475
+ last_resolve = converge_locked_specs
476
+ remove_ruby_from_platforms_if_necessary!(current_dependencies)
477
+ Resolver.new(source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve(last_resolve), platforms)
478
+ end
479
+ end
480
+
481
+ def expanded_dependencies
482
+ @expanded_dependencies ||= dependencies + metadata_dependencies
483
+ end
484
+
485
+ def filter_specs(specs, deps)
486
+ SpecSet.new(specs).for(deps, false, platforms)
487
+ end
488
+
489
+ def materialize(dependencies)
490
+ specs = resolve.materialize(dependencies)
491
+ missing_specs = specs.missing_specs
492
+
493
+ if missing_specs.any?
494
+ missing_specs.each do |s|
495
+ locked_gem = @locked_specs[s.name].last
496
+ next if locked_gem.nil? || locked_gem.version != s.version || !@remote
497
+ raise GemNotFound, "Your bundle is locked to #{locked_gem} from #{locked_gem.source}, but that version can " \
498
+ "no longer be found in that source. That means the author of #{locked_gem} has removed it. " \
499
+ "You'll need to update your bundle to a version other than #{locked_gem} that hasn't been " \
500
+ "removed in order to install."
501
+ end
502
+
503
+ missing_specs_list = missing_specs.group_by(&:source).map do |source, missing_specs_for_source|
504
+ "#{missing_specs_for_source.map(&:full_name).join(", ")} in #{source}"
505
+ end
506
+
507
+ raise GemNotFound, "Could not find #{missing_specs_list.join(" nor ")}"
508
+ end
509
+
510
+ loop do
511
+ incomplete_specs = specs.incomplete_specs
512
+ break if incomplete_specs.empty?
513
+
514
+ Bundler.ui.debug("The lockfile does not have all gems needed for the current platform though, Bundler will still re-resolve dependencies")
515
+ @resolve = resolver.start(expanded_dependencies, :exclude_specs => incomplete_specs)
516
+ specs = resolve.materialize(dependencies)
517
+ end
518
+
519
+ bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last
520
+ specs["bundler"] = bundler
521
+
522
+ specs
523
+ end
524
+
525
+ def precompute_source_requirements_for_indirect_dependencies?
526
+ @remote && sources.non_global_rubygems_sources.all?(&:dependency_api_available?) && !sources.aggregate_global_source?
527
+ end
528
+
529
+ def pin_locally_available_names(source_requirements)
530
+ source_requirements.each_with_object({}) do |(name, original_source), new_source_requirements|
531
+ local_source = original_source.dup
532
+ local_source.local_only!
533
+
534
+ new_source_requirements[name] = if local_source.specs.search(name).any?
535
+ local_source
536
+ else
537
+ original_source
538
+ end
539
+ end
540
+ end
541
+
543
542
  def current_ruby_platform_locked?
544
543
  return false unless generic_local_platform == Gem::Platform::RUBY
544
+ return false if Bundler.settings[:force_ruby_platform] && !@platforms.include?(Gem::Platform::RUBY)
545
545
 
546
546
  current_platform_locked?
547
547
  end
@@ -574,12 +574,11 @@ module Bundler
574
574
  [@new_platform, "you added a new platform to your gemfile"],
575
575
  [@path_changes, "the gemspecs for path gems changed"],
576
576
  [@local_changes, "the gemspecs for git local gems changed"],
577
- [@locked_specs_incomplete_for_platform, "the lockfile does not have all gems needed for the current platform"],
578
577
  ].select(&:first).map(&:last).join(", ")
579
578
  end
580
579
 
581
- def pretty_dep(dep, source = false)
582
- SharedHelpers.pretty_dependency(dep, source)
580
+ def pretty_dep(dep)
581
+ SharedHelpers.pretty_dependency(dep)
583
582
  end
584
583
 
585
584
  # Check if the specs of the given source changed
@@ -592,9 +591,9 @@ module Bundler
592
591
 
593
592
  def dependencies_for_source_changed?(source, locked_source = source)
594
593
  deps_for_source = @dependencies.select {|s| s.source == source }
595
- locked_deps_for_source = @locked_deps.values.select {|dep| dep.source == locked_source }
594
+ locked_deps_for_source = locked_dependencies.select {|dep| dep.source == locked_source }
596
595
 
597
- deps_for_source.sort != locked_deps_for_source.sort
596
+ deps_for_source.uniq.sort != locked_deps_for_source.sort
598
597
  end
599
598
 
600
599
  def specs_for_source_changed?(source)
@@ -653,36 +652,11 @@ module Bundler
653
652
  end
654
653
  end
655
654
 
656
- def converge_rubygems_sources
657
- return false if Bundler.feature_flag.disable_multisource?
658
-
659
- changes = false
660
-
661
- # Get the RubyGems sources from the Gemfile.lock
662
- locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
663
- # Get the RubyGems remotes from the Gemfile
664
- actual_remotes = sources.rubygems_remotes
665
-
666
- # If there is a RubyGems source in both
667
- if !locked_gem_sources.empty? && !actual_remotes.empty?
668
- locked_gem_sources.each do |locked_gem|
669
- # Merge the remotes from the Gemfile into the Gemfile.lock
670
- changes |= locked_gem.replace_remotes(actual_remotes, Bundler.settings[:allow_deployment_source_credential_changes])
671
- end
672
- end
673
-
674
- changes
675
- end
676
-
677
655
  def converge_sources
678
- changes = false
679
-
680
- changes |= converge_rubygems_sources
681
-
682
656
  # Replace the sources from the Gemfile with the sources from the Gemfile.lock,
683
657
  # if they exist in the Gemfile.lock and are `==`. If you can't find an equivalent
684
658
  # source in the Gemfile.lock, use the one from the Gemfile.
685
- changes |= sources.replace_sources!(@locked_sources)
659
+ changes = sources.replace_sources!(@locked_sources)
686
660
 
687
661
  sources.all_sources.each do |source|
688
662
  # If the source is unlockable and the current command allows an unlock of
@@ -700,25 +674,14 @@ module Bundler
700
674
  end
701
675
 
702
676
  def converge_dependencies
703
- frozen = Bundler.frozen_bundle?
704
- (@dependencies + @locked_deps.values).each do |dep|
705
- locked_source = @locked_deps[dep.name]
706
- # This is to make sure that if bundler is installing in deployment mode and
707
- # after locked_source and sources don't match, we still use locked_source.
708
- if frozen && !locked_source.nil? &&
709
- locked_source.respond_to?(:source) && locked_source.source.instance_of?(Source::Path) && locked_source.source.path.exist?
710
- dep.source = locked_source.source
711
- elsif dep.source
677
+ changes = false
678
+
679
+ @dependencies.each do |dep|
680
+ if dep.source
712
681
  dep.source = sources.get(dep.source)
713
682
  end
714
- end
715
683
 
716
- changes = false
717
- # We want to know if all match, but don't want to check all entries
718
- # This means we need to return false if any dependency doesn't match
719
- # the lock or doesn't exist in the lock.
720
- @dependencies.each do |dependency|
721
- unless locked_dep = @locked_deps[dependency.name]
684
+ unless locked_dep = @locked_deps[dep.name]
722
685
  changes = true
723
686
  next
724
687
  end
@@ -729,11 +692,11 @@ module Bundler
729
692
  # directive, the lockfile dependencies and resolved dependencies end up
730
693
  # with a mismatch on #type. Work around that by setting the type on the
731
694
  # dep from the lockfile.
732
- locked_dep.instance_variable_set(:@type, dependency.type)
695
+ locked_dep.instance_variable_set(:@type, dep.type)
733
696
 
734
697
  # We already know the name matches from the hash lookup
735
698
  # so we only need to check the requirement now
736
- changes ||= dependency.requirement != locked_dep.requirement
699
+ changes ||= dep.requirement != locked_dep.requirement
737
700
  end
738
701
 
739
702
  changes
@@ -743,50 +706,50 @@ module Bundler
743
706
  # commonly happen if the Gemfile has changed since the lockfile was last
744
707
  # generated
745
708
  def converge_locked_specs
746
- deps = []
709
+ converged = converge_specs(@locked_specs)
747
710
 
748
- # Build a list of dependencies that are the same in the Gemfile
749
- # and Gemfile.lock. If the Gemfile modified a dependency, but
750
- # the gem in the Gemfile.lock still satisfies it, this is fine
751
- # too.
752
- @dependencies.each do |dep|
753
- locked_dep = @locked_deps[dep.name]
711
+ resolve = SpecSet.new(converged.reject {|s| @unlock[:gems].include?(s.name) })
754
712
 
755
- # If the locked_dep doesn't match the dependency we're looking for then we ignore the locked_dep
756
- locked_dep = nil unless locked_dep == dep
713
+ diff = nil
757
714
 
758
- if in_locked_deps?(dep, locked_dep) || satisfies_locked_spec?(dep)
759
- deps << dep
760
- elsif dep.source.is_a?(Source::Path) && dep.current_platform? && (!locked_dep || dep.source != locked_dep.source)
761
- @locked_specs.each do |s|
762
- @unlock[:gems] << s.name if s.source == dep.source
763
- end
715
+ # Now, we unlock any sources that do not have anymore gems pinned to it
716
+ sources.all_sources.each do |source|
717
+ next unless source.respond_to?(:unlock!)
764
718
 
765
- dep.source.unlock! if dep.source.respond_to?(:unlock!)
766
- dep.source.specs.each {|s| @unlock[:gems] << s.name }
719
+ unless resolve.any? {|s| s.source == source }
720
+ diff ||= @locked_specs.to_a - resolve.to_a
721
+ source.unlock! if diff.any? {|s| s.source == source }
767
722
  end
768
723
  end
769
724
 
770
- unlock_source_unlocks_spec = Bundler.feature_flag.unlock_source_unlocks_spec?
725
+ resolve
726
+ end
771
727
 
728
+ def converge_specs(specs)
772
729
  converged = []
773
- @locked_specs.each do |s|
774
- # Replace the locked dependency's source with the equivalent source from the Gemfile
730
+
731
+ deps = @dependencies.select do |dep|
732
+ specs[dep].any? {|s| s.satisfies?(dep) && (!dep.source || s.source.include?(dep.source)) }
733
+ end
734
+
735
+ @specs_that_changed_sources = []
736
+
737
+ specs.each do |s|
775
738
  dep = @dependencies.find {|d| s.satisfies?(d) }
776
- s.source = (dep && dep.source) || sources.get(s.source)
777
739
 
778
- # Don't add a spec to the list if its source is expired. For example,
779
- # if you change a Git gem to RubyGems.
780
- next if s.source.nil?
781
- next if @unlock[:sources].include?(s.source.name)
740
+ # Replace the locked dependency's source with the equivalent source from the Gemfile
741
+ s.source = if dep && dep.source
742
+ gemfile_source = dep.source
743
+ lockfile_source = s.source
782
744
 
783
- # XXX This is a backwards-compatibility fix to preserve the ability to
784
- # unlock a single gem by passing its name via `--source`. See issue #3759
785
- # TODO: delete in Bundler 2
786
- next if unlock_source_unlocks_spec && @unlock[:sources].include?(s.name)
745
+ @specs_that_changed_sources << s if gemfile_source != lockfile_source
787
746
 
788
- # If the spec is from a path source and it doesn't exist anymore
789
- # then we unlock it.
747
+ gemfile_source
748
+ else
749
+ sources.get_with_fallback(s.source)
750
+ end
751
+
752
+ next if @unlock[:sources].include?(s.source.name)
790
753
 
791
754
  # Path sources have special logic
792
755
  if s.source.instance_of?(Source::Path) || s.source.instance_of?(Source::Gemspec)
@@ -795,8 +758,8 @@ module Bundler
795
758
  rescue PathError, GitError
796
759
  # if we won't need the source (according to the lockfile),
797
760
  # don't error if the path/git source isn't available
798
- next if @locked_specs.
799
- for(requested_dependencies, [], false, true, false).
761
+ next if specs.
762
+ for(requested_dependencies, false).
800
763
  none? {|locked_spec| locked_spec.source == s.source }
801
764
 
802
765
  raise
@@ -811,116 +774,56 @@ module Bundler
811
774
  s.dependencies.replace(new_spec.dependencies)
812
775
  end
813
776
 
814
- converged << s
815
- end
816
-
817
- resolve = SpecSet.new(converged)
818
- @locked_specs_incomplete_for_platform = !resolve.for(expand_dependencies(requested_dependencies & deps), @unlock[:gems], true, true)
819
- resolve = resolve.for(expand_dependencies(deps, true), @unlock[:gems], false, false, false)
820
- diff = nil
821
-
822
- # Now, we unlock any sources that do not have anymore gems pinned to it
823
- sources.all_sources.each do |source|
824
- next unless source.respond_to?(:unlock!)
825
-
826
- unless resolve.any? {|s| s.source == source }
827
- diff ||= @locked_specs.to_a - resolve.to_a
828
- source.unlock! if diff.any? {|s| s.source == source }
777
+ if dep.nil? && requested_dependencies.find {|d| s.name == d.name }
778
+ @unlock[:gems] << s.name
779
+ else
780
+ converged << s
829
781
  end
830
782
  end
831
783
 
832
- resolve
833
- end
834
-
835
- def in_locked_deps?(dep, locked_dep)
836
- # Because the lockfile can't link a dep to a specific remote, we need to
837
- # treat sources as equivalent anytime the locked dep has all the remotes
838
- # that the Gemfile dep does.
839
- locked_dep && locked_dep.source && dep.source && locked_dep.source.include?(dep.source)
840
- end
841
-
842
- def satisfies_locked_spec?(dep)
843
- @locked_specs[dep].any? {|s| s.satisfies?(dep) && (!dep.source || s.source.include?(dep.source)) }
784
+ filter_specs(converged, deps)
844
785
  end
845
786
 
846
787
  def metadata_dependencies
847
- @metadata_dependencies ||= begin
848
- ruby_versions = ruby_version_requirements(@ruby_version)
849
- [
850
- Dependency.new("Ruby\0", ruby_versions),
851
- Dependency.new("RubyGems\0", Gem::VERSION),
852
- ]
853
- end
854
- end
855
-
856
- def ruby_version_requirements(ruby_version)
857
- return [] unless ruby_version
858
- if ruby_version.patchlevel
859
- [ruby_version.to_gem_version_with_patchlevel]
860
- else
861
- ruby_version.versions.map do |version|
862
- requirement = Gem::Requirement.new(version)
863
- if requirement.exact?
864
- "~> #{version}.0"
865
- else
866
- requirement
867
- end
868
- end
869
- end
870
- end
871
-
872
- def expand_dependencies(dependencies, remote = false)
873
- deps = []
874
- dependencies.each do |dep|
875
- dep = Dependency.new(dep, ">= 0") unless dep.respond_to?(:name)
876
- next unless remote || dep.current_platform?
877
- target_platforms = dep.gem_platforms(remote ? @platforms : [generic_local_platform])
878
- deps += expand_dependency_with_platforms(dep, target_platforms)
879
- end
880
- deps
881
- end
882
-
883
- def expand_dependency_with_platforms(dep, platforms)
884
- platforms.map do |p|
885
- DepProxy.get_proxy(dep, p)
886
- end
788
+ @metadata_dependencies ||= [
789
+ Dependency.new("Ruby\0", Gem.ruby_version),
790
+ Dependency.new("RubyGems\0", Gem::VERSION),
791
+ ]
887
792
  end
888
793
 
889
794
  def source_requirements
890
- # Load all specs from remote sources
891
- index
892
-
893
795
  # Record the specs available in each gem's source, so that those
894
796
  # specs will be available later when the resolver knows where to
895
797
  # look for that gemspec (or its dependencies)
896
- default = sources.default_source
897
- source_requirements = { :default => default }
898
- default = nil unless Bundler.feature_flag.disable_multisource?
899
- dependencies.each do |dep|
900
- next unless source = dep.source || default
901
- source_requirements[dep.name] = source
798
+ source_requirements = if precompute_source_requirements_for_indirect_dependencies?
799
+ all_requirements = source_map.all_requirements
800
+ all_requirements = pin_locally_available_names(all_requirements) if @prefer_local
801
+ { :default => sources.default_source }.merge(all_requirements)
802
+ else
803
+ { :default => Source::RubygemsAggregate.new(sources, source_map) }.merge(source_map.direct_requirements)
902
804
  end
805
+ source_requirements.merge!(source_map.locked_requirements) unless @remote
903
806
  metadata_dependencies.each do |dep|
904
807
  source_requirements[dep.name] = sources.metadata_source
905
808
  end
906
- source_requirements[:default_bundler] = source_requirements["bundler"] || source_requirements[:default]
809
+ source_requirements[:default_bundler] = source_requirements["bundler"] || sources.default_source
907
810
  source_requirements["bundler"] = sources.metadata_source # needs to come last to override
811
+ verify_changed_sources!
908
812
  source_requirements
909
813
  end
910
814
 
911
- def pinned_spec_names(skip = nil)
912
- pinned_names = []
913
- default = Bundler.feature_flag.disable_multisource? && sources.default_source
914
- @dependencies.each do |dep|
915
- next unless dep_source = dep.source || default
916
- next if dep_source == skip
917
- pinned_names << dep.name
815
+ def verify_changed_sources!
816
+ @specs_that_changed_sources.each do |s|
817
+ if s.source.specs.search(s.name).empty?
818
+ raise GemNotFound, "Could not find gem '#{s.name}' in #{s.source}"
819
+ end
918
820
  end
919
- pinned_names
920
821
  end
921
822
 
922
823
  def requested_groups
923
- groups - Bundler.settings[:without] - @optional_groups + Bundler.settings[:with]
824
+ values = groups - Bundler.settings[:without] - @optional_groups + Bundler.settings[:with]
825
+ values &= Bundler.settings[:only] unless Bundler.settings[:only].empty?
826
+ values
924
827
  end
925
828
 
926
829
  def lockfiles_equal?(current, proposed, preserve_unknown_sections)
@@ -936,12 +839,6 @@ module Bundler
936
839
  current == proposed
937
840
  end
938
841
 
939
- def extract_gem_info(error)
940
- # This method will extract the error message like "Could not find foo-1.2.3 in any of the sources"
941
- # to an array. The first element will be the gem name (e.g. foo), the second will be the version number.
942
- error.message.scan(/Could not find (\w+)-(\d+(?:\.\d+)+)/).flatten
943
- end
944
-
945
842
  def compute_requires
946
843
  dependencies.reduce({}) do |requires, dep|
947
844
  next requires unless dep.should_include?
@@ -953,25 +850,26 @@ module Bundler
953
850
  end
954
851
  end
955
852
 
956
- def additional_base_requirements_for_resolve
957
- return [] unless @locked_gems && Bundler.feature_flag.only_update_to_newer_versions?
958
- dependencies_by_name = dependencies.inject({}) {|memo, dep| memo.update(dep.name => dep) }
959
- @locked_gems.specs.reduce({}) do |requirements, locked_spec|
960
- name = locked_spec.name
961
- dependency = dependencies_by_name[name]
962
- next requirements unless dependency
963
- next requirements if @locked_gems.dependencies[name] != dependency
964
- next requirements if dependency.source.is_a?(Source::Path)
965
- dep = Gem::Dependency.new(name, ">= #{locked_spec.version}")
966
- requirements[name] = DepProxy.get_proxy(dep, locked_spec.platform)
967
- requirements
968
- end.values
853
+ def additional_base_requirements_for_resolve(last_resolve)
854
+ return [] unless @locked_gems && unlocking? && !sources.expired_sources?(@locked_gems.sources)
855
+ converge_specs(@originally_locked_specs - last_resolve).map do |locked_spec|
856
+ Dependency.new(locked_spec.name, ">= #{locked_spec.version}")
857
+ end.uniq
969
858
  end
970
859
 
971
- def equivalent_rubygems_remotes?(source)
972
- return false unless source.is_a?(Source::Rubygems)
860
+ def remove_ruby_from_platforms_if_necessary!(dependencies)
861
+ return if Bundler.frozen_bundle? ||
862
+ Bundler.local_platform == Gem::Platform::RUBY ||
863
+ !platforms.include?(Gem::Platform::RUBY) ||
864
+ (@new_platform && platforms.last == Gem::Platform::RUBY) ||
865
+ !@originally_locked_specs.incomplete_ruby_specs?(dependencies)
866
+
867
+ remove_platform(Gem::Platform::RUBY)
868
+ add_current_platform
869
+ end
973
870
 
974
- Bundler.settings[:allow_deployment_source_credential_changes] && source.equivalent_remotes?(sources.rubygems_remotes)
871
+ def source_map
872
+ @source_map ||= SourceMap.new(sources, dependencies, @locked_specs)
975
873
  end
976
874
  end
977
875
  end