bundler 2.6.3 → 2.6.9
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +119 -6
- data/README.md +1 -1
- data/lib/bundler/build_metadata.rb +2 -2
- data/lib/bundler/checksum.rb +22 -12
- data/lib/bundler/cli/console.rb +8 -6
- data/lib/bundler/cli/doctor/diagnose.rb +167 -0
- data/lib/bundler/cli/doctor/ssl.rb +249 -0
- data/lib/bundler/cli/doctor.rb +27 -151
- data/lib/bundler/cli/info.rb +4 -4
- data/lib/bundler/cli/inject.rb +2 -2
- data/lib/bundler/cli/issue.rb +3 -3
- data/lib/bundler/cli/lock.rb +2 -1
- data/lib/bundler/cli/show.rb +1 -1
- data/lib/bundler/cli.rb +2 -11
- data/lib/bundler/compact_index_client/cache.rb +1 -1
- data/lib/bundler/compact_index_client/parser.rb +1 -1
- data/lib/bundler/compact_index_client/updater.rb +2 -1
- data/lib/bundler/current_ruby.rb +23 -33
- data/lib/bundler/definition.rb +220 -184
- data/lib/bundler/dependency.rb +92 -47
- data/lib/bundler/dsl.rb +84 -80
- data/lib/bundler/endpoint_specification.rb +10 -3
- data/lib/bundler/errors.rb +22 -0
- data/lib/bundler/friendly_errors.rb +1 -1
- data/lib/bundler/gem_helpers.rb +4 -10
- data/lib/bundler/gem_version_promoter.rb +0 -2
- data/lib/bundler/injector.rb +9 -9
- data/lib/bundler/installer.rb +2 -2
- data/lib/bundler/lazy_specification.rb +67 -45
- data/lib/bundler/lockfile_parser.rb +8 -5
- data/lib/bundler/man/bundle-add.1 +1 -1
- data/lib/bundler/man/bundle-binstubs.1 +1 -1
- data/lib/bundler/man/bundle-cache.1 +1 -1
- data/lib/bundler/man/bundle-check.1 +1 -1
- data/lib/bundler/man/bundle-clean.1 +1 -1
- data/lib/bundler/man/bundle-config.1 +6 -6
- data/lib/bundler/man/bundle-config.1.ronn +9 -4
- data/lib/bundler/man/bundle-console.1 +1 -1
- data/lib/bundler/man/bundle-doctor.1 +1 -1
- data/lib/bundler/man/bundle-env.1 +1 -1
- data/lib/bundler/man/bundle-exec.1 +3 -3
- data/lib/bundler/man/bundle-exec.1.ronn +2 -2
- data/lib/bundler/man/bundle-fund.1 +1 -1
- data/lib/bundler/man/bundle-gem.1 +1 -1
- data/lib/bundler/man/bundle-help.1 +1 -1
- data/lib/bundler/man/bundle-info.1 +1 -1
- data/lib/bundler/man/bundle-init.1 +1 -1
- data/lib/bundler/man/bundle-inject.1 +1 -1
- data/lib/bundler/man/bundle-install.1 +1 -1
- data/lib/bundler/man/bundle-issue.1 +1 -1
- data/lib/bundler/man/bundle-licenses.1 +1 -1
- data/lib/bundler/man/bundle-list.1 +1 -1
- data/lib/bundler/man/bundle-lock.1 +1 -1
- data/lib/bundler/man/bundle-open.1 +1 -1
- data/lib/bundler/man/bundle-outdated.1 +1 -1
- data/lib/bundler/man/bundle-platform.1 +1 -1
- data/lib/bundler/man/bundle-plugin.1 +1 -1
- data/lib/bundler/man/bundle-pristine.1 +1 -1
- data/lib/bundler/man/bundle-remove.1 +1 -1
- data/lib/bundler/man/bundle-show.1 +1 -1
- data/lib/bundler/man/bundle-update.1 +1 -1
- data/lib/bundler/man/bundle-version.1 +1 -1
- data/lib/bundler/man/bundle-viz.1 +1 -1
- data/lib/bundler/man/bundle.1 +1 -1
- data/lib/bundler/man/gemfile.5 +1 -1
- data/lib/bundler/match_metadata.rb +13 -0
- data/lib/bundler/plugin/api/source.rb +1 -1
- data/lib/bundler/plugin/index.rb +1 -1
- data/lib/bundler/plugin/installer/path.rb +8 -0
- data/lib/bundler/plugin.rb +1 -1
- data/lib/bundler/resolver/candidate.rb +12 -9
- data/lib/bundler/resolver/package.rb +7 -3
- data/lib/bundler/resolver/spec_group.rb +1 -25
- data/lib/bundler/resolver/strategy.rb +40 -0
- data/lib/bundler/resolver.rb +29 -27
- data/lib/bundler/rubygems_ext.rb +97 -81
- data/lib/bundler/rubygems_integration.rb +2 -3
- data/lib/bundler/runtime.rb +27 -29
- data/lib/bundler/shared_helpers.rb +4 -0
- data/lib/bundler/source/gemspec.rb +1 -4
- data/lib/bundler/source/git/git_proxy.rb +14 -3
- data/lib/bundler/source/git.rb +5 -1
- data/lib/bundler/source/path.rb +2 -2
- data/lib/bundler/source/rubygems/remote.rb +11 -3
- data/lib/bundler/source/rubygems.rb +19 -4
- data/lib/bundler/source.rb +2 -0
- data/lib/bundler/source_list.rb +33 -11
- data/lib/bundler/spec_set.rb +98 -40
- data/lib/bundler/templates/newgem/Gemfile.tt +1 -0
- data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +53 -3
- data/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +1 -1
- data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +11 -0
- data/lib/bundler/vendor/pub_grub/lib/pub_grub/basic_package_source.rb +4 -24
- data/lib/bundler/vendor/pub_grub/lib/pub_grub/strategy.rb +42 -0
- data/lib/bundler/vendor/pub_grub/lib/pub_grub/version_range.rb +20 -8
- data/lib/bundler/vendor/pub_grub/lib/pub_grub/version_solver.rb +17 -29
- data/lib/bundler/vendor/uri/lib/uri/common.rb +7 -3
- data/lib/bundler/vendor/uri/lib/uri/generic.rb +12 -11
- data/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +6 -6
- data/lib/bundler/vendor/uri/lib/uri/version.rb +1 -1
- data/lib/bundler/version.rb +1 -1
- metadata +7 -4
- data/lib/bundler/compact_index_client/gem_parser.rb +0 -32
data/lib/bundler/definition.rb
CHANGED
@@ -58,17 +58,28 @@ module Bundler
|
|
58
58
|
# @param ruby_version [Bundler::RubyVersion, nil] Requested Ruby Version
|
59
59
|
# @param optional_groups [Array(String)] A list of optional groups
|
60
60
|
def initialize(lockfile, dependencies, sources, unlock, ruby_version = nil, optional_groups = [], gemfiles = [])
|
61
|
-
|
61
|
+
unlock ||= {}
|
62
|
+
|
63
|
+
if unlock == true
|
64
|
+
@unlocking_all = true
|
62
65
|
@unlocking_bundler = false
|
63
66
|
@unlocking = unlock
|
67
|
+
@sources_to_unlock = []
|
68
|
+
@unlocking_ruby = false
|
69
|
+
@explicit_unlocks = []
|
70
|
+
conservative = false
|
64
71
|
else
|
72
|
+
@unlocking_all = false
|
65
73
|
@unlocking_bundler = unlock.delete(:bundler)
|
66
74
|
@unlocking = unlock.any? {|_k, v| !Array(v).empty? }
|
75
|
+
@sources_to_unlock = unlock.delete(:sources) || []
|
76
|
+
@unlocking_ruby = unlock.delete(:ruby)
|
77
|
+
@explicit_unlocks = unlock.delete(:gems) || []
|
78
|
+
conservative = unlock.delete(:conservative)
|
67
79
|
end
|
68
80
|
|
69
81
|
@dependencies = dependencies
|
70
82
|
@sources = sources
|
71
|
-
@unlock = unlock
|
72
83
|
@optional_groups = optional_groups
|
73
84
|
@prefer_local = false
|
74
85
|
@specs = nil
|
@@ -83,7 +94,8 @@ module Bundler
|
|
83
94
|
|
84
95
|
@locked_ruby_version = nil
|
85
96
|
@new_platforms = []
|
86
|
-
@
|
97
|
+
@removed_platforms = []
|
98
|
+
@originally_invalid_platforms = []
|
87
99
|
|
88
100
|
if lockfile_exists?
|
89
101
|
@lockfile_contents = Bundler.read_file(lockfile)
|
@@ -93,29 +105,24 @@ module Bundler
|
|
93
105
|
@platforms = @locked_platforms.dup
|
94
106
|
@locked_bundler_version = @locked_gems.bundler_version
|
95
107
|
@locked_ruby_version = @locked_gems.ruby_version
|
96
|
-
@
|
108
|
+
@locked_deps = @locked_gems.dependencies
|
97
109
|
@originally_locked_specs = SpecSet.new(@locked_gems.specs)
|
98
110
|
@locked_checksums = @locked_gems.checksums
|
99
111
|
|
100
|
-
if
|
101
|
-
@locked_deps = @originally_locked_deps
|
102
|
-
@locked_specs = @originally_locked_specs
|
103
|
-
@locked_sources = @locked_gems.sources
|
104
|
-
else
|
105
|
-
@unlock = {}
|
106
|
-
@locked_deps = {}
|
112
|
+
if @unlocking_all
|
107
113
|
@locked_specs = SpecSet.new([])
|
108
114
|
@locked_sources = []
|
115
|
+
else
|
116
|
+
@locked_specs = @originally_locked_specs
|
117
|
+
@locked_sources = @locked_gems.sources
|
109
118
|
end
|
110
119
|
else
|
111
|
-
@
|
112
|
-
@locked_gems = nil
|
120
|
+
@locked_gems = nil
|
113
121
|
@locked_platforms = []
|
114
122
|
@most_specific_locked_platform = nil
|
115
123
|
@platforms = []
|
116
124
|
@locked_deps = {}
|
117
125
|
@locked_specs = SpecSet.new([])
|
118
|
-
@originally_locked_deps = {}
|
119
126
|
@originally_locked_specs = @locked_specs
|
120
127
|
@locked_sources = []
|
121
128
|
@locked_checksums = Bundler.feature_flag.lockfile_checksums?
|
@@ -134,21 +141,17 @@ module Bundler
|
|
134
141
|
@sources.merged_gem_lockfile_sections!(locked_gem_sources.first)
|
135
142
|
end
|
136
143
|
|
137
|
-
@
|
138
|
-
@unlock[:ruby] ||= if @ruby_version && locked_ruby_version_object
|
144
|
+
@unlocking_ruby ||= if @ruby_version && locked_ruby_version_object
|
139
145
|
@ruby_version.diff(locked_ruby_version_object)
|
140
146
|
end
|
141
|
-
@unlocking ||= @
|
147
|
+
@unlocking ||= @unlocking_ruby ||= (!@locked_ruby_version ^ !@ruby_version)
|
142
148
|
|
143
149
|
@current_platform_missing = add_current_platform unless Bundler.frozen_bundle?
|
144
150
|
|
145
|
-
converge_path_sources_to_gemspec_sources
|
146
|
-
@path_changes = converge_paths
|
147
151
|
@source_changes = converge_sources
|
152
|
+
@path_changes = converge_paths
|
148
153
|
|
149
|
-
|
150
|
-
|
151
|
-
if @unlock[:conservative]
|
154
|
+
if conservative
|
152
155
|
@gems_to_unlock = @explicit_unlocks.any? ? @explicit_unlocks : @dependencies.map(&:name)
|
153
156
|
else
|
154
157
|
eager_unlock = @explicit_unlocks.map {|name| Dependency.new(name, ">= 0") }
|
@@ -220,6 +223,8 @@ module Bundler
|
|
220
223
|
|
221
224
|
def prefer_local!
|
222
225
|
@prefer_local = true
|
226
|
+
|
227
|
+
sources.prefer_local!
|
223
228
|
end
|
224
229
|
|
225
230
|
# For given dependency list returns a SpecSet with Gemspec of all the required
|
@@ -252,7 +257,7 @@ module Bundler
|
|
252
257
|
rescue BundlerError => e
|
253
258
|
@resolve = nil
|
254
259
|
@resolver = nil
|
255
|
-
@
|
260
|
+
@resolution_base = nil
|
256
261
|
@source_requirements = nil
|
257
262
|
@specs = nil
|
258
263
|
|
@@ -325,18 +330,14 @@ module Bundler
|
|
325
330
|
SpecSet.new(filter_specs(@locked_specs, @dependencies - deleted_deps))
|
326
331
|
else
|
327
332
|
Bundler.ui.debug "Found no changes, using resolution from the lockfile"
|
328
|
-
if @
|
333
|
+
if @removed_platforms.any? || @locked_gems.may_include_redundant_platform_specific_gems?
|
329
334
|
SpecSet.new(filter_specs(@locked_specs, @dependencies))
|
330
335
|
else
|
331
336
|
@locked_specs
|
332
337
|
end
|
333
338
|
end
|
334
339
|
else
|
335
|
-
|
336
|
-
Bundler.ui.debug "Found changes from the lockfile, re-resolving dependencies because #{change_reason}"
|
337
|
-
else
|
338
|
-
Bundler.ui.debug "Resolving dependencies because there's no lockfile"
|
339
|
-
end
|
340
|
+
Bundler.ui.debug resolve_needed_reason
|
340
341
|
|
341
342
|
start_resolution
|
342
343
|
end
|
@@ -374,7 +375,7 @@ module Bundler
|
|
374
375
|
|
375
376
|
def locked_ruby_version
|
376
377
|
return unless ruby_version
|
377
|
-
if @
|
378
|
+
if @unlocking_ruby || !@locked_ruby_version
|
378
379
|
Bundler::RubyVersion.system
|
379
380
|
else
|
380
381
|
@locked_ruby_version
|
@@ -407,51 +408,18 @@ module Bundler
|
|
407
408
|
|
408
409
|
raise ProductionError, "Frozen mode is set, but there's no lockfile" unless lockfile_exists?
|
409
410
|
|
410
|
-
|
411
|
-
|
412
|
-
changed = []
|
413
|
-
|
414
|
-
new_platforms = @platforms - @locked_platforms
|
415
|
-
deleted_platforms = @locked_platforms - @platforms
|
416
|
-
added.concat new_platforms.map {|p| "* platform: #{p}" }
|
417
|
-
deleted.concat deleted_platforms.map {|p| "* platform: #{p}" }
|
418
|
-
|
419
|
-
added.concat new_deps.map {|d| "* #{pretty_dep(d)}" } if new_deps.any?
|
420
|
-
deleted.concat deleted_deps.map {|d| "* #{pretty_dep(d)}" } if deleted_deps.any?
|
421
|
-
|
422
|
-
both_sources = Hash.new {|h, k| h[k] = [] }
|
423
|
-
current_dependencies.each {|d| both_sources[d.name][0] = d }
|
424
|
-
current_locked_dependencies.each {|d| both_sources[d.name][1] = d }
|
425
|
-
|
426
|
-
both_sources.each do |name, (dep, lock_dep)|
|
427
|
-
next if dep.nil? || lock_dep.nil?
|
428
|
-
|
429
|
-
gemfile_source = dep.source || default_source
|
430
|
-
lock_source = lock_dep.source || default_source
|
431
|
-
next if lock_source.include?(gemfile_source)
|
432
|
-
|
433
|
-
gemfile_source_name = dep.source ? gemfile_source.to_gemfile : "no specified source"
|
434
|
-
lockfile_source_name = lock_dep.source ? lock_source.to_gemfile : "no specified source"
|
435
|
-
changed << "* #{name} from `#{lockfile_source_name}` to `#{gemfile_source_name}`"
|
436
|
-
end
|
437
|
-
|
438
|
-
reason = nothing_changed? ? "some dependencies were deleted from your gemfile" : change_reason
|
439
|
-
msg = String.new
|
440
|
-
msg << "#{reason.capitalize.strip}, but the lockfile can't be updated because frozen mode is set"
|
441
|
-
msg << "\n\nYou have added to the Gemfile:\n" << added.join("\n") if added.any?
|
442
|
-
msg << "\n\nYou have deleted from the Gemfile:\n" << deleted.join("\n") if deleted.any?
|
443
|
-
msg << "\n\nYou have changed in the Gemfile:\n" << changed.join("\n") if changed.any?
|
444
|
-
msg << "\n\nRun `bundle install` elsewhere and add the updated #{SharedHelpers.relative_gemfile_path} to version control.\n"
|
411
|
+
msg = lockfile_changes_summary("frozen mode is set")
|
412
|
+
return unless msg
|
445
413
|
|
446
414
|
unless explicit_flag
|
447
415
|
suggested_command = unless Bundler.settings.locations("frozen").keys.include?(:env)
|
448
416
|
"bundle config set frozen false"
|
449
417
|
end
|
450
|
-
msg << "
|
418
|
+
msg << "\n\nIf this is a development machine, remove the #{SharedHelpers.relative_lockfile_path} " \
|
451
419
|
"freeze by running `#{suggested_command}`." if suggested_command
|
452
420
|
end
|
453
421
|
|
454
|
-
raise ProductionError, msg
|
422
|
+
raise ProductionError, msg
|
455
423
|
end
|
456
424
|
|
457
425
|
def validate_runtime!
|
@@ -485,7 +453,7 @@ module Bundler
|
|
485
453
|
end
|
486
454
|
|
487
455
|
def validate_platforms!
|
488
|
-
return if current_platform_locked?
|
456
|
+
return if current_platform_locked? || @platforms.include?(Gem::Platform::RUBY)
|
489
457
|
|
490
458
|
raise ProductionError, "Your bundle only supports platforms #{@platforms.map(&:to_s)} " \
|
491
459
|
"but your local platform is #{local_platform}. " \
|
@@ -493,7 +461,7 @@ module Bundler
|
|
493
461
|
end
|
494
462
|
|
495
463
|
def normalize_platforms
|
496
|
-
|
464
|
+
resolve.normalize_platforms!(current_dependencies, platforms)
|
497
465
|
|
498
466
|
@resolve = SpecSet.new(resolve.for(current_dependencies, @platforms))
|
499
467
|
end
|
@@ -506,10 +474,10 @@ module Bundler
|
|
506
474
|
end
|
507
475
|
|
508
476
|
def remove_platform(platform)
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
477
|
+
raise InvalidOption, "Unable to remove the platform `#{platform}` since the only platforms are #{@platforms.join ", "}" unless @platforms.include?(platform)
|
478
|
+
|
479
|
+
@removed_platforms << platform
|
480
|
+
@platforms.delete(platform)
|
513
481
|
end
|
514
482
|
|
515
483
|
def nothing_changed?
|
@@ -536,6 +504,45 @@ module Bundler
|
|
536
504
|
|
537
505
|
private
|
538
506
|
|
507
|
+
def lockfile_changes_summary(update_refused_reason)
|
508
|
+
added = []
|
509
|
+
deleted = []
|
510
|
+
changed = []
|
511
|
+
|
512
|
+
added.concat @new_platforms.map {|p| "* platform: #{p}" }
|
513
|
+
deleted.concat @removed_platforms.map {|p| "* platform: #{p}" }
|
514
|
+
|
515
|
+
added.concat new_deps.map {|d| "* #{pretty_dep(d)}" } if new_deps.any?
|
516
|
+
deleted.concat deleted_deps.map {|d| "* #{pretty_dep(d)}" } if deleted_deps.any?
|
517
|
+
|
518
|
+
both_sources = Hash.new {|h, k| h[k] = [] }
|
519
|
+
current_dependencies.each {|d| both_sources[d.name][0] = d }
|
520
|
+
current_locked_dependencies.each {|d| both_sources[d.name][1] = d }
|
521
|
+
|
522
|
+
both_sources.each do |name, (dep, lock_dep)|
|
523
|
+
next if dep.nil? || lock_dep.nil?
|
524
|
+
|
525
|
+
gemfile_source = dep.source || default_source
|
526
|
+
lock_source = lock_dep.source || default_source
|
527
|
+
next if lock_source.include?(gemfile_source)
|
528
|
+
|
529
|
+
gemfile_source_name = dep.source ? gemfile_source.to_gemfile : "no specified source"
|
530
|
+
lockfile_source_name = lock_dep.source ? lock_source.to_gemfile : "no specified source"
|
531
|
+
changed << "* #{name} from `#{lockfile_source_name}` to `#{gemfile_source_name}`"
|
532
|
+
end
|
533
|
+
|
534
|
+
return unless added.any? || deleted.any? || changed.any? || resolve_needed?
|
535
|
+
|
536
|
+
msg = String.new("#{change_reason.capitalize.strip}, but ")
|
537
|
+
msg << "the lockfile " unless msg.start_with?("Your lockfile")
|
538
|
+
msg << "can't be updated because #{update_refused_reason}"
|
539
|
+
msg << "\n\nYou have added to the Gemfile:\n" << added.join("\n") if added.any?
|
540
|
+
msg << "\n\nYou have deleted from the Gemfile:\n" << deleted.join("\n") if deleted.any?
|
541
|
+
msg << "\n\nYou have changed in the Gemfile:\n" << changed.join("\n") if changed.any?
|
542
|
+
msg << "\n\nRun `bundle install` elsewhere and add the updated #{SharedHelpers.relative_lockfile_path} to version control.\n" unless unlocking?
|
543
|
+
msg
|
544
|
+
end
|
545
|
+
|
539
546
|
def install_needed?
|
540
547
|
resolve_needed? || missing_specs?
|
541
548
|
end
|
@@ -551,6 +558,7 @@ module Bundler
|
|
551
558
|
@local_changes ||
|
552
559
|
@missing_lockfile_dep ||
|
553
560
|
@unlocking_bundler ||
|
561
|
+
@locked_spec_with_missing_checksums ||
|
554
562
|
@locked_spec_with_missing_deps ||
|
555
563
|
@locked_spec_with_invalid_deps
|
556
564
|
end
|
@@ -596,13 +604,17 @@ module Bundler
|
|
596
604
|
return
|
597
605
|
end
|
598
606
|
|
599
|
-
|
600
|
-
|
607
|
+
begin
|
608
|
+
SharedHelpers.filesystem_access(file) do |p|
|
609
|
+
File.open(p, "wb") {|f| f.puts(contents) }
|
610
|
+
end
|
611
|
+
rescue ReadOnlyFileSystemError
|
612
|
+
raise ProductionError, lockfile_changes_summary("file system is read-only")
|
601
613
|
end
|
602
614
|
end
|
603
615
|
|
604
616
|
def resolver
|
605
|
-
@resolver ||= Resolver.new(
|
617
|
+
@resolver ||= Resolver.new(resolution_base, gem_version_promoter, @most_specific_locked_platform)
|
606
618
|
end
|
607
619
|
|
608
620
|
def expanded_dependencies
|
@@ -616,14 +628,15 @@ module Bundler
|
|
616
628
|
[Dependency.new("bundler", @unlocking_bundler)] + dependencies
|
617
629
|
end
|
618
630
|
|
619
|
-
def
|
620
|
-
@
|
631
|
+
def resolution_base
|
632
|
+
@resolution_base ||= begin
|
621
633
|
last_resolve = converge_locked_specs
|
622
634
|
remove_invalid_platforms!
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
635
|
+
new_resolution_platforms = @current_platform_missing ? @new_platforms + [local_platform] : @new_platforms
|
636
|
+
base = Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, locked_specs: @originally_locked_specs, unlock: @unlocking_all || @gems_to_unlock, prerelease: gem_version_promoter.pre?, prefer_local: @prefer_local, new_platforms: new_resolution_platforms)
|
637
|
+
base = additional_base_requirements_to_prevent_downgrades(base)
|
638
|
+
base = additional_base_requirements_to_force_updates(base)
|
639
|
+
base
|
627
640
|
end
|
628
641
|
end
|
629
642
|
|
@@ -639,6 +652,8 @@ module Bundler
|
|
639
652
|
specs = begin
|
640
653
|
resolve.materialize(dependencies)
|
641
654
|
rescue IncorrectLockfileDependencies => e
|
655
|
+
raise if Bundler.frozen_bundle?
|
656
|
+
|
642
657
|
spec = e.spec
|
643
658
|
raise "Infinite loop while fixing lockfile dependencies" if incorrect_spec == spec
|
644
659
|
|
@@ -696,8 +711,7 @@ module Bundler
|
|
696
711
|
still_incomplete_specs = resolve.incomplete_specs
|
697
712
|
|
698
713
|
if still_incomplete_specs == incomplete_specs
|
699
|
-
|
700
|
-
resolver.raise_not_found! package
|
714
|
+
resolver.raise_incomplete! incomplete_specs
|
701
715
|
end
|
702
716
|
|
703
717
|
incomplete_specs = still_incomplete_specs
|
@@ -719,12 +733,12 @@ module Bundler
|
|
719
733
|
end
|
720
734
|
|
721
735
|
def reresolve_without(incomplete_specs)
|
722
|
-
|
736
|
+
resolution_base.delete(incomplete_specs)
|
723
737
|
@resolve = start_resolution
|
724
738
|
end
|
725
739
|
|
726
740
|
def start_resolution
|
727
|
-
local_platform_needed_for_resolvability = @
|
741
|
+
local_platform_needed_for_resolvability = @most_specific_non_local_locked_platform && !@platforms.include?(local_platform)
|
728
742
|
@platforms << local_platform if local_platform_needed_for_resolvability
|
729
743
|
add_platform(Gem::Platform::RUBY) if RUBY_ENGINE == "truffleruby"
|
730
744
|
|
@@ -732,15 +746,27 @@ module Bundler
|
|
732
746
|
|
733
747
|
@resolved_bundler_version = result.find {|spec| spec.name == "bundler" }&.version
|
734
748
|
|
735
|
-
|
736
|
-
|
737
|
-
|
749
|
+
@new_platforms.each do |platform|
|
750
|
+
incomplete_specs = result.incomplete_specs_for_platform(current_dependencies, platform)
|
751
|
+
|
752
|
+
if incomplete_specs.any?
|
753
|
+
resolver.raise_incomplete! incomplete_specs
|
754
|
+
end
|
755
|
+
end
|
756
|
+
|
757
|
+
if @most_specific_non_local_locked_platform
|
758
|
+
if result.incomplete_for_platform?(current_dependencies, @most_specific_non_local_locked_platform)
|
759
|
+
@platforms.delete(@most_specific_non_local_locked_platform)
|
738
760
|
elsif local_platform_needed_for_resolvability
|
739
761
|
@platforms.delete(local_platform)
|
740
762
|
end
|
741
763
|
end
|
742
764
|
|
743
|
-
|
765
|
+
if should_add_extra_platforms?
|
766
|
+
result.add_extra_platforms!(platforms)
|
767
|
+
elsif @originally_invalid_platforms.any?
|
768
|
+
result.add_originally_invalid_platforms!(platforms, @originally_invalid_platforms)
|
769
|
+
end
|
744
770
|
|
745
771
|
SpecSet.new(result.for(dependencies, @platforms | [Gem::Platform::RUBY]))
|
746
772
|
end
|
@@ -751,52 +777,78 @@ module Bundler
|
|
751
777
|
|
752
778
|
def current_platform_locked?
|
753
779
|
@platforms.any? do |bundle_platform|
|
754
|
-
|
780
|
+
generic_local_platform == bundle_platform || local_platform === bundle_platform
|
755
781
|
end
|
756
782
|
end
|
757
783
|
|
758
784
|
def add_current_platform
|
759
785
|
return if @platforms.include?(local_platform)
|
760
786
|
|
761
|
-
@
|
762
|
-
return if @
|
787
|
+
@most_specific_non_local_locked_platform = find_most_specific_locked_platform
|
788
|
+
return if @most_specific_non_local_locked_platform
|
763
789
|
|
764
790
|
@platforms << local_platform
|
765
791
|
true
|
766
792
|
end
|
767
793
|
|
768
|
-
def
|
769
|
-
return unless
|
794
|
+
def find_most_specific_locked_platform
|
795
|
+
return unless current_platform_locked?
|
770
796
|
|
771
797
|
@most_specific_locked_platform
|
772
798
|
end
|
773
799
|
|
774
|
-
def
|
775
|
-
if
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
800
|
+
def resolve_needed_reason
|
801
|
+
if lockfile_exists?
|
802
|
+
if unlocking?
|
803
|
+
"Re-resolving dependencies because #{unlocking_reason}"
|
804
|
+
else
|
805
|
+
"Found changes from the lockfile, re-resolving dependencies because #{lockfile_changed_reason}"
|
780
806
|
end
|
807
|
+
else
|
808
|
+
"Resolving dependencies because there's no lockfile"
|
809
|
+
end
|
810
|
+
end
|
781
811
|
|
782
|
-
|
783
|
-
|
812
|
+
def change_reason
|
813
|
+
if resolve_needed?
|
814
|
+
if unlocking?
|
815
|
+
unlocking_reason
|
784
816
|
else
|
785
|
-
|
817
|
+
lockfile_changed_reason
|
786
818
|
end
|
819
|
+
else
|
820
|
+
"some dependencies were deleted from your gemfile"
|
821
|
+
end
|
822
|
+
end
|
823
|
+
|
824
|
+
def unlocking_reason
|
825
|
+
unlock_targets = if @gems_to_unlock.any?
|
826
|
+
["gems", @gems_to_unlock]
|
827
|
+
elsif @sources_to_unlock.any?
|
828
|
+
["sources", @sources_to_unlock]
|
829
|
+
end
|
787
830
|
|
788
|
-
|
831
|
+
unlock_reason = if unlock_targets
|
832
|
+
"#{unlock_targets.first}: (#{unlock_targets.last.join(", ")})"
|
833
|
+
else
|
834
|
+
@unlocking_ruby ? "ruby" : ""
|
789
835
|
end
|
836
|
+
|
837
|
+
"bundler is unlocking #{unlock_reason}"
|
838
|
+
end
|
839
|
+
|
840
|
+
def lockfile_changed_reason
|
790
841
|
[
|
791
842
|
[@source_changes, "the list of sources changed"],
|
792
843
|
[@dependency_changes, "the dependencies in your gemfile changed"],
|
793
|
-
[@current_platform_missing, "your lockfile
|
794
|
-
[@new_platforms.any?, "you
|
844
|
+
[@current_platform_missing, "your lockfile is missing the current platform"],
|
845
|
+
[@new_platforms.any?, "you are adding a new platform to your lockfile"],
|
795
846
|
[@path_changes, "the gemspecs for path gems changed"],
|
796
847
|
[@local_changes, "the gemspecs for git local gems changed"],
|
797
|
-
[@missing_lockfile_dep, "your
|
848
|
+
[@missing_lockfile_dep, "your lockfile is missing \"#{@missing_lockfile_dep}\""],
|
798
849
|
[@unlocking_bundler, "an update to the version of Bundler itself was requested"],
|
799
|
-
[@
|
850
|
+
[@locked_spec_with_missing_checksums, "your lockfile is missing a CHECKSUMS entry for \"#{@locked_spec_with_missing_checksums}\""],
|
851
|
+
[@locked_spec_with_missing_deps, "your lockfile includes \"#{@locked_spec_with_missing_deps}\" but not some of its dependencies"],
|
800
852
|
[@locked_spec_with_invalid_deps, "your lockfile does not satisfy dependencies of \"#{@locked_spec_with_invalid_deps}\""],
|
801
853
|
].select(&:first).map(&:last).join(", ")
|
802
854
|
end
|
@@ -813,8 +865,8 @@ module Bundler
|
|
813
865
|
!locked || dependencies_for_source_changed?(source, locked) || specs_for_source_changed?(source)
|
814
866
|
end
|
815
867
|
|
816
|
-
def dependencies_for_source_changed?(source, locked_source
|
817
|
-
deps_for_source = @dependencies.select {|
|
868
|
+
def dependencies_for_source_changed?(source, locked_source)
|
869
|
+
deps_for_source = @dependencies.select {|dep| dep.source == source }
|
818
870
|
locked_deps_for_source = locked_dependencies.select {|dep| dep.source == locked_source }
|
819
871
|
|
820
872
|
deps_for_source.uniq.sort != locked_deps_for_source.sort
|
@@ -822,7 +874,7 @@ module Bundler
|
|
822
874
|
|
823
875
|
def specs_for_source_changed?(source)
|
824
876
|
locked_index = Index.new
|
825
|
-
locked_index.use(@locked_specs.select {|s|
|
877
|
+
locked_index.use(@locked_specs.select {|s| s.replace_source_with!(source) })
|
826
878
|
|
827
879
|
!locked_index.subset?(source.specs)
|
828
880
|
rescue PathError, GitError => e
|
@@ -852,29 +904,29 @@ module Bundler
|
|
852
904
|
end
|
853
905
|
|
854
906
|
def check_lockfile
|
855
|
-
@missing_lockfile_dep = nil
|
856
|
-
|
857
907
|
@locked_spec_with_invalid_deps = nil
|
858
908
|
@locked_spec_with_missing_deps = nil
|
909
|
+
@locked_spec_with_missing_checksums = nil
|
859
910
|
|
860
|
-
|
911
|
+
missing_deps = []
|
912
|
+
missing_checksums = []
|
861
913
|
invalid = []
|
862
914
|
|
863
915
|
@locked_specs.each do |s|
|
916
|
+
missing_checksums << s if @locked_checksums && s.source.checksum_store.missing?(s)
|
917
|
+
|
864
918
|
validation = @locked_specs.validate_deps(s)
|
865
919
|
|
866
|
-
|
920
|
+
missing_deps << s if validation == :missing
|
867
921
|
invalid << s if validation == :invalid
|
868
922
|
end
|
869
923
|
|
870
|
-
if
|
871
|
-
@locked_specs.delete(missing)
|
924
|
+
@locked_spec_with_missing_checksums = missing_checksums.first.name if missing_checksums.any?
|
872
925
|
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
end&.name
|
926
|
+
if missing_deps.any?
|
927
|
+
@locked_specs.delete(missing_deps)
|
928
|
+
|
929
|
+
@locked_spec_with_missing_deps = missing_deps.first.name
|
878
930
|
end
|
879
931
|
|
880
932
|
if invalid.any?
|
@@ -890,24 +942,6 @@ module Bundler
|
|
890
942
|
end
|
891
943
|
end
|
892
944
|
|
893
|
-
def converge_path_source_to_gemspec_source(source)
|
894
|
-
return source unless source.instance_of?(Source::Path)
|
895
|
-
gemspec_source = sources.path_sources.find {|s| s.is_a?(Source::Gemspec) && s.as_path_source == source }
|
896
|
-
gemspec_source || source
|
897
|
-
end
|
898
|
-
|
899
|
-
def converge_path_sources_to_gemspec_sources
|
900
|
-
@locked_sources.map! do |source|
|
901
|
-
converge_path_source_to_gemspec_source(source)
|
902
|
-
end
|
903
|
-
@locked_specs.each do |spec|
|
904
|
-
spec.source &&= converge_path_source_to_gemspec_source(spec.source)
|
905
|
-
end
|
906
|
-
@locked_deps.each do |_, dep|
|
907
|
-
dep.source &&= converge_path_source_to_gemspec_source(dep.source)
|
908
|
-
end
|
909
|
-
end
|
910
|
-
|
911
945
|
def converge_sources
|
912
946
|
# Replace the sources from the Gemfile with the sources from the Gemfile.lock,
|
913
947
|
# if they exist in the Gemfile.lock and are `==`. If you can't find an equivalent
|
@@ -935,32 +969,39 @@ module Bundler
|
|
935
969
|
end
|
936
970
|
|
937
971
|
def converge_dependencies
|
938
|
-
|
972
|
+
@missing_lockfile_dep = nil
|
973
|
+
@changed_dependencies = []
|
939
974
|
|
940
|
-
|
975
|
+
current_dependencies.each do |dep|
|
941
976
|
if dep.source
|
942
977
|
dep.source = sources.get(dep.source)
|
943
978
|
end
|
944
979
|
|
945
|
-
|
946
|
-
|
947
|
-
|
980
|
+
name = dep.name
|
981
|
+
|
982
|
+
dep_changed = @locked_deps[name].nil?
|
983
|
+
|
984
|
+
unless name == "bundler"
|
985
|
+
locked_specs = @originally_locked_specs[name]
|
986
|
+
|
987
|
+
if locked_specs.empty?
|
988
|
+
@missing_lockfile_dep = name if dep_changed == false
|
989
|
+
else
|
990
|
+
if locked_specs.map(&:source).uniq.size > 1
|
991
|
+
@locked_specs.delete(locked_specs.select {|s| s.source != dep.source })
|
992
|
+
end
|
993
|
+
|
994
|
+
unless dep.matches_spec?(locked_specs.first)
|
995
|
+
@gems_to_unlock << name
|
996
|
+
dep_changed = true
|
997
|
+
end
|
998
|
+
end
|
948
999
|
end
|
949
1000
|
|
950
|
-
|
951
|
-
# doesn't carry a notion of the dependency type, if you use
|
952
|
-
# add_development_dependency in a gemspec that's loaded with the gemspec
|
953
|
-
# directive, the lockfile dependencies and resolved dependencies end up
|
954
|
-
# with a mismatch on #type. Work around that by setting the type on the
|
955
|
-
# dep from the lockfile.
|
956
|
-
locked_dep.instance_variable_set(:@type, dep.type)
|
957
|
-
|
958
|
-
# We already know the name matches from the hash lookup
|
959
|
-
# so we only need to check the requirement now
|
960
|
-
changes ||= dep.requirement != locked_dep.requirement
|
1001
|
+
@changed_dependencies << name if dep_changed
|
961
1002
|
end
|
962
1003
|
|
963
|
-
|
1004
|
+
@changed_dependencies.any?
|
964
1005
|
end
|
965
1006
|
|
966
1007
|
# Remove elements from the locked specs that are expired. This will most
|
@@ -1022,11 +1063,6 @@ module Bundler
|
|
1022
1063
|
end
|
1023
1064
|
end
|
1024
1065
|
|
1025
|
-
if dep.nil? && requested_dep = requested_dependencies.find {|d| name == d.name }
|
1026
|
-
@gems_to_unlock << name
|
1027
|
-
deps << requested_dep
|
1028
|
-
end
|
1029
|
-
|
1030
1066
|
converged << s
|
1031
1067
|
end
|
1032
1068
|
|
@@ -1095,23 +1131,27 @@ module Bundler
|
|
1095
1131
|
current == proposed
|
1096
1132
|
end
|
1097
1133
|
|
1098
|
-
def additional_base_requirements_to_prevent_downgrades(
|
1099
|
-
return
|
1100
|
-
|
1134
|
+
def additional_base_requirements_to_prevent_downgrades(resolution_base)
|
1135
|
+
return resolution_base unless @locked_gems && !sources.expired_sources?(@locked_gems.sources)
|
1136
|
+
@originally_locked_specs.each do |locked_spec|
|
1101
1137
|
next if locked_spec.source.is_a?(Source::Path)
|
1102
|
-
|
1138
|
+
|
1139
|
+
name = locked_spec.name
|
1140
|
+
next if @changed_dependencies.include?(name)
|
1141
|
+
|
1142
|
+
resolution_base.base_requirements[name] = Gem::Requirement.new(">= #{locked_spec.version}")
|
1103
1143
|
end
|
1104
|
-
|
1144
|
+
resolution_base
|
1105
1145
|
end
|
1106
1146
|
|
1107
|
-
def additional_base_requirements_to_force_updates(
|
1108
|
-
return
|
1147
|
+
def additional_base_requirements_to_force_updates(resolution_base)
|
1148
|
+
return resolution_base if @explicit_unlocks.empty?
|
1109
1149
|
full_update = dup_for_full_unlock.resolve
|
1110
1150
|
@explicit_unlocks.each do |name|
|
1111
1151
|
version = full_update.version_for(name)
|
1112
|
-
|
1152
|
+
resolution_base.base_requirements[name] = Gem::Requirement.new("= #{version}") if version
|
1113
1153
|
end
|
1114
|
-
|
1154
|
+
resolution_base
|
1115
1155
|
end
|
1116
1156
|
|
1117
1157
|
def dup_for_full_unlock
|
@@ -1128,20 +1168,16 @@ module Bundler
|
|
1128
1168
|
def remove_invalid_platforms!
|
1129
1169
|
return if Bundler.frozen_bundle?
|
1130
1170
|
|
1131
|
-
|
1132
|
-
next if local_platform == platform ||
|
1133
|
-
@new_platforms.include?(platform) ||
|
1134
|
-
@path_changes ||
|
1135
|
-
@dependency_changes ||
|
1136
|
-
@locked_spec_with_invalid_deps ||
|
1137
|
-
!spec_set_incomplete_for_platform?(@originally_locked_specs, platform)
|
1171
|
+
skips = (@new_platforms + [local_platform]).uniq
|
1138
1172
|
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1173
|
+
# We should probably avoid removing non-ruby platforms, since that means
|
1174
|
+
# lockfile will no longer install on those platforms, so a error to give
|
1175
|
+
# heads up to the user may be better. However, we have tests expecting
|
1176
|
+
# non ruby platform autoremoval to work, so leaving that in place for
|
1177
|
+
# now.
|
1178
|
+
skips |= platforms - [Gem::Platform::RUBY] if @dependency_changes
|
1142
1179
|
|
1143
|
-
|
1144
|
-
spec_set.incomplete_for_platform?(current_dependencies, platform)
|
1180
|
+
@originally_invalid_platforms = @originally_locked_specs.remove_invalid_platforms!(current_dependencies, platforms, skips: skips)
|
1145
1181
|
end
|
1146
1182
|
|
1147
1183
|
def source_map
|