bundler-multilock 2.0.0.beta3 → 2.0.0.beta5
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/lib/bundler/multilock/ext/dsl.rb +7 -2
- data/lib/bundler/multilock/ext/runtime.rb +128 -0
- data/lib/bundler/multilock/version.rb +1 -1
- data/lib/bundler/multilock.rb +116 -53
- metadata +4 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 730bc7b4e1a107a6b3fd9527014b630b97918ed317e703b8cf045c67d6f6fae9
|
|
4
|
+
data.tar.gz: 11943fc5875e3a07ba89f66b38e6b4ab6d100fe0d47168e24d5d3ae023609ebb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 998f0024a84771dc5d61ada77c069bd267c9d0da5c1d09acd11c098a02bdcd6c537a32e5e8bfd3005ebb9050d1fea9afed8a6f4cc32877e5af8224089431cd00
|
|
7
|
+
data.tar.gz: dcf0c9c3e0089f48f796857eec57f555381ff215327ba904a11ef294c1b8bd45611613be3548b8def4c0dc7a4abd6f2fa65f7082251bfe83d216c092891a822e
|
|
@@ -99,10 +99,15 @@ module Bundler
|
|
|
99
99
|
@allowed_duplicate_plugins = Set.new
|
|
100
100
|
end
|
|
101
101
|
|
|
102
|
-
|
|
102
|
+
# Significant changes:
|
|
103
|
+
# * a lockfile with a block or options is managed by Multilock
|
|
104
|
+
# * a bare lockfile name is just Bundler's own `lockfile`, for
|
|
105
|
+
# Gemfiles that only want to name their lockfile
|
|
106
|
+
def lockfile(*args, **kwargs, &block)
|
|
103
107
|
return true if Multilock.loaded?
|
|
108
|
+
return super(args.first) if args.length == 1 && args.first.is_a?(String) && kwargs.empty? && !block
|
|
104
109
|
|
|
105
|
-
Multilock.add_lockfile(
|
|
110
|
+
Multilock.add_lockfile(*args, builder: self, **kwargs, &block)
|
|
106
111
|
end
|
|
107
112
|
end
|
|
108
113
|
end
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Bundler
|
|
4
|
+
module Multilock
|
|
5
|
+
module Ext
|
|
6
|
+
# Makes `bundle cache` (and `bundle install` when vendor/cache exists) package
|
|
7
|
+
# the gems from every lockfile, and only prune gems that none of them use.
|
|
8
|
+
# Likewise, `bundle clean` only removes gems that none of the lockfiles use, and the
|
|
9
|
+
# `prune` setting covers the git gems from all of them.
|
|
10
|
+
module Runtime
|
|
11
|
+
::Bundler::Runtime.prepend(self)
|
|
12
|
+
|
|
13
|
+
def cache(custom_path = nil, *)
|
|
14
|
+
cache_alternate_lockfiles(custom_path)
|
|
15
|
+
super
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def prune_cache(cache_path)
|
|
19
|
+
return super if multilock_alternate_definitions.empty?
|
|
20
|
+
|
|
21
|
+
ensure_multilock_cache_path(cache_path)
|
|
22
|
+
|
|
23
|
+
resolve = [@definition, *multilock_alternate_definitions].flat_map { |definition| definition.resolve.to_a }
|
|
24
|
+
prune_gem_cache(resolve, cache_path)
|
|
25
|
+
prune_git_and_path_cache(resolve, cache_path)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Bundler's `clean` only keeps what the one definition needs, so keep what all of them need.
|
|
29
|
+
# It also keys the specs it keeps by name, which would drop all but one version of a gem
|
|
30
|
+
# that the lockfiles disagree on, so that's replaced for the duration. (Keyed by where they
|
|
31
|
+
# are installed, since different lockfiles can lock different revisions of the same git gem.)
|
|
32
|
+
def clean(*)
|
|
33
|
+
alternate_definitions = multilock_alternate_definitions
|
|
34
|
+
return super if alternate_definitions.empty?
|
|
35
|
+
|
|
36
|
+
combined = [specs, *alternate_definitions.map(&:specs)].flat_map(&:to_a)
|
|
37
|
+
rubygems = Bundler.rubygems
|
|
38
|
+
original_add_default_gems_to = rubygems.method(:add_default_gems_to)
|
|
39
|
+
rubygems.define_singleton_method(:add_default_gems_to) do |_specs|
|
|
40
|
+
(original_add_default_gems_to.call([]).values + combined).to_h { |spec| [spec.full_gem_path, spec] }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
begin
|
|
44
|
+
super
|
|
45
|
+
ensure
|
|
46
|
+
rubygems.singleton_class.send(:remove_method, :add_default_gems_to)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
# Same as Bundler's, except that it also covers the git gems that only other lockfiles use
|
|
53
|
+
def prune_git_metadata
|
|
54
|
+
return super if multilock_alternate_definitions.empty?
|
|
55
|
+
|
|
56
|
+
owned = "#{Bundler.install_path}#{File::SEPARATOR}"
|
|
57
|
+
git_sources = [@definition, *multilock_alternate_definitions].flat_map do |definition|
|
|
58
|
+
definition.sources.git_sources
|
|
59
|
+
end
|
|
60
|
+
git_dirs = git_sources.reject(&:local?).filter_map do |source|
|
|
61
|
+
install_path = source.install_path.to_s
|
|
62
|
+
next unless install_path.start_with?(owned)
|
|
63
|
+
|
|
64
|
+
git_dir = File.join(install_path, ".git")
|
|
65
|
+
git_dir if File.exist?(git_dir)
|
|
66
|
+
end.uniq
|
|
67
|
+
return if git_dirs.empty?
|
|
68
|
+
|
|
69
|
+
Bundler.ui.info "Removing git metadata from checked out git gems"
|
|
70
|
+
git_dirs.each do |git_dir|
|
|
71
|
+
::Bundler::SharedHelpers.filesystem_access(git_dir) do |p|
|
|
72
|
+
FileUtils.rm_rf(p)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def ensure_multilock_cache_path(cache_path)
|
|
78
|
+
return if File.exist?(cache_path)
|
|
79
|
+
|
|
80
|
+
::Bundler::SharedHelpers.filesystem_access(cache_path) do |p|
|
|
81
|
+
FileUtils.mkdir_p(p)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# @return [Array<Definition>] the definitions of the lockfiles other than the one being cached
|
|
86
|
+
def multilock_alternate_definitions
|
|
87
|
+
@multilock_alternate_definitions ||= Multilock.alternate_definitions
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Caches the gems that only the other lockfiles use. The ones in common are cached by the
|
|
91
|
+
# usual process, which also cleans up git sources and prunes afterwards.
|
|
92
|
+
def cache_alternate_lockfiles(custom_path)
|
|
93
|
+
return if multilock_alternate_definitions.empty?
|
|
94
|
+
|
|
95
|
+
cache_path = Bundler.app_cache(custom_path)
|
|
96
|
+
ensure_multilock_cache_path(cache_path)
|
|
97
|
+
|
|
98
|
+
cached = Set.new
|
|
99
|
+
multilock_alternate_definitions.each do |definition|
|
|
100
|
+
specs_to_cache = if Bundler.settings[:cache_all_platforms]
|
|
101
|
+
definition.resolve.materialized_for_all_platforms
|
|
102
|
+
else
|
|
103
|
+
definition.specs
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
specs_to_cache.each do |spec|
|
|
107
|
+
next if spec.name == "bundler"
|
|
108
|
+
|
|
109
|
+
source = spec.source
|
|
110
|
+
next if source.is_a?(::Bundler::Source::Gemspec)
|
|
111
|
+
|
|
112
|
+
# git sources are equal regardless of which revision is locked, but each one
|
|
113
|
+
# is cached separately
|
|
114
|
+
cache_key = source.respond_to?(:app_cache_dirname) ? source.app_cache_dirname : source
|
|
115
|
+
next unless cached.add?([spec.full_name, cache_key])
|
|
116
|
+
|
|
117
|
+
if source.respond_to?(:migrate_cache)
|
|
118
|
+
source.migrate_cache(custom_path, local: false)
|
|
119
|
+
elsif source.respond_to?(:cache)
|
|
120
|
+
source.cache(spec, custom_path)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
data/lib/bundler/multilock.rb
CHANGED
|
@@ -4,6 +4,7 @@ require_relative "multilock/ext/bundler"
|
|
|
4
4
|
require_relative "multilock/ext/definition"
|
|
5
5
|
require_relative "multilock/ext/dsl"
|
|
6
6
|
require_relative "multilock/ext/plugin/dsl"
|
|
7
|
+
require_relative "multilock/ext/runtime"
|
|
7
8
|
require_relative "multilock/ext/shared_helpers"
|
|
8
9
|
require_relative "multilock/ext/source"
|
|
9
10
|
require_relative "multilock/ext/source_list"
|
|
@@ -40,11 +41,15 @@ module Bundler
|
|
|
40
41
|
parent: nil,
|
|
41
42
|
enforce_pinned_additional_dependencies: false,
|
|
42
43
|
&block)
|
|
44
|
+
# remembered for gems that need to be kept for the primary lockfile, even if it was never
|
|
45
|
+
# declared and an alternate lockfile is active (which may use its own Gemfile)
|
|
46
|
+
@primary_gemfile ||= Bundler.default_gemfile
|
|
47
|
+
@primary_lockfile ||= Bundler.default_lockfile(force_original: true)
|
|
48
|
+
|
|
43
49
|
active = true if active.nil? && lockfile_definitions.empty? && lockfile.nil? && gemfile.nil?
|
|
44
50
|
|
|
45
51
|
# if a gemfile was provided, but not a lockfile, infer the default lockfile for that gemfile
|
|
46
52
|
lockfile ||= "#{gemfile}.lock" if gemfile
|
|
47
|
-
# allow short-form lockfile names
|
|
48
53
|
lockfile = expand_lockfile(lockfile)
|
|
49
54
|
|
|
50
55
|
raise ArgumentError, "Lockfile #{lockfile} is already defined" if lockfile_definitions.key?(lockfile)
|
|
@@ -139,9 +144,6 @@ module Bundler
|
|
|
139
144
|
|
|
140
145
|
Bundler.ui.debug("Syncing to alternate lockfiles")
|
|
141
146
|
|
|
142
|
-
attempts = 1
|
|
143
|
-
previous_contents = Set.new
|
|
144
|
-
|
|
145
147
|
default_root = Bundler.root
|
|
146
148
|
|
|
147
149
|
cache = Cache.new
|
|
@@ -158,17 +160,6 @@ module Bundler
|
|
|
158
160
|
|
|
159
161
|
relative_lockfile = lockfile_name.relative_path_from(Dir.pwd)
|
|
160
162
|
|
|
161
|
-
# prevent infinite loops of tick-tocking back and forth between two versions
|
|
162
|
-
current_contents = cache.contents(lockfile_name)
|
|
163
|
-
if previous_contents.include?(current_contents)
|
|
164
|
-
Bundler.ui.debug("Unable to converge on a single solution for #{lockfile_name}; " \
|
|
165
|
-
"perhaps there are conflicting requirements?")
|
|
166
|
-
attempts = 1
|
|
167
|
-
previous_contents.clear
|
|
168
|
-
next
|
|
169
|
-
end
|
|
170
|
-
previous_contents << current_contents
|
|
171
|
-
|
|
172
163
|
# already up to date?
|
|
173
164
|
up_to_date = false
|
|
174
165
|
conflicts = Set.new
|
|
@@ -178,13 +169,14 @@ module Bundler
|
|
|
178
169
|
checker.deep_check(lockfile_definition, conflicts:)
|
|
179
170
|
end
|
|
180
171
|
end
|
|
181
|
-
if up_to_date
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
172
|
+
next if up_to_date
|
|
173
|
+
|
|
174
|
+
# a missing lockfile that enforces pinned additional dependencies has nothing
|
|
175
|
+
# to be out of sync with, so even a frozen bundle just generates it
|
|
176
|
+
generate_missing = Bundler.frozen_bundle? && !lockfile_name.exist? &&
|
|
177
|
+
lockfile_definition[:enforce_pinned_additional_dependencies]
|
|
186
178
|
|
|
187
|
-
if Bundler.frozen_bundle?
|
|
179
|
+
if Bundler.frozen_bundle? && !generate_missing
|
|
188
180
|
# if we're frozen, you have to use the pre-existing lockfile
|
|
189
181
|
unless lockfile_name.exist?
|
|
190
182
|
Bundler.ui.error("The bundle is locked, but #{relative_lockfile} is missing. " \
|
|
@@ -196,7 +188,7 @@ module Bundler
|
|
|
196
188
|
Bundler.ui.info("Installing gems for #{relative_lockfile}...")
|
|
197
189
|
write_lockfile(lockfile_definition, lockfile_name, cache, install:)
|
|
198
190
|
else
|
|
199
|
-
Bundler.ui.info("Syncing to #{relative_lockfile}...")
|
|
191
|
+
Bundler.ui.info("Syncing to #{relative_lockfile}...")
|
|
200
192
|
synced_any = true
|
|
201
193
|
|
|
202
194
|
parent_lockfile_name = lockfile_definition[:parent]
|
|
@@ -225,6 +217,8 @@ module Bundler
|
|
|
225
217
|
TEXT
|
|
226
218
|
end
|
|
227
219
|
|
|
220
|
+
added_platforms = []
|
|
221
|
+
removed_platforms = []
|
|
228
222
|
if lockfile_name.exist?
|
|
229
223
|
# if the lockfile already exists, "merge" it together
|
|
230
224
|
parent_lockfile = if adjusted_parent_lockfile_contents == cache.contents(lockfile_name)
|
|
@@ -274,8 +268,32 @@ module Bundler
|
|
|
274
268
|
parent_spec
|
|
275
269
|
end
|
|
276
270
|
|
|
277
|
-
lockfile.
|
|
278
|
-
lockfile
|
|
271
|
+
# the parent's versions might depend on gems this lockfile didn't need before.
|
|
272
|
+
# without them, Bundler considers the lockfile broken, and ignores what's
|
|
273
|
+
# locked in it, which can update everything
|
|
274
|
+
names = lockfile.specs.to_set(&:name)
|
|
275
|
+
pending = lockfile.specs.dup
|
|
276
|
+
until pending.empty?
|
|
277
|
+
pending.shift.dependencies.each do |dependency|
|
|
278
|
+
next if names.include?(dependency.name) || !(dependency_specs = parent_specs[dependency.name])
|
|
279
|
+
|
|
280
|
+
names << dependency.name
|
|
281
|
+
dependency_changes = true
|
|
282
|
+
dependency_specs.each_value do |dependency_spec|
|
|
283
|
+
source = dependency_spec.source
|
|
284
|
+
lockfile.sources << source unless lockfile.sources.include?(source)
|
|
285
|
+
lockfile.specs << dependency_spec
|
|
286
|
+
pending << dependency_spec
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
# leave the lockfile's platforms alone, and let Bundler add and remove them itself
|
|
292
|
+
# (in write_lockfile), like `bundle lock --add-platform` and `--remove-platform`,
|
|
293
|
+
# so that it also adds or removes the gems needed for them
|
|
294
|
+
removed_platforms = lockfile.platforms - parent_lockfile.platforms
|
|
295
|
+
added_platforms = parent_lockfile.platforms - lockfile.platforms
|
|
296
|
+
lockfile.instance_variable_set(:@ruby_version, parent_lockfile.ruby_version)
|
|
279
297
|
unless lockfile.bundler_version == parent_lockfile.bundler_version
|
|
280
298
|
unlocking_bundler = parent_lockfile.bundler_version
|
|
281
299
|
lockfile.instance_variable_set(:@bundler_version, parent_lockfile.bundler_version)
|
|
@@ -294,28 +312,20 @@ module Bundler
|
|
|
294
312
|
temp_lockfile.write(new_contents)
|
|
295
313
|
temp_lockfile.flush
|
|
296
314
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
315
|
+
# Bundler refuses to write a lockfile when frozen, which we need to allow in the case
|
|
316
|
+
# of a missing lockfile that enforces pinned dependencies.
|
|
317
|
+
Bundler.settings.temporary(frozen: generate_missing ? false : Bundler.frozen_bundle?) do
|
|
318
|
+
had_changes ||= write_lockfile(lockfile_definition,
|
|
319
|
+
temp_lockfile.path,
|
|
320
|
+
cache,
|
|
321
|
+
install:,
|
|
322
|
+
dependency_changes:,
|
|
323
|
+
unlocking_bundler:,
|
|
324
|
+
added_platforms:,
|
|
325
|
+
removed_platforms:)
|
|
326
|
+
end
|
|
303
327
|
end
|
|
304
328
|
cache.invalidate_lockfile(lockfile_name) if had_changes
|
|
305
|
-
|
|
306
|
-
# if we had changes, bundler may have updated some common
|
|
307
|
-
# dependencies beyond the default lockfile, so re-run it
|
|
308
|
-
# once to reset them back to the default lockfile's version.
|
|
309
|
-
# if it's already good, the `check` check at the beginning of
|
|
310
|
-
# the loop will skip the second sync anyway.
|
|
311
|
-
if had_changes
|
|
312
|
-
attempts += 1
|
|
313
|
-
Bundler.ui.debug("Re-running sync to #{relative_lockfile} to reset common dependencies")
|
|
314
|
-
redo
|
|
315
|
-
else
|
|
316
|
-
attempts = 1
|
|
317
|
-
previous_contents.clear
|
|
318
|
-
end
|
|
319
329
|
end
|
|
320
330
|
end
|
|
321
331
|
ensure
|
|
@@ -377,10 +387,10 @@ module Bundler
|
|
|
377
387
|
return [] unless lockfile
|
|
378
388
|
return [lockfile] if recovered
|
|
379
389
|
|
|
380
|
-
# we can't tell if Bundler expanded
|
|
381
|
-
#
|
|
390
|
+
# we can't tell if Bundler expanded "active" to an absolute path,
|
|
391
|
+
# or if it was written that way, so allow either
|
|
382
392
|
relative = Pathname.new(lockfile).relative_path_from(Pathname.pwd).to_s
|
|
383
|
-
relative
|
|
393
|
+
(relative == "active") ? [lockfile, relative] : [lockfile]
|
|
384
394
|
end
|
|
385
395
|
|
|
386
396
|
# @!visibility private
|
|
@@ -402,6 +412,8 @@ module Bundler
|
|
|
402
412
|
def reset!
|
|
403
413
|
@lockfile_definitions = {}
|
|
404
414
|
@loaded = false
|
|
415
|
+
@primary_gemfile = nil
|
|
416
|
+
@primary_lockfile = nil
|
|
405
417
|
end
|
|
406
418
|
|
|
407
419
|
# @!visibility private
|
|
@@ -409,6 +421,40 @@ module Bundler
|
|
|
409
421
|
lockfile_definitions[Bundler.default_lockfile(force_original: true)]
|
|
410
422
|
end
|
|
411
423
|
|
|
424
|
+
# @!visibility private
|
|
425
|
+
# The definitions of the other lockfiles, when working with all of them (so not with
|
|
426
|
+
# BUNDLE_LOCKFILE), for packaging gems from all of them. Their gems need to have been
|
|
427
|
+
# installed already, by a regular `bundle install`.
|
|
428
|
+
#
|
|
429
|
+
# @return [Array<Definition>]
|
|
430
|
+
def alternate_definitions
|
|
431
|
+
return [] if lockfile_definitions.empty? || env_lockfile
|
|
432
|
+
|
|
433
|
+
# the primary lockfile doesn't have to be declared
|
|
434
|
+
candidates = lockfile_definitions.values
|
|
435
|
+
if @primary_lockfile && !lockfile_definitions.key?(@primary_lockfile)
|
|
436
|
+
candidates += [{ gemfile: @primary_gemfile, lockfile: @primary_lockfile, prepare: nil }]
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
default_root = Bundler.root
|
|
440
|
+
candidates.filter_map do |lockfile_definition|
|
|
441
|
+
lockfile = lockfile_definition[:lockfile]
|
|
442
|
+
# the one Bundler is already working with, which may be an alternate lockfile flagged as active
|
|
443
|
+
next if lockfile == Bundler.default_lockfile
|
|
444
|
+
next unless lockfile.exist?
|
|
445
|
+
|
|
446
|
+
Bundler.root = lockfile_definition[:gemfile].dirname
|
|
447
|
+
builder = Dsl.new
|
|
448
|
+
prepare_block = lockfile_definition[:prepare]
|
|
449
|
+
builder.eval_gemfile(lockfile_definition[:gemfile], &prepare_block) if prepare_block
|
|
450
|
+
builder.eval_gemfile(lockfile_definition[:gemfile])
|
|
451
|
+
# (as the default lockfile, so that it isn't swapped for the active one)
|
|
452
|
+
Bundler.with_default_lockfile(lockfile) { builder.to_definition(lockfile, {}) }
|
|
453
|
+
end
|
|
454
|
+
ensure
|
|
455
|
+
Bundler.root = default_root if default_root
|
|
456
|
+
end
|
|
457
|
+
|
|
412
458
|
private
|
|
413
459
|
|
|
414
460
|
# @return [Array(String, true or false), nil]
|
|
@@ -436,9 +482,6 @@ module Bundler
|
|
|
436
482
|
end
|
|
437
483
|
|
|
438
484
|
def expand_lockfile(lockfile)
|
|
439
|
-
if lockfile.is_a?(String) && !(lockfile.include?("/") || lockfile.end_with?(".lock"))
|
|
440
|
-
lockfile = "Gemfile.#{lockfile}.lock"
|
|
441
|
-
end
|
|
442
485
|
# use absolute paths
|
|
443
486
|
lockfile = Bundler.root.join(lockfile).expand_path if lockfile
|
|
444
487
|
# use the default lockfile (Gemfile.lock) if none was given
|
|
@@ -495,7 +538,9 @@ module Bundler
|
|
|
495
538
|
cache,
|
|
496
539
|
install:,
|
|
497
540
|
dependency_changes: false,
|
|
498
|
-
unlocking_bundler: false
|
|
541
|
+
unlocking_bundler: false,
|
|
542
|
+
added_platforms: [],
|
|
543
|
+
removed_platforms: [])
|
|
499
544
|
prepare_block = lockfile_definition[:prepare]
|
|
500
545
|
|
|
501
546
|
gemfile = lockfile_definition[:gemfile]
|
|
@@ -513,6 +558,8 @@ module Bundler
|
|
|
513
558
|
|
|
514
559
|
definition = builder.to_definition(lockfile, { bundler: unlocking_bundler })
|
|
515
560
|
definition.instance_variable_set(:@dependency_changes, dependency_changes) if dependency_changes
|
|
561
|
+
added_platforms.each { |platform| definition.add_platform(platform) }
|
|
562
|
+
removed_platforms.each { |platform| definition.remove_platform(platform) }
|
|
516
563
|
|
|
517
564
|
# match the parent lockfile in whether there are checksums
|
|
518
565
|
unless Bundler.frozen_bundle?
|
|
@@ -528,6 +575,10 @@ module Bundler
|
|
|
528
575
|
definition.instance_variable_set(:@lockfile_contents, current_lockfile.read) if current_lockfile.exist?
|
|
529
576
|
|
|
530
577
|
orig_definition = definition.dup # we might need it twice
|
|
578
|
+
# `dup` shares the platforms array, and resolving locally changes it (like dropping the ruby platform,
|
|
579
|
+
# and adding the local platform) before it might fail, which would leave a remote resolution
|
|
580
|
+
# starting from the wrong platforms
|
|
581
|
+
orig_definition.instance_variable_set(:@platforms, definition.instance_variable_get(:@platforms).dup)
|
|
531
582
|
|
|
532
583
|
# install gems for the exact current version of the lockfile
|
|
533
584
|
# this ensures it doesn't re-resolve with only (different)
|
|
@@ -563,8 +614,10 @@ module Bundler
|
|
|
563
614
|
previous_ui_level = Bundler.ui.level
|
|
564
615
|
Bundler.ui.level = "warn"
|
|
565
616
|
begin
|
|
566
|
-
# force a remote resolution if intermediate gems are missing
|
|
567
|
-
|
|
617
|
+
# force a remote resolution if intermediate gems are missing, or if platforms were added
|
|
618
|
+
# (a gem's source variant would satisfy them locally, without its platform specific variants)
|
|
619
|
+
if (added_platforms.any? && !local_only?) ||
|
|
620
|
+
definition.instance_variable_get(:@locked_spec_with_missing_deps) ||
|
|
568
621
|
definition.instance_variable_get(:@locked_spec_with_invalid_deps) ||
|
|
569
622
|
definition.instance_variable_get(:@missing_lockfile_dep) ||
|
|
570
623
|
definition.instance_variable_get(:@invalid_lockfile_dep)
|
|
@@ -584,6 +637,11 @@ module Bundler
|
|
|
584
637
|
spec.source.specs << spec
|
|
585
638
|
end
|
|
586
639
|
resolve_locally(definition)
|
|
640
|
+
# a local resolution can only see the gems that are installed, so it can drop platforms
|
|
641
|
+
# (like ruby) that remote gem variants would keep. the platforms should match the parent's
|
|
642
|
+
parent_platforms = cache.parser(lockfile_definition[:parent]).platforms.map(&:to_s).sort
|
|
643
|
+
raise SolveFailure unless local_only? || definition.platforms.map(&:to_s).sort == parent_platforms
|
|
644
|
+
|
|
587
645
|
missing_checksums = fill_checksums(definition, lockfile_definition[:parent], cache)
|
|
588
646
|
# fetch checksums that aren't available locally
|
|
589
647
|
raise SolveFailure unless missing_checksums.empty? || local_only?
|
|
@@ -603,6 +661,11 @@ module Bundler
|
|
|
603
661
|
"Run without `--local` to fetch them."
|
|
604
662
|
end
|
|
605
663
|
SharedHelpers.capture_filesystem_access do
|
|
664
|
+
# a frozen bundle can't change its lockfile, and trying to just fails with a misleading
|
|
665
|
+
# error from Bundler (like about updating Bundler itself). install what it locks, and
|
|
666
|
+
# let the check afterwards report what's actually wrong with it
|
|
667
|
+
next if Bundler.frozen_bundle?
|
|
668
|
+
|
|
606
669
|
definition.instance_variable_set(:@resolved_bundler_version, unlocking_bundler) if unlocking_bundler
|
|
607
670
|
|
|
608
671
|
# need to force it to _not_ preserve unknown sections, so that it
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bundler-multilock
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.0.0.
|
|
4
|
+
version: 2.0.0.beta5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Instructure
|
|
@@ -18,7 +18,7 @@ dependencies:
|
|
|
18
18
|
version: 4.1.0.beta2
|
|
19
19
|
- - "<"
|
|
20
20
|
- !ruby/object:Gem::Version
|
|
21
|
-
version: '
|
|
21
|
+
version: '4.2'
|
|
22
22
|
type: :runtime
|
|
23
23
|
prerelease: false
|
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -28,7 +28,7 @@ dependencies:
|
|
|
28
28
|
version: 4.1.0.beta2
|
|
29
29
|
- - "<"
|
|
30
30
|
- !ruby/object:Gem::Version
|
|
31
|
-
version: '
|
|
31
|
+
version: '4.2'
|
|
32
32
|
executables: []
|
|
33
33
|
extensions: []
|
|
34
34
|
extra_rdoc_files: []
|
|
@@ -41,6 +41,7 @@ files:
|
|
|
41
41
|
- lib/bundler/multilock/ext/definition.rb
|
|
42
42
|
- lib/bundler/multilock/ext/dsl.rb
|
|
43
43
|
- lib/bundler/multilock/ext/plugin/dsl.rb
|
|
44
|
+
- lib/bundler/multilock/ext/runtime.rb
|
|
44
45
|
- lib/bundler/multilock/ext/shared_helpers.rb
|
|
45
46
|
- lib/bundler/multilock/ext/source.rb
|
|
46
47
|
- lib/bundler/multilock/ext/source_list.rb
|