bundler-multilock 1.1.1 → 1.2.0

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: cac57db5334b1e1eca3b690b889b28fbb0fa0ffed4a2961ddc8208f3fc7620f1
4
- data.tar.gz: 0f80468fd6caab34bc0139aaf078cfc6b8e635237570fdcc803a46d658872515
3
+ metadata.gz: c84016021b1c7595a4e796a80de94d7df2160f016c4bdc286f1616c61bb09170
4
+ data.tar.gz: 8b8ed6c345db6beb1fdf681e603ffee395d39459fc5a81982f1457876bea4037
5
5
  SHA512:
6
- metadata.gz: aa446fe3eb1cbf6896083dee2b5063c1fd5569043b3f2d4df7572f91d1054409bb83c0a29061390d367906f1649bf3a3c646440fa7f664454be0863dedc95885
7
- data.tar.gz: 11bbaa79a07b0854150a053a83f9f3d32afe8e4ab7ffeda8936d878b1842b98f50d956941a33ecc90710cd2ca916f569e4328097c259153979addb2beac6cf75
6
+ metadata.gz: 4eb1334a6a9860cea9fbb7ece25741bc35f9dd3e44ab6a17bbf041998116445acf53173a7372f6c1f19dedf1538f1bccc0db859123493b5addae86d134f81146
7
+ data.tar.gz: 6bc840a4f41344443609f00447e87c95a89eab942446b5dd2598e55bcd15a79a7fcdb3952a4e417ce7664e50316073defdb627bba2da1b886323c0d92292d345
@@ -58,7 +58,7 @@ module Bundler
58
58
 
59
59
  # this is mostly equivalent to the built in checks in `bundle check`, but even
60
60
  # more conservative, and returns false instead of exiting on failure
61
- def base_check(lockfile_definition, log_missing: false, return_missing: false)
61
+ def base_check(lockfile_definition, log_missing: false, return_missing: false, check_missing_deps: false)
62
62
  return return_missing ? [] : false unless lockfile_definition[:lockfile].file?
63
63
 
64
64
  Multilock.prepare_block = lockfile_definition[:prepare]
@@ -83,14 +83,17 @@ module Bundler
83
83
 
84
84
  return not_installed if return_missing
85
85
 
86
- not_installed.empty? && definition.no_resolve_needed?
86
+ return false unless not_installed.empty? && definition.no_resolve_needed?
87
+ return true unless check_missing_deps
88
+
89
+ (definition.locked_gems.dependencies.values - definition.dependencies).empty?
87
90
  ensure
88
91
  Multilock.prepare_block = nil
89
92
  end
90
93
 
91
94
  # this checks for mismatches between the parent lockfile and the given lockfile,
92
95
  # and for pinned dependencies in lockfiles requiring them
93
- def check(lockfile_definition, allow_mismatched_dependencies: true)
96
+ def check(lockfile_definition)
94
97
  success = true
95
98
  proven_pinned = Set.new
96
99
  needs_pin_check = []
@@ -109,36 +112,8 @@ module Bundler
109
112
  success = false
110
113
  end
111
114
 
112
- specs = lockfile.specs.group_by(&:name)
113
- if allow_mismatched_dependencies
114
- allow_mismatched_dependencies = lockfile_definition[:allow_mismatched_dependencies]
115
- end
116
-
117
- # build list of top-level dependencies that differ from the parent lockfile,
118
- # and all _their_ transitive dependencies
119
- if allow_mismatched_dependencies
120
- transitive_dependencies = Set.new
121
- # only dependencies that differ from the parent lockfile
122
- pending_transitive_dependencies = lockfile.dependencies.reject do |name, dep|
123
- parent_lockfile.dependencies[name] == dep
124
- end.map(&:first)
125
-
126
- until pending_transitive_dependencies.empty?
127
- dep = pending_transitive_dependencies.shift
128
- next if transitive_dependencies.include?(dep)
129
-
130
- transitive_dependencies << dep
131
- platform_specs = specs[dep]
132
- unless platform_specs
133
- # should only be bundler that's missing a spec
134
- raise "Could not find spec for dependency #{dep}" unless dep == "bundler"
135
-
136
- next
137
- end
138
-
139
- pending_transitive_dependencies.concat(platform_specs.flat_map(&:dependencies).map(&:name).uniq)
140
- end
141
- end
115
+ reverse_dependencies = cache_reverse_dependencies(lockfile)
116
+ parent_reverse_dependencies = cache_reverse_dependencies(parent_lockfile)
142
117
 
143
118
  # look through top-level explicit dependencies for pinned requirements
144
119
  if lockfile_definition[:enforce_pinned_additional_dependencies]
@@ -146,7 +121,7 @@ module Bundler
146
121
  end
147
122
 
148
123
  # check for conflicting requirements (and build list of pins, in the same loop)
149
- specs.values.flatten.each do |spec|
124
+ lockfile.specs.each do |spec|
150
125
  parent_spec = lockfile_specs[parent][[spec.name, spec.platform]]
151
126
 
152
127
  if lockfile_definition[:enforce_pinned_additional_dependencies]
@@ -170,7 +145,15 @@ module Bundler
170
145
  end
171
146
 
172
147
  next if parent_spec.version == spec.version && same_source
173
- next if allow_mismatched_dependencies && transitive_dependencies.include?(spec.name)
148
+
149
+ # the version in the parent lockfile cannot possibly satisfy the requirements
150
+ # in this lockfile, and vice versa, so we assume it's intentional and allow it
151
+ unless reverse_dependencies[spec.name].satisfied_by?(parent_spec.version) ||
152
+ parent_reverse_dependencies[spec.name].satisfied_by?(spec.version)
153
+ # we're allowing it to differ from the parent, so pin check requirement comes into play
154
+ needs_pin_check << spec if lockfile_definition[:enforce_pinned_additional_dependencies]
155
+ next
156
+ end
174
157
 
175
158
  Bundler.ui.error("#{spec}#{spec.git_version} in #{lockfile_path} " \
176
159
  "does not match the parent lockfile's version " \
@@ -206,6 +189,21 @@ module Bundler
206
189
 
207
190
  private
208
191
 
192
+ def cache_reverse_dependencies(lockfile)
193
+ reverse_dependencies = Hash.new { |h, k| h[k] = Gem::Requirement.default_prerelease }
194
+
195
+ lockfile.dependencies.each_value do |spec|
196
+ reverse_dependencies[spec.name].requirements.concat(spec.requirement.requirements)
197
+ end
198
+ lockfile.specs.each do |spec|
199
+ spec.dependencies.each do |dependency|
200
+ reverse_dependencies[dependency.name].requirements.concat(dependency.requirement.requirements)
201
+ end
202
+ end
203
+
204
+ reverse_dependencies
205
+ end
206
+
209
207
  def find_pinned_dependencies(proven_pinned, dependencies)
210
208
  dependencies.each do |dependency|
211
209
  dependency.requirement.requirements.each do |requirement|
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Bundler
4
4
  module Multilock
5
- VERSION = "1.1.1"
5
+ VERSION = "1.2.0"
6
6
  end
7
7
  end
@@ -27,11 +27,6 @@ module Bundler
27
27
  # BUNDLE_LOCKFILE will still override a lockfile tagged as active
28
28
  # @param parent [String] The parent lockfile to sync dependencies from.
29
29
  # Also used for comparing enforce_pinned_additional_dependencies against.
30
- # @param allow_mismatched_dependencies [true, false]
31
- # Allows version differences in dependencies between this lockfile and
32
- # the default lockfile. Note that even with this option, only top-level
33
- # dependencies that differ from the default lockfile, and their transitive
34
- # depedencies, are allowed to mismatch.
35
30
  # @param enforce_pinned_additional_dependencies [true, false]
36
31
  # If dependencies are present in this lockfile that are not present in the
37
32
  # default lockfile, enforce that they are pinned.
@@ -44,12 +39,15 @@ module Bundler
44
39
  active: nil,
45
40
  default: nil,
46
41
  parent: nil,
47
- allow_mismatched_dependencies: true,
42
+ allow_mismatched_dependencies: nil,
48
43
  enforce_pinned_additional_dependencies: false,
49
44
  &block)
50
45
  # backcompat
51
46
  active = default if active.nil?
52
47
  Bundler.ui.warn("lockfile(default:) is deprecated. Use lockfile(active:) instead.") if default
48
+ unless allow_mismatched_dependencies.nil?
49
+ Bundler.ui.warn("lockfile(allow_mismatched_dependencies:) is deprecated.")
50
+ end
53
51
 
54
52
  active = true if active.nil? && lockfile_definitions.empty? && lockfile.nil? && gemfile.nil?
55
53
 
@@ -62,14 +60,8 @@ module Bundler
62
60
  raise ArgumentError, "Lockfile #{lockfile} is already defined"
63
61
  end
64
62
 
65
- env_lockfile = ENV["BUNDLE_LOCKFILE"]
66
- if env_lockfile
67
- unless env_lockfile.include?("/") || env_lockfile.end_with?(".lock")
68
- env_lockfile = "Gemfile.#{env_lockfile}.lock"
69
- end
70
- env_lockfile = Bundler.root.join(env_lockfile).expand_path
71
- active = env_lockfile == lockfile
72
- end
63
+ env_lockfile = ENV["BUNDLE_LOCKFILE"]&.then { |l| expand_lockfile(l) }
64
+ active = env_lockfile == lockfile if env_lockfile
73
65
 
74
66
  if active && (old_active = lockfile_definitions.find { |definition| definition[:active] })
75
67
  raise ArgumentError, "Only one lockfile (#{old_active[:lockfile]}) can be flagged as the default"
@@ -87,7 +79,6 @@ module Bundler
87
79
  active: active,
88
80
  prepare: block,
89
81
  parent: parent,
90
- allow_mismatched_dependencies: allow_mismatched_dependencies,
91
82
  enforce_pinned_additional_dependencies: enforce_pinned_additional_dependencies
92
83
  })
93
84
 
@@ -155,7 +146,6 @@ module Bundler
155
146
  require_relative "multilock/lockfile_generator"
156
147
 
157
148
  Bundler.ui.debug("Syncing to alternate lockfiles")
158
- Bundler.ui.info ""
159
149
 
160
150
  attempts = 1
161
151
 
@@ -177,8 +167,8 @@ module Bundler
177
167
  up_to_date = false
178
168
  Bundler.settings.temporary(frozen: true) do
179
169
  Bundler.ui.silence do
180
- up_to_date = checker.base_check(lockfile_definition) &&
181
- checker.check(lockfile_definition, allow_mismatched_dependencies: false)
170
+ up_to_date = checker.base_check(lockfile_definition, check_missing_deps: true) &&
171
+ checker.check(lockfile_definition)
182
172
  end
183
173
  end
184
174
  if up_to_date
@@ -310,16 +300,17 @@ module Bundler
310
300
 
311
301
  return unless lockfile_definitions.none? { |definition| definition[:active] }
312
302
 
313
- # Gemfile.lock isn't explicitly specified, otherwise it would be active
314
- default_lockfile_definition = lockfile_definitions.find do |definition|
315
- definition[:lockfile] == Bundler.default_lockfile(force_original: true)
316
- end
317
- if ENV["BUNDLE_LOCKFILE"] == Bundler.default_lockfile(force_original: true) && default_lockfile_definition
303
+ if ENV["BUNDLE_LOCKFILE"]&.then { |l| expand_lockfile(l) } ==
304
+ Bundler.default_lockfile(force_original: true)
318
305
  return
319
306
  end
320
307
 
321
308
  raise GemfileNotFound, "Could not locate lockfile #{ENV["BUNDLE_LOCKFILE"].inspect}" if ENV["BUNDLE_LOCKFILE"]
322
309
 
310
+ # Gemfile.lock isn't explicitly specified, otherwise it would be active
311
+ default_lockfile_definition = lockfile_definitions.find do |definition|
312
+ definition[:lockfile] == Bundler.default_lockfile(force_original: true)
313
+ end
323
314
  return unless default_lockfile_definition && default_lockfile_definition[:active] == false
324
315
 
325
316
  raise GemfileEvalError, "No lockfiles marked as default"
@@ -431,9 +422,16 @@ module Bundler
431
422
 
432
423
  orig_definition = definition.dup # we might need it twice
433
424
 
425
+ # install gems for the exact current version of the lockfile
426
+ # this ensures it doesn't re-resolve with only (different)
427
+ # local gems after you've pulled down an update to the lockfile
428
+ # from someone else
434
429
  if current_lockfile.exist? && install
435
430
  Bundler.settings.temporary(frozen: true) do
436
431
  current_definition = builder.to_definition(current_lockfile, {})
432
+ # if something has changed, we skip this step; it's unlocking anyway
433
+ next unless current_definition.no_resolve_needed?
434
+
437
435
  current_definition.resolve_with_cache!
438
436
  if current_definition.missing_specs.any?
439
437
  Bundler.with_default_lockfile(current_lockfile) do
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.1.1
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Instructure
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-06 00:00:00.000000000 Z
11
+ date: 2023-10-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler