bundler 2.3.17 → 2.3.20

Sign up to get free protection for your applications and to get access to all the features.
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