bundler-multilock 1.3.1 → 1.3.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a0cfa166a89e37eb6e7716c6be3f974d2c928c18c03fd2b45451f8bf1a005d6
4
- data.tar.gz: 7b9a270fa65c7d076db82aa4f3db317a74b8e888235902799661982be326dccb
3
+ metadata.gz: ba0cab59258e277e546634302417061f583bccb384c48d2573ac5565c23d436b
4
+ data.tar.gz: f0571eef5788f3299324cc39c8ca6bdeb742d7296b2a564d5511e5118e72e94c
5
5
  SHA512:
6
- metadata.gz: 1d68d41b6415bb46eff5b33d159985afdd0d65ea5492f4b753edad491116144d1f467a9e3441c9c3fa141a01db37fe1450158436113f27dc848c799396537ab1
7
- data.tar.gz: e024f799b4f52a2cce3be0025b1e0cc0165a0bedd4ce9adf157b292fe3cb6590739654ac8c2bdebf01d362f1bc0e97e62662b00b6d7e1c3be4d97621a506ee7a
6
+ metadata.gz: 92aa36d22778ef5073846af9eae61c1046be24ca103edd3b6ad4efc2ad2d99e0463e6b0750c74dc24174a16414aae64356465c957a1e85f4c214c4e42c49b3ad
7
+ data.tar.gz: 4b420871866b9be6de5e33671e63ad9741ddb17909a9899c8ed86ebe2c8b011e3e89366c99dc8c044323697636edbd9a048f8173572f5218100f3024300ff662
@@ -57,11 +57,27 @@ module Bundler
57
57
  end
58
58
 
59
59
  def specs(lockfile_name)
60
- @specs[lockfile_name] ||= parser(lockfile_name).specs.to_h do |spec|
61
- [[spec.name, spec.platform], spec]
60
+ @specs[lockfile_name] ||= begin
61
+ specs = {}
62
+ parser(lockfile_name).specs.each do |spec|
63
+ (specs[spec.name] ||= {})[spec.platform] = spec
64
+ end
65
+ specs
62
66
  end
63
67
  end
64
68
 
69
+ # sometimes a gem changes platforms with a new version, such as from aarch64-linux
70
+ # to aarch64-linux-gnu. we need to still sync it
71
+ def find_matching_spec(specs, spec)
72
+ specs = self.specs(specs) unless specs.is_a?(Hash)
73
+ platform_specs = specs[spec.name]
74
+ return unless platform_specs
75
+
76
+ parent_spec = platform_specs[spec.platform]
77
+ parent_spec ||= platform_specs.find { |platform, _| platform =~ spec.platform }&.last
78
+ parent_spec || platform_specs.find { |platform, _| platform == "ruby" }&.last
79
+ end
80
+
65
81
  # @param lockfile_name [Pathname]
66
82
  # @return [Hash<String, Set<String>>] hash of gem name to set of gem names that depend on it
67
83
  def reverse_dependencies(lockfile_name)
@@ -88,7 +88,7 @@ module Bundler
88
88
 
89
89
  # this checks for mismatches between the parent lockfile and the given lockfile,
90
90
  # and for pinned dependencies in lockfiles requiring them
91
- def deep_check(lockfile_definition)
91
+ def deep_check(lockfile_definition, conflicts: nil)
92
92
  lockfile_name = lockfile_definition[:lockfile]
93
93
  @cache.deep_check(lockfile_name) do
94
94
  success = true
@@ -120,7 +120,7 @@ module Bundler
120
120
 
121
121
  # check for conflicting requirements (and build list of pins, in the same loop)
122
122
  parser.specs.each do |spec|
123
- parent_spec = @cache.specs(parent_lockfile_name)[[spec.name, spec.platform]]
123
+ parent_spec = @cache.find_matching_spec(parent_lockfile_name, spec)
124
124
 
125
125
  if lockfile_definition[:enforce_pinned_additional_dependencies]
126
126
  # look through what this spec depends on, and keep track of all pinned requirements
@@ -156,6 +156,7 @@ module Bundler
156
156
  "does not match the parent lockfile's version " \
157
157
  "(@#{parent_spec.version}#{parent_spec.git_version}); " \
158
158
  "this may be due to a conflicting requirement, which would require manual resolution.")
159
+ conflicts&.add(spec.name)
159
160
  success = false
160
161
  end
161
162
 
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bundler
4
+ module Multilock
5
+ module Ext
6
+ module CLI
7
+ module ClassMethods
8
+ def instance
9
+ return @instance if instance_variable_defined?(:@instance)
10
+
11
+ # this is a little icky, but there's no other way to determine which command was run
12
+ @instance = ObjectSpace.each_object(::Bundler::CLI).first
13
+ end
14
+ end
15
+
16
+ ::Bundler::CLI.extend(ClassMethods)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "delegate"
4
+
3
5
  require "bundler/lockfile_generator"
4
6
 
5
7
  module Bundler
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Bundler
4
4
  module Multilock
5
- VERSION = "1.3.1"
5
+ VERSION = "1.3.3"
6
6
  end
7
7
  end
@@ -82,17 +82,13 @@ module Bundler
82
82
  enforce_pinned_additional_dependencies: enforce_pinned_additional_dependencies
83
83
  })
84
84
 
85
- if (defined?(CLI::Check) ||
86
- defined?(CLI::Install) ||
87
- defined?(CLI::Lock) ||
88
- defined?(CLI::Update)) &&
89
- !defined?(CLI::Cache) && !env_lockfile
85
+ # If they're using BUNDLE_LOCKFILE, then they really do want to
86
+ # use a particular lockfile, and it overrides whatever they
87
+ # dynamically set in their gemfile
88
+ if !env_lockfile && defined?(CLI) &&
89
+ %i[check install lock update].include?(CLI.instance&.current_command_chain&.first)
90
90
  # always use Gemfile.lock for `bundle check`, `bundle install`,
91
- # `bundle lock`, and `bundle update`. `bundle cache` delegates to
92
- # `bundle install`, but we want that to run as normal.
93
- # If they're using BUNDLE_LOCKFILE, then they really do want to
94
- # use a particular lockfile, and it overrides whatever they
95
- # dynamically set in their gemfile
91
+ # `bundle lock`, and `bundle update`.
96
92
  active = lockfile == Bundler.default_lockfile(force_original: true)
97
93
  end
98
94
 
@@ -179,10 +175,11 @@ module Bundler
179
175
 
180
176
  # already up to date?
181
177
  up_to_date = false
178
+ conflicts = Set.new
182
179
  Bundler.settings.temporary(frozen: true) do
183
180
  Bundler.ui.silence do
184
181
  up_to_date = checker.base_check(lockfile_definition, check_missing_deps: true) &&
185
- checker.deep_check(lockfile_definition)
182
+ checker.deep_check(lockfile_definition, conflicts: conflicts)
186
183
  end
187
184
  end
188
185
  if up_to_date
@@ -206,7 +203,6 @@ module Bundler
206
203
  Bundler.ui.info("Syncing to #{relative_lockfile}...") if attempts == 1
207
204
  synced_any = true
208
205
 
209
- specs = lockfile_name.exist? ? cache.specs(lockfile_name) : {}
210
206
  parent_lockfile_name = lockfile_definition[:parent]
211
207
  parent_root = parent_lockfile_name.dirname
212
208
  parent_specs = cache.specs(parent_lockfile_name)
@@ -222,7 +218,7 @@ module Bundler
222
218
  end
223
219
 
224
220
  # add a source for the current gem
225
- gem_spec = parent_specs[[File.basename(Bundler.root), "ruby"]]
221
+ gem_spec = parent_specs.dig(File.basename(Bundler.root), "ruby")
226
222
 
227
223
  if gem_spec
228
224
  adjusted_parent_lockfile_contents += <<~TEXT
@@ -252,39 +248,30 @@ module Bundler
252
248
  next :self if parent_spec.nil?
253
249
  next spec_precedences[spec.name] if spec_precedences.key?(spec.name)
254
250
 
255
- precedence = :self if cache.conflicting_requirements?(lockfile_name,
256
- parent_lockfile_name,
257
- spec,
258
- parent_spec)
259
-
260
- # look through all reverse dependencies; if any of them say it
261
- # has to come from self, due to conflicts, then this gem has
262
- # to come from self as well
263
- [cache.reverse_dependencies(lockfile_name),
264
- cache.reverse_dependencies(parent_lockfile_name)].each do |reverse_dependencies|
265
- break if precedence == :self
266
-
267
- reverse_dependencies[spec.name].each do |dep_name|
268
- precedence = check_precedence.call(specs[dep_name], parent_specs[dep_name])
269
- break if precedence == :self
270
- end
271
- end
251
+ precedence = if !(cache.reverse_dependencies(lockfile_name)[spec.name] & conflicts).empty?
252
+ :parent
253
+ elsif cache.conflicting_requirements?(lockfile_name,
254
+ parent_lockfile_name,
255
+ spec,
256
+ parent_spec)
257
+ :self
258
+ end
272
259
 
273
260
  spec_precedences[spec.name] = precedence || :parent
274
261
  end
275
262
 
263
+ lockfile.sources.map! do |source|
264
+ parent_lockfile.sources.find { |s| s == source } || source
265
+ end
276
266
  # replace any duplicate specs with what's in the parent lockfile
277
267
  lockfile.specs.map! do |spec|
278
- parent_spec = parent_specs[[spec.name, spec.platform]]
268
+ parent_spec = cache.find_matching_spec(parent_specs, spec)
279
269
  next spec unless parent_spec
280
-
281
270
  next spec if check_precedence.call(spec, parent_spec) == :self
282
271
 
283
272
  dependency_changes ||= spec != parent_spec
284
273
 
285
- new_spec = parent_spec.dup
286
- new_spec.source = spec.source
287
- new_spec
274
+ parent_spec
288
275
  end
289
276
 
290
277
  lockfile.platforms.replace(parent_lockfile.platforms).uniq!
@@ -497,6 +484,13 @@ module Bundler
497
484
  # from someone else
498
485
  if current_lockfile.exist? && install
499
486
  Bundler.settings.temporary(frozen: true) do
487
+ # it keeps the same sources as the builder, which now shares with
488
+ # `definition` above; give it its own copy to avoid stomping on it
489
+ builder.instance_variable_set(
490
+ :@sources,
491
+ builder.instance_variable_get(:@sources).dup
492
+ )
493
+
500
494
  current_definition = builder.to_definition(current_lockfile, {})
501
495
  # if something has changed, we skip this step; it's unlocking anyway
502
496
  next unless current_definition.no_resolve_needed?
@@ -518,6 +512,14 @@ module Bundler
518
512
  previous_ui_level = Bundler.ui.level
519
513
  Bundler.ui.level = "warn"
520
514
  begin
515
+ # force a remote resolution if intermediate gems are missing
516
+ if definition.instance_variable_get(:@locked_spec_with_missing_deps) ||
517
+ definition.instance_variable_get(:@locked_spec_with_invalid_deps) ||
518
+ definition.instance_variable_get(:@missing_lockfile_dep) ||
519
+ definition.instance_variable_get(:@invalid_lockfile_dep)
520
+ raise SolveFailure
521
+ end
522
+
521
523
  # this is a horrible hack, to fix what I consider to be a Bundler bug.
522
524
  # basically, if you have multiple platform specific gems in your
523
525
  # lockfile, and that gem gets unlocked, Bundler will only search
@@ -577,25 +579,29 @@ end
577
579
  Bundler::LazySpecification.include(Bundler::MatchMetadata) if defined?(Bundler::MatchMetadata)
578
580
  Bundler::Multilock.inject_preamble unless Bundler::Multilock.loaded?
579
581
 
580
- # this is terrible, but we can't prepend into these modules because we only load
581
- # _inside_ of the CLI commands already running
582
- if defined?(Bundler::CLI::Check)
583
- require_relative "multilock/check"
584
- at_exit do
585
- next unless $!.nil?
586
- next if $!.is_a?(SystemExit) && !$!.success?
582
+ if defined?(Bundler::CLI)
583
+ require_relative "multilock/ext/cli"
584
+
585
+ # this is terrible, but we can't prepend into these modules because we only load
586
+ # _inside_ of the CLI commands already running
587
+ if Bundler::CLI.instance&.current_command_chain&.first == :check
588
+ require_relative "multilock/check"
589
+ at_exit do
590
+ next unless $!.nil?
591
+ next if $!.is_a?(SystemExit) && !$!.success?
587
592
 
588
- next if Bundler::Multilock::Check.run
593
+ next if Bundler::Multilock::Check.run
589
594
 
590
- Bundler.ui.warn("You can attempt to fix by running `bundle install`")
591
- exit 1
595
+ Bundler.ui.warn("You can attempt to fix by running `bundle install`")
596
+ exit 1
597
+ end
592
598
  end
593
- end
594
- if defined?(Bundler::CLI::Lock)
595
- at_exit do
596
- next unless $!.nil?
597
- next if $!.is_a?(SystemExit) && !$!.success?
599
+ if Bundler::CLI.instance&.current_command_chain&.first == :lock
600
+ at_exit do
601
+ next unless $!.nil?
602
+ next if $!.is_a?(SystemExit) && !$!.success?
598
603
 
599
- Bundler::Multilock.after_install_all(install: false)
604
+ Bundler::Multilock.after_install_all(install: false)
605
+ end
600
606
  end
601
607
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bundler-multilock
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: 1.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Instructure
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-04-25 00:00:00.000000000 Z
11
+ date: 2024-06-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -82,6 +82,7 @@ files:
82
82
  - lib/bundler/multilock/cache.rb
83
83
  - lib/bundler/multilock/check.rb
84
84
  - lib/bundler/multilock/ext/bundler.rb
85
+ - lib/bundler/multilock/ext/cli.rb
85
86
  - lib/bundler/multilock/ext/definition.rb
86
87
  - lib/bundler/multilock/ext/dsl.rb
87
88
  - lib/bundler/multilock/ext/plugin.rb
@@ -113,7 +114,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
113
114
  - !ruby/object:Gem::Version
114
115
  version: '0'
115
116
  requirements: []
116
- rubygems_version: 3.5.9
117
+ rubygems_version: 3.5.14
117
118
  signing_key:
118
119
  specification_version: 4
119
120
  summary: Support Multiple Lockfiles