bundler 2.3.17 → 2.3.20

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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +76 -0
  3. data/lib/bundler/build_metadata.rb +2 -2
  4. data/lib/bundler/cli/common.rb +1 -0
  5. data/lib/bundler/cli/install.rb +5 -2
  6. data/lib/bundler/cli/outdated.rb +12 -3
  7. data/lib/bundler/cli/platform.rb +1 -1
  8. data/lib/bundler/cli.rb +5 -3
  9. data/lib/bundler/compact_index_client/updater.rb +16 -3
  10. data/lib/bundler/definition.rb +111 -28
  11. data/lib/bundler/dependency.rb +2 -1
  12. data/lib/bundler/dsl.rb +3 -3
  13. data/lib/bundler/fetcher.rb +6 -6
  14. data/lib/bundler/gem_helpers.rb +8 -1
  15. data/lib/bundler/incomplete_specification.rb +12 -0
  16. data/lib/bundler/index.rb +10 -12
  17. data/lib/bundler/installer/standalone.rb +1 -1
  18. data/lib/bundler/installer.rb +8 -1
  19. data/lib/bundler/lazy_specification.rb +30 -21
  20. data/lib/bundler/lockfile_parser.rb +4 -0
  21. data/lib/bundler/man/bundle-add.1 +1 -1
  22. data/lib/bundler/man/bundle-binstubs.1 +1 -1
  23. data/lib/bundler/man/bundle-cache.1 +7 -1
  24. data/lib/bundler/man/bundle-cache.1.ronn +7 -0
  25. data/lib/bundler/man/bundle-check.1 +1 -1
  26. data/lib/bundler/man/bundle-clean.1 +1 -1
  27. data/lib/bundler/man/bundle-config.1 +15 -5
  28. data/lib/bundler/man/bundle-config.1.ronn +12 -5
  29. data/lib/bundler/man/bundle-doctor.1 +1 -1
  30. data/lib/bundler/man/bundle-exec.1 +2 -2
  31. data/lib/bundler/man/bundle-exec.1.ronn +1 -1
  32. data/lib/bundler/man/bundle-gem.1 +1 -1
  33. data/lib/bundler/man/bundle-info.1 +1 -1
  34. data/lib/bundler/man/bundle-init.1 +1 -1
  35. data/lib/bundler/man/bundle-inject.1 +5 -2
  36. data/lib/bundler/man/bundle-inject.1.ronn +3 -1
  37. data/lib/bundler/man/bundle-install.1 +5 -1
  38. data/lib/bundler/man/bundle-install.1.ronn +6 -0
  39. data/lib/bundler/man/bundle-list.1 +1 -1
  40. data/lib/bundler/man/bundle-lock.1 +1 -1
  41. data/lib/bundler/man/bundle-open.1 +1 -1
  42. data/lib/bundler/man/bundle-outdated.1 +1 -1
  43. data/lib/bundler/man/bundle-platform.1 +16 -6
  44. data/lib/bundler/man/bundle-platform.1.ronn +14 -7
  45. data/lib/bundler/man/bundle-pristine.1 +1 -1
  46. data/lib/bundler/man/bundle-remove.1 +1 -1
  47. data/lib/bundler/man/bundle-show.1 +1 -1
  48. data/lib/bundler/man/bundle-update.1 +1 -1
  49. data/lib/bundler/man/bundle-viz.1 +4 -1
  50. data/lib/bundler/man/bundle-viz.1.ronn +2 -0
  51. data/lib/bundler/man/bundle.1 +6 -9
  52. data/lib/bundler/man/bundle.1.ronn +5 -6
  53. data/lib/bundler/man/gemfile.5 +77 -47
  54. data/lib/bundler/man/gemfile.5.ronn +75 -54
  55. data/lib/bundler/remote_specification.rb +5 -4
  56. data/lib/bundler/resolver/spec_group.rb +5 -4
  57. data/lib/bundler/resolver.rb +10 -7
  58. data/lib/bundler/ruby_dsl.rb +1 -1
  59. data/lib/bundler/ruby_version.rb +5 -5
  60. data/lib/bundler/rubygems_ext.rb +13 -0
  61. data/lib/bundler/rubygems_gem_installer.rb +19 -12
  62. data/lib/bundler/runtime.rb +0 -1
  63. data/lib/bundler/settings.rb +1 -0
  64. data/lib/bundler/source/metadata.rb +1 -1
  65. data/lib/bundler/source/rubygems.rb +12 -6
  66. data/lib/bundler/source_list.rb +4 -0
  67. data/lib/bundler/spec_set.rb +26 -31
  68. data/lib/bundler/version.rb +1 -1
  69. data/lib/bundler.rb +1 -0
  70. metadata +4 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 364d4bc2c2c1f342aa034417b9e30074317878931bf34e90ddf6c42d3ae539c2
4
- data.tar.gz: dad782afd5246e703b67d004c7282a89132f0ebe699d8e8306387fb8db179193
3
+ metadata.gz: d496688c0b2262b47e1df23183882af5e469ca4a70eb40bf962a9d1583409748
4
+ data.tar.gz: '087ba876a0582ff5200d5bdb766e4b2722e5c9ba0ff433b5f65c6e67dd8387b0'
5
5
  SHA512:
6
- metadata.gz: 463cc7534f4164ae4d2e4c67d1ed57dcc9a40494c496f0b06e11ac8f2b3599ea0dbc74be8772a98abb2d09c119db2da8f1d85cde6bafe83319051de3e24a46f2
7
- data.tar.gz: 61b997e77634dc3a7d812adb805f899bb8bbae48bd25aad2884906c818d21853e76fd0db8bfbd95ee79689c25567e346e9c468fbe1321768c2614518f0e78356
6
+ metadata.gz: a9706bc28946dc9fbd2eaa60dad29eddf99f4d614c04d74b2524a3f2382290d546a634e2b6d1a072a5f5197a819af4c31ca1621cf1571b530f0672c43bb40e01
7
+ data.tar.gz: 660efd70ee1f43363d317ac3efd33c6f870987e1039991208258230983856b429ddcf9ea7763165452fa0f92a21f46e26c76fe279035be5a0fa0cee401340c80
data/CHANGELOG.md CHANGED
@@ -1,3 +1,79 @@
1
+ # 2.3.20 (August 10, 2022)
2
+
3
+ ## Enhancements:
4
+
5
+ - Consistently ignore patchlevel when reporting `bundle platform --ruby` [#5793](https://github.com/rubygems/rubygems/pull/5793)
6
+ - Make `--standalone` play nice with `--local` [#5762](https://github.com/rubygems/rubygems/pull/5762)
7
+ - Implement `bundle install --prefer-local` [#5761](https://github.com/rubygems/rubygems/pull/5761)
8
+
9
+ ## Bug fixes:
10
+
11
+ - Fix regression where yanked gems are now unintentionally updated when other gems are unlocked [#5812](https://github.com/rubygems/rubygems/pull/5812)
12
+ - Automatically remove "ruby" from lockfile if incomplete [#5807](https://github.com/rubygems/rubygems/pull/5807)
13
+ - Fix `bundle outdated --strict` showing too many outdated gems [#5798](https://github.com/rubygems/rubygems/pull/5798)
14
+ - Don't discard candidates matching Ruby metadata [#5784](https://github.com/rubygems/rubygems/pull/5784)
15
+ - Fix `bundle outdated` crash in debug mode [#5796](https://github.com/rubygems/rubygems/pull/5796)
16
+ - Fix `ruby` DSL requirement matching for head and prerelease rubies [#5766](https://github.com/rubygems/rubygems/pull/5766)
17
+
18
+ ## Documentation:
19
+
20
+ - Update Bundler support policies to match what we do these days [#5813](https://github.com/rubygems/rubygems/pull/5813)
21
+ - Fix arguments for bundle-config(1) docs [#5804](https://github.com/rubygems/rubygems/pull/5804)
22
+ - Improve `bundle platform` man page [#5788](https://github.com/rubygems/rubygems/pull/5788)
23
+ - Remove `bundle cache` from deprecated commands list, and consistently link to `bundle cache` in man pages [#5783](https://github.com/rubygems/rubygems/pull/5783)
24
+ - Add package/pack aliases to man pages for cache [#5785](https://github.com/rubygems/rubygems/pull/5785)
25
+ - Add deprecation notice of bundle console [#5775](https://github.com/rubygems/rubygems/pull/5775)
26
+
27
+ # 2.3.19 (July 27, 2022)
28
+
29
+ ## Enhancements:
30
+
31
+ - Add `Bundler.settings[:only]` to install gems of the specified groups [#5759](https://github.com/rubygems/rubygems/pull/5759)
32
+ - Add `ignore_funding_requests` config flag [#5767](https://github.com/rubygems/rubygems/pull/5767)
33
+ - Prevent random crash when autoloading `Pathname` [#5769](https://github.com/rubygems/rubygems/pull/5769)
34
+ - Don't corrupt lockfile when user moves a gem that's already in the lockfile to an incorrect source by mistake [#5070](https://github.com/rubygems/rubygems/pull/5070)
35
+ - Reconcile error/warning message for multiple global sources with documentation [#5741](https://github.com/rubygems/rubygems/pull/5741)
36
+ - Improve error message when gems cannot be found to include the source for each gem [#5729](https://github.com/rubygems/rubygems/pull/5729)
37
+
38
+ ## Bug fixes:
39
+
40
+ - Fix yet another TruffleRuby platform selection regression [#5746](https://github.com/rubygems/rubygems/pull/5746)
41
+ - Show a proper error if extension dir is not writable [#5726](https://github.com/rubygems/rubygems/pull/5726)
42
+
43
+ ## Performance:
44
+
45
+ - Lazily check incomplete lockfile to improve performance [#5546](https://github.com/rubygems/rubygems/pull/5546)
46
+
47
+ ## Documentation:
48
+
49
+ - Add deprecation notice of bundle inject [#5776](https://github.com/rubygems/rubygems/pull/5776)
50
+ - Add deprecation notice of `bundle viz` to man pages [#5765](https://github.com/rubygems/rubygems/pull/5765)
51
+ - Update command example in `bundle exec` man page [#5754](https://github.com/rubygems/rubygems/pull/5754)
52
+ - Remove bundle show from obsolete commands [#5753](https://github.com/rubygems/rubygems/pull/5753)
53
+ - Improve global source(s) documentation [#5732](https://github.com/rubygems/rubygems/pull/5732)
54
+ - Use https protocol for URLs for config mirror in bundler man [#5722](https://github.com/rubygems/rubygems/pull/5722)
55
+
56
+ # 2.3.18 (July 14, 2022)
57
+
58
+ ## Enhancements:
59
+
60
+ - Extend `gem` DSL with a `force_ruby_platform` option [#4049](https://github.com/rubygems/rubygems/pull/4049)
61
+
62
+ ## Bug fixes:
63
+
64
+ - Fix misleading error if compact index cannot be copied [#5709](https://github.com/rubygems/rubygems/pull/5709)
65
+ - Fix TruffleRuby no longer able to install lockfiles generated with other implementations [#5711](https://github.com/rubygems/rubygems/pull/5711)
66
+ - Fix TruffleRuby no longer installing lockfiles using "ruby" platform correctly [#5694](https://github.com/rubygems/rubygems/pull/5694)
67
+ - Fix crash when updating vendor cache of default gems [#5679](https://github.com/rubygems/rubygems/pull/5679)
68
+
69
+ ## Performance:
70
+
71
+ - Speed up `bundler/setup` by using the raw `Gemfile.lock` information without extra processing whenever possible [#5695](https://github.com/rubygems/rubygems/pull/5695)
72
+
73
+ ## Documentation:
74
+
75
+ - Use modern style hashes in Gemfile DSL docs [#5674](https://github.com/rubygems/rubygems/pull/5674)
76
+
1
77
  # 2.3.17 (June 29, 2022)
2
78
 
3
79
  ## Enhancements:
@@ -4,8 +4,8 @@ module Bundler
4
4
  # Represents metadata from when the Bundler gem was built.
5
5
  module BuildMetadata
6
6
  # begin ivars
7
- @built_at = "2022-06-29".freeze
8
- @git_commit_sha = "539b20c172".freeze
7
+ @built_at = "2022-08-10".freeze
8
+ @git_commit_sha = "4fd2813f54".freeze
9
9
  @release = true
10
10
  # end ivars
11
11
 
@@ -15,6 +15,7 @@ module Bundler
15
15
  end
16
16
 
17
17
  def self.output_fund_metadata_summary
18
+ return if Bundler.settings["ignore_funding_requests"]
18
19
  definition = Bundler.definition
19
20
  current_dependencies = definition.requested_dependencies
20
21
  current_specs = definition.specs
@@ -147,8 +147,11 @@ module Bundler
147
147
  def normalize_settings
148
148
  Bundler.settings.set_command_option :path, nil if options[:system]
149
149
  Bundler.settings.set_command_option_if_given :path, options[:path]
150
- Bundler.settings.temporary(:path_relative_to_cwd => false) do
151
- Bundler.settings.set_command_option :path, "bundle" if options["standalone"] && Bundler.settings[:path].nil?
150
+
151
+ if options["standalone"] && Bundler.settings[:path].nil? && !options["local"]
152
+ Bundler.settings.temporary(:path_relative_to_cwd => false) do
153
+ Bundler.settings.set_command_option :path, "bundle"
154
+ end
152
155
  end
153
156
 
154
157
  bin_option = options["binstubs"]
@@ -46,7 +46,7 @@ module Bundler
46
46
 
47
47
  Bundler::CLI::Common.configure_gem_version_promoter(
48
48
  Bundler.definition,
49
- options
49
+ options.merge(:strict => @strict)
50
50
  )
51
51
 
52
52
  definition_resolution = proc do
@@ -129,6 +129,12 @@ module Bundler
129
129
 
130
130
  private
131
131
 
132
+ def loaded_from_for(spec)
133
+ return unless spec.respond_to?(:loaded_from)
134
+
135
+ spec.loaded_from
136
+ end
137
+
132
138
  def groups_text(group_text, groups)
133
139
  "#{group_text}#{groups.split(",").size > 1 ? "s" : ""} \"#{groups}\""
134
140
  end
@@ -184,7 +190,10 @@ module Bundler
184
190
 
185
191
  def print_gem(current_spec, active_spec, dependency, groups)
186
192
  spec_version = "#{active_spec.version}#{active_spec.git_version}"
187
- spec_version += " (from #{active_spec.loaded_from})" if Bundler.ui.debug? && active_spec.loaded_from
193
+ if Bundler.ui.debug?
194
+ loaded_from = loaded_from_for(active_spec)
195
+ spec_version += " (from #{loaded_from})" if loaded_from
196
+ end
188
197
  current_version = "#{current_spec.version}#{current_spec.git_version}"
189
198
 
190
199
  if dependency && dependency.specific?
@@ -211,7 +220,7 @@ module Bundler
211
220
  dependency = dependency.requirement if dependency
212
221
 
213
222
  ret_val = [active_spec.name, current_version, spec_version, dependency.to_s, groups.to_s]
214
- ret_val << active_spec.loaded_from.to_s if Bundler.ui.debug?
223
+ ret_val << loaded_from_for(active_spec).to_s if Bundler.ui.debug?
215
224
  ret_val
216
225
  end
217
226
 
@@ -9,7 +9,7 @@ module Bundler
9
9
 
10
10
  def run
11
11
  platforms, ruby_version = Bundler.ui.silence do
12
- locked_ruby_version = Bundler.locked_gems && Bundler.locked_gems.ruby_version
12
+ locked_ruby_version = Bundler.locked_gems && Bundler.locked_gems.ruby_version.gsub(/p\d+\Z/, "")
13
13
  gemfile_ruby_version = Bundler.definition.ruby_version && Bundler.definition.ruby_version.single_version_string
14
14
  [Bundler.definition.platforms.map {|p| "* #{p}" },
15
15
  locked_ruby_version || gemfile_ruby_version]
data/lib/bundler/cli.rb CHANGED
@@ -218,6 +218,8 @@ module Bundler
218
218
  "Specify the number of jobs to run in parallel"
219
219
  method_option "local", :type => :boolean, :banner =>
220
220
  "Do not attempt to fetch gems remotely and use the gem cache instead"
221
+ method_option "prefer-local", :type => :boolean, :banner =>
222
+ "Only attempt to fetch gems remotely if not present locally, even if newer versions are available remotely"
221
223
  method_option "no-cache", :type => :boolean, :banner =>
222
224
  "Don't update the existing gem cache."
223
225
  method_option "redownload", :type => :boolean, :aliases => "--force", :banner =>
@@ -236,7 +238,7 @@ module Bundler
236
238
  "Install to the system location ($BUNDLE_PATH or $GEM_HOME) even if the bundle was previously installed somewhere else for this application"
237
239
  method_option "trust-policy", :alias => "P", :type => :string, :banner =>
238
240
  "Gem trust policy (like gem install -P). Must be one of " +
239
- Bundler.rubygems.security_policy_keys.join("|")
241
+ Bundler.rubygems.security_policy_keys.join("|")
240
242
  method_option "without", :type => :array, :banner =>
241
243
  "Exclude gems that are part of the specified named group."
242
244
  method_option "with", :type => :array, :banner =>
@@ -399,9 +401,9 @@ module Bundler
399
401
  "Do not attempt to fetch gems remotely and use the gem cache instead"
400
402
  method_option "pre", :type => :boolean, :banner => "Check for newer pre-release gems"
401
403
  method_option "source", :type => :array, :banner => "Check against a specific source"
402
- method_option "filter-strict", :type => :boolean, :banner =>
404
+ method_option "filter-strict", :type => :boolean, :aliases => "--strict", :banner =>
403
405
  "Only list newer versions allowed by your Gemfile requirements"
404
- method_option "strict", :type => :boolean, :aliases => "--update-strict", :banner =>
406
+ method_option "update-strict", :type => :boolean, :banner =>
405
407
  "Strict conservative resolution, do not allow any gem to be updated past latest --patch | --minor | --major"
406
408
  method_option "minor", :type => :boolean, :banner => "Prefer updating only to next minor version"
407
409
  method_option "major", :type => :boolean, :banner => "Prefer updating to next major version (default)"
@@ -31,9 +31,8 @@ module Bundler
31
31
 
32
32
  # first try to fetch any new bytes on the existing file
33
33
  if retrying.nil? && local_path.file?
34
- SharedHelpers.filesystem_access(local_temp_path) do
35
- FileUtils.cp local_path, local_temp_path
36
- end
34
+ copy_file local_path, local_temp_path
35
+
37
36
  headers["If-None-Match"] = etag_for(local_temp_path)
38
37
  headers["Range"] =
39
38
  if local_temp_path.size.nonzero?
@@ -98,6 +97,20 @@ module Bundler
98
97
  SharedHelpers.digest(:MD5).hexdigest(File.read(path))
99
98
  end
100
99
  end
100
+
101
+ private
102
+
103
+ def copy_file(source, dest)
104
+ SharedHelpers.filesystem_access(source, :read) do
105
+ File.open(source, "r") do |s|
106
+ SharedHelpers.filesystem_access(dest, :write) do
107
+ File.open(dest, "wb", s.stat.mode) do |f|
108
+ IO.copy_stream(s, f)
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
101
114
  end
102
115
  end
103
116
  end
@@ -70,6 +70,7 @@ module Bundler
70
70
  @unlock = unlock
71
71
  @optional_groups = optional_groups
72
72
  @remote = false
73
+ @prefer_local = false
73
74
  @specs = nil
74
75
  @ruby_version = ruby_version
75
76
  @gemfiles = gemfiles
@@ -138,13 +139,13 @@ module Bundler
138
139
  @unlock[:gems] ||= @dependencies.map(&:name)
139
140
  else
140
141
  eager_unlock = expand_dependencies(@unlock[:gems] || [], true)
141
- @unlock[:gems] = @locked_specs.for(eager_unlock, false, false).map(&:name)
142
+ @unlock[:gems] = @locked_specs.for(eager_unlock, false, platforms).map(&:name)
142
143
  end
143
144
 
144
145
  @dependency_changes = converge_dependencies
145
146
  @local_changes = converge_locals
146
147
 
147
- @locked_specs_incomplete_for_platform = !@locked_specs.for(requested_dependencies & expand_dependencies(locked_dependencies), true, true)
148
+ @reresolve = nil
148
149
 
149
150
  @requires = compute_requires
150
151
  end
@@ -170,6 +171,13 @@ module Bundler
170
171
  resolve
171
172
  end
172
173
 
174
+ def resolve_prefering_local!
175
+ @prefer_local = true
176
+ @remote = true
177
+ sources.remote!
178
+ resolve
179
+ end
180
+
173
181
  def resolve_with_cache!
174
182
  sources.cached!
175
183
  resolve
@@ -235,6 +243,14 @@ module Bundler
235
243
  @locked_deps.values
236
244
  end
237
245
 
246
+ def new_deps
247
+ @new_deps ||= @dependencies - locked_dependencies
248
+ end
249
+
250
+ def deleted_deps
251
+ @deleted_deps ||= locked_dependencies - @dependencies
252
+ end
253
+
238
254
  def specs_for(groups)
239
255
  return specs if groups.empty?
240
256
  deps = dependencies_for(groups)
@@ -259,14 +275,20 @@ module Bundler
259
275
  Bundler.ui.debug "Frozen, using resolution from the lockfile"
260
276
  @locked_specs
261
277
  elsif !unlocking? && nothing_changed?
262
- Bundler.ui.debug("Found no changes, using resolution from the lockfile")
263
- SpecSet.new(filter_specs(@locked_specs, @dependencies.select {|dep| @locked_specs[dep].any? }))
278
+ if deleted_deps.any?
279
+ Bundler.ui.debug("Some dependencies were deleted, using a subset of the resolution from the lockfile")
280
+ SpecSet.new(filter_specs(@locked_specs, @dependencies - deleted_deps))
281
+ else
282
+ Bundler.ui.debug("Found no changes, using resolution from the lockfile")
283
+ if @locked_gems.may_include_redundant_platform_specific_gems?
284
+ SpecSet.new(filter_specs(@locked_specs, @dependencies))
285
+ else
286
+ @locked_specs
287
+ end
288
+ end
264
289
  else
265
- last_resolve = converge_locked_specs
266
- # Run a resolve against the locally available gems
267
290
  Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}")
268
- expanded_dependencies = expand_dependencies(dependencies + metadata_dependencies, true)
269
- Resolver.resolve(expanded_dependencies, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
291
+ @reresolve = reresolve
270
292
  end
271
293
  end
272
294
 
@@ -359,9 +381,6 @@ module Bundler
359
381
  added.concat new_platforms.map {|p| "* platform: #{p}" }
360
382
  deleted.concat deleted_platforms.map {|p| "* platform: #{p}" }
361
383
 
362
- new_deps = @dependencies - locked_dependencies
363
- deleted_deps = locked_dependencies - @dependencies
364
-
365
384
  added.concat new_deps.map {|d| "* #{pretty_dep(d)}" } if new_deps.any?
366
385
  deleted.concat deleted_deps.map {|d| "* #{pretty_dep(d)}" } if deleted_deps.any?
367
386
 
@@ -454,7 +473,7 @@ module Bundler
454
473
  private :sources
455
474
 
456
475
  def nothing_changed?
457
- !@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes && !@locked_specs_incomplete_for_platform
476
+ !@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes
458
477
  end
459
478
 
460
479
  def unlocking?
@@ -463,8 +482,15 @@ module Bundler
463
482
 
464
483
  private
465
484
 
485
+ def reresolve
486
+ last_resolve = converge_locked_specs
487
+ remove_ruby_from_platforms_if_necessary!(dependencies)
488
+ expanded_dependencies = expand_dependencies(dependencies + metadata_dependencies, true)
489
+ Resolver.resolve(expanded_dependencies, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
490
+ end
491
+
466
492
  def filter_specs(specs, deps)
467
- SpecSet.new(specs).for(expand_dependencies(deps, true), false, false)
493
+ SpecSet.new(specs).for(expand_dependencies(deps, true), false, platforms)
468
494
  end
469
495
 
470
496
  def materialize(dependencies)
@@ -481,14 +507,27 @@ module Bundler
481
507
  "removed in order to install."
482
508
  end
483
509
 
484
- raise GemNotFound, "Could not find #{missing_specs.map(&:full_name).join(", ")} in any of the sources"
510
+ missing_specs_list = missing_specs.group_by(&:source).map do |source, missing_specs_for_source|
511
+ "#{missing_specs_for_source.map(&:full_name).join(", ")} in #{source}"
512
+ end
513
+
514
+ raise GemNotFound, "Could not find #{missing_specs_list.join(" nor ")}"
485
515
  end
486
516
 
487
- unless specs["bundler"].any?
488
- bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last
489
- specs["bundler"] = bundler
517
+ if @reresolve.nil?
518
+ incomplete_specs = specs.incomplete_specs
519
+
520
+ if incomplete_specs.any?
521
+ Bundler.ui.debug("The lockfile does not have all gems needed for the current platform though, Bundler will still re-resolve dependencies")
522
+ @unlock[:gems].concat(incomplete_specs.map(&:name))
523
+ @resolve = reresolve
524
+ specs = resolve.materialize(dependencies)
525
+ end
490
526
  end
491
527
 
528
+ bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last
529
+ specs["bundler"] = bundler
530
+
492
531
  specs
493
532
  end
494
533
 
@@ -496,6 +535,19 @@ module Bundler
496
535
  @remote && sources.non_global_rubygems_sources.all?(&:dependency_api_available?) && !sources.aggregate_global_source?
497
536
  end
498
537
 
538
+ def pin_locally_available_names(source_requirements)
539
+ source_requirements.each_with_object({}) do |(name, original_source), new_source_requirements|
540
+ local_source = original_source.dup
541
+ local_source.local_only!
542
+
543
+ new_source_requirements[name] = if local_source.specs.search(name).any?
544
+ local_source
545
+ else
546
+ original_source
547
+ end
548
+ end
549
+ end
550
+
499
551
  def current_ruby_platform_locked?
500
552
  return false unless generic_local_platform == Gem::Platform::RUBY
501
553
  return false if Bundler.settings[:force_ruby_platform] && !@platforms.include?(Gem::Platform::RUBY)
@@ -531,7 +583,6 @@ module Bundler
531
583
  [@new_platform, "you added a new platform to your gemfile"],
532
584
  [@path_changes, "the gemspecs for path gems changed"],
533
585
  [@local_changes, "the gemspecs for git local gems changed"],
534
- [@locked_specs_incomplete_for_platform, "the lockfile does not have all gems needed for the current platform"],
535
586
  ].select(&:first).map(&:last).join(", ")
536
587
  end
537
588
 
@@ -688,16 +739,24 @@ module Bundler
688
739
  specs[dep].any? {|s| s.satisfies?(dep) && (!dep.source || s.source.include?(dep.source)) }
689
740
  end
690
741
 
742
+ @specs_that_changed_sources = []
743
+
691
744
  specs.each do |s|
692
- # Replace the locked dependency's source with the equivalent source from the Gemfile
693
745
  dep = @dependencies.find {|d| s.satisfies?(d) }
694
746
 
695
- s.source = (dep && dep.source) || sources.get(s.source) || sources.default_source
747
+ # Replace the locked dependency's source with the equivalent source from the Gemfile
748
+ s.source = if dep && dep.source
749
+ gemfile_source = dep.source
750
+ lockfile_source = s.source
696
751
 
697
- next if @unlock[:sources].include?(s.source.name)
752
+ @specs_that_changed_sources << s if gemfile_source != lockfile_source
698
753
 
699
- # If the spec is from a path source and it doesn't exist anymore
700
- # then we unlock it.
754
+ gemfile_source
755
+ else
756
+ sources.get_with_fallback(s.source)
757
+ end
758
+
759
+ next if @unlock[:sources].include?(s.source.name)
701
760
 
702
761
  # Path sources have special logic
703
762
  if s.source.instance_of?(Source::Path) || s.source.instance_of?(Source::Gemspec)
@@ -707,7 +766,7 @@ module Bundler
707
766
  # if we won't need the source (according to the lockfile),
708
767
  # don't error if the path/git source isn't available
709
768
  next if specs.
710
- for(requested_dependencies, false, true).
769
+ for(requested_dependencies, false).
711
770
  none? {|locked_spec| locked_spec.source == s.source }
712
771
 
713
772
  raise
@@ -734,7 +793,7 @@ module Bundler
734
793
 
735
794
  def metadata_dependencies
736
795
  @metadata_dependencies ||= [
737
- Dependency.new("Ruby\0", RubyVersion.system.gem_version),
796
+ Dependency.new("Ruby\0", Gem.ruby_version),
738
797
  Dependency.new("RubyGems\0", Gem::VERSION),
739
798
  ]
740
799
  end
@@ -761,7 +820,9 @@ module Bundler
761
820
  # specs will be available later when the resolver knows where to
762
821
  # look for that gemspec (or its dependencies)
763
822
  source_requirements = if precompute_source_requirements_for_indirect_dependencies?
764
- { :default => sources.default_source }.merge(source_map.all_requirements)
823
+ all_requirements = source_map.all_requirements
824
+ all_requirements = pin_locally_available_names(all_requirements) if @prefer_local
825
+ { :default => sources.default_source }.merge(all_requirements)
765
826
  else
766
827
  { :default => Source::RubygemsAggregate.new(sources, source_map) }.merge(source_map.direct_requirements)
767
828
  end
@@ -771,11 +832,22 @@ module Bundler
771
832
  end
772
833
  source_requirements[:default_bundler] = source_requirements["bundler"] || sources.default_source
773
834
  source_requirements["bundler"] = sources.metadata_source # needs to come last to override
835
+ verify_changed_sources!
774
836
  source_requirements
775
837
  end
776
838
 
839
+ def verify_changed_sources!
840
+ @specs_that_changed_sources.each do |s|
841
+ if s.source.specs.search(s.name).empty?
842
+ raise GemNotFound, "Could not find gem '#{s.name}' in #{s.source}"
843
+ end
844
+ end
845
+ end
846
+
777
847
  def requested_groups
778
- groups - Bundler.settings[:without] - @optional_groups + Bundler.settings[:with]
848
+ values = groups - Bundler.settings[:without] - @optional_groups + Bundler.settings[:with]
849
+ values &= Bundler.settings[:only] unless Bundler.settings[:only].empty?
850
+ values
779
851
  end
780
852
 
781
853
  def lockfiles_equal?(current, proposed, preserve_unknown_sections)
@@ -806,11 +878,22 @@ module Bundler
806
878
  return [] unless @locked_gems && unlocking? && !sources.expired_sources?(@locked_gems.sources)
807
879
  converge_specs(@originally_locked_specs).map do |locked_spec|
808
880
  name = locked_spec.name
809
- dep = Gem::Dependency.new(name, ">= #{locked_spec.version}")
881
+ dep = Dependency.new(name, ">= #{locked_spec.version}")
810
882
  DepProxy.get_proxy(dep, locked_spec.platform)
811
883
  end
812
884
  end
813
885
 
886
+ def remove_ruby_from_platforms_if_necessary!(dependencies)
887
+ return if Bundler.frozen_bundle? ||
888
+ Bundler.local_platform == Gem::Platform::RUBY ||
889
+ !platforms.include?(Gem::Platform::RUBY) ||
890
+ (@new_platform && platforms.last == Gem::Platform::RUBY) ||
891
+ !@originally_locked_specs.incomplete_ruby_specs?(dependencies)
892
+
893
+ remove_platform(Gem::Platform::RUBY)
894
+ add_current_platform
895
+ end
896
+
814
897
  def source_map
815
898
  @source_map ||= SourceMap.new(sources, dependencies, @locked_specs)
816
899
  end
@@ -7,7 +7,7 @@ require_relative "rubygems_ext"
7
7
  module Bundler
8
8
  class Dependency < Gem::Dependency
9
9
  attr_reader :autorequire
10
- attr_reader :groups, :platforms, :gemfile, :git, :github, :branch, :ref
10
+ attr_reader :groups, :platforms, :gemfile, :git, :github, :branch, :ref, :force_ruby_platform
11
11
 
12
12
  # rubocop:disable Naming/VariableNumber
13
13
  PLATFORM_MAP = {
@@ -109,6 +109,7 @@ module Bundler
109
109
  @env = options["env"]
110
110
  @should_include = options.fetch("should_include", true)
111
111
  @gemfile = options["gemfile"]
112
+ @force_ruby_platform = options["force_ruby_platform"]
112
113
 
113
114
  @autorequire = Array(options["require"] || []) if options.key?("require")
114
115
  end
data/lib/bundler/dsl.rb CHANGED
@@ -16,7 +16,7 @@ module Bundler
16
16
  VALID_PLATFORMS = Bundler::Dependency::PLATFORM_MAP.keys.freeze
17
17
 
18
18
  VALID_KEYS = %w[group groups git path glob name branch ref tag require submodules
19
- platform platforms type source install_if gemfile].freeze
19
+ platform platforms type source install_if gemfile force_ruby_platform].freeze
20
20
 
21
21
  GITHUB_PULL_REQUEST_URL = %r{\Ahttps://github\.com/([A-Za-z0-9_\-\.]+/[A-Za-z0-9_\-\.]+)/pull/(\d+)\z}.freeze
22
22
 
@@ -465,12 +465,12 @@ module Bundler
465
465
 
466
466
  def multiple_global_source_warning
467
467
  if Bundler.feature_flag.bundler_3_mode?
468
- msg = "This Gemfile contains multiple primary sources. " \
468
+ msg = "This Gemfile contains multiple global sources. " \
469
469
  "Each source after the first must include a block to indicate which gems " \
470
470
  "should come from that source"
471
471
  raise GemfileEvalError, msg
472
472
  else
473
- Bundler::SharedHelpers.major_deprecation 2, "Your Gemfile contains multiple primary sources. " \
473
+ Bundler::SharedHelpers.major_deprecation 2, "Your Gemfile contains multiple global sources. " \
474
474
  "Using `source` more than once without a block is a security risk, and " \
475
475
  "may result in installing unexpected gems. To resolve this warning, use " \
476
476
  "a block to indicate which gems should come from the secondary source."
@@ -240,8 +240,8 @@ module Bundler
240
240
  def connection
241
241
  @connection ||= begin
242
242
  needs_ssl = remote_uri.scheme == "https" ||
243
- Bundler.settings[:ssl_verify_mode] ||
244
- Bundler.settings[:ssl_client_cert]
243
+ Bundler.settings[:ssl_verify_mode] ||
244
+ Bundler.settings[:ssl_client_cert]
245
245
  raise SSLError if needs_ssl && !defined?(OpenSSL::SSL)
246
246
 
247
247
  con = PersistentHTTP.new :name => "bundler", :proxy => :ENV
@@ -256,8 +256,8 @@ module Bundler
256
256
  end
257
257
 
258
258
  ssl_client_cert = Bundler.settings[:ssl_client_cert] ||
259
- (Gem.configuration.ssl_client_cert if
260
- Gem.configuration.respond_to?(:ssl_client_cert))
259
+ (Gem.configuration.ssl_client_cert if
260
+ Gem.configuration.respond_to?(:ssl_client_cert))
261
261
  if ssl_client_cert
262
262
  pem = File.read(ssl_client_cert)
263
263
  con.cert = OpenSSL::X509::Certificate.new(pem)
@@ -288,8 +288,8 @@ module Bundler
288
288
  def bundler_cert_store
289
289
  store = OpenSSL::X509::Store.new
290
290
  ssl_ca_cert = Bundler.settings[:ssl_ca_cert] ||
291
- (Gem.configuration.ssl_ca_cert if
292
- Gem.configuration.respond_to?(:ssl_ca_cert))
291
+ (Gem.configuration.ssl_ca_cert if
292
+ Gem.configuration.respond_to?(:ssl_ca_cert))
293
293
  if ssl_ca_cert
294
294
  if File.directory? ssl_ca_cert
295
295
  store.add_path ssl_ca_cert
@@ -5,6 +5,7 @@ module Bundler
5
5
  GENERIC_CACHE = { Gem::Platform::RUBY => Gem::Platform::RUBY } # rubocop:disable Style/MutableConstant
6
6
  GENERICS = [
7
7
  [Gem::Platform.new("java"), Gem::Platform.new("java")],
8
+ [Gem::Platform.new("universal-java"), Gem::Platform.new("java")],
8
9
  [Gem::Platform.new("mswin32"), Gem::Platform.new("mswin32")],
9
10
  [Gem::Platform.new("mswin64"), Gem::Platform.new("mswin64")],
10
11
  [Gem::Platform.new("universal-mingw32"), Gem::Platform.new("universal-mingw32")],
@@ -43,6 +44,12 @@ module Bundler
43
44
 
44
45
  def select_best_platform_match(specs, platform)
45
46
  matching = specs.select {|spec| spec.match_platform(platform) }
47
+
48
+ sort_best_platform_match(matching, platform)
49
+ end
50
+ module_function :select_best_platform_match
51
+
52
+ def sort_best_platform_match(matching, platform)
46
53
  exact = matching.select {|spec| spec.platform == platform }
47
54
  return exact if exact.any?
48
55
 
@@ -51,7 +58,7 @@ module Bundler
51
58
 
52
59
  sorted_matching.take_while {|spec| same_specificity(platform, spec, exemplary_spec) && same_deps(spec, exemplary_spec) }
53
60
  end
54
- module_function :select_best_platform_match
61
+ module_function :sort_best_platform_match
55
62
 
56
63
  class PlatformMatch
57
64
  def self.specificity_score(spec_platform, user_platform)
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bundler
4
+ class IncompleteSpecification
5
+ attr_reader :name, :platform
6
+
7
+ def initialize(name, platform)
8
+ @name = name
9
+ @platform = platform
10
+ end
11
+ end
12
+ end