Skip to content

Commit 5593098

Browse files
deivid-rodriguezhsbt
authored andcommitted
[rubygems/rubygems] Raise an error in frozen mode if CHECKSUMS entries are missing
ruby/rubygems@054a0cd76c
1 parent 60d00da commit 5593098

File tree

7 files changed

+90
-24
lines changed

7 files changed

+90
-24
lines changed

lib/bundler/checksum.rb

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -201,9 +201,11 @@ def replace(spec, checksum)
201201
end
202202
end
203203

204-
def register(spec, checksum)
205-
return unless checksum
204+
def missing?(spec)
205+
@store[spec.lock_name].nil?
206+
end
206207

208+
def register(spec, checksum)
207209
register_checksum(spec.lock_name, checksum)
208210
end
209211

@@ -218,7 +220,7 @@ def merge!(other)
218220
def to_lock(spec)
219221
lock_name = spec.lock_name
220222
checksums = @store[lock_name]
221-
if checksums
223+
if checksums&.any?
222224
"#{lock_name} #{checksums.values.map(&:to_lock).sort.join(",")}"
223225
else
224226
lock_name
@@ -229,11 +231,15 @@ def to_lock(spec)
229231

230232
def register_checksum(lock_name, checksum)
231233
@store_mutex.synchronize do
232-
existing = fetch_checksum(lock_name, checksum.algo)
233-
if existing
234-
merge_checksum(lock_name, checksum, existing)
234+
if checksum
235+
existing = fetch_checksum(lock_name, checksum.algo)
236+
if existing
237+
merge_checksum(lock_name, checksum, existing)
238+
else
239+
store_checksum(lock_name, checksum)
240+
end
235241
else
236-
store_checksum(lock_name, checksum)
242+
init_checksum(lock_name)
237243
end
238244
end
239245
end
@@ -243,7 +249,11 @@ def merge_checksum(lock_name, checksum, existing)
243249
end
244250

245251
def store_checksum(lock_name, checksum)
246-
(@store[lock_name] ||= {})[checksum.algo] = checksum
252+
init_checksum(lock_name)[checksum.algo] = checksum
253+
end
254+
255+
def init_checksum(lock_name)
256+
@store[lock_name] ||= {}
247257
end
248258

249259
def fetch_checksum(lock_name, algo)

lib/bundler/definition.rb

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,8 @@ def initialize(lockfile, dependencies, sources, unlock, ruby_version = nil, opti
147147

148148
@current_platform_missing = add_current_platform unless Bundler.frozen_bundle?
149149

150-
@path_changes = converge_paths
151150
@source_changes = converge_sources
151+
@path_changes = converge_paths
152152

153153
if conservative
154154
@gems_to_unlock = @explicit_unlocks.any? ? @explicit_unlocks : @dependencies.map(&:name)
@@ -563,6 +563,7 @@ def something_changed?
563563
@local_changes ||
564564
@missing_lockfile_dep ||
565565
@unlocking_bundler ||
566+
@locked_spec_with_missing_checksums ||
566567
@locked_spec_with_missing_deps ||
567568
@locked_spec_with_invalid_deps
568569
end
@@ -815,6 +816,7 @@ def change_reason
815816
[@local_changes, "the gemspecs for git local gems changed"],
816817
[@missing_lockfile_dep, "your lockfile is missing \"#{@missing_lockfile_dep}\""],
817818
[@unlocking_bundler, "an update to the version of Bundler itself was requested"],
819+
[@locked_spec_with_missing_checksums, "your lockfile is missing a CHECKSUMS entry for \"#{@locked_spec_with_missing_checksums}\""],
818820
[@locked_spec_with_missing_deps, "your lockfile includes \"#{@locked_spec_with_missing_deps}\" but not some of its dependencies"],
819821
[@locked_spec_with_invalid_deps, "your lockfile does not satisfy dependencies of \"#{@locked_spec_with_invalid_deps}\""],
820822
].select(&:first).map(&:last).join(", ")
@@ -873,21 +875,27 @@ def converge_locals
873875
def check_lockfile
874876
@locked_spec_with_invalid_deps = nil
875877
@locked_spec_with_missing_deps = nil
878+
@locked_spec_with_missing_checksums = nil
876879

877-
missing = []
880+
missing_deps = []
881+
missing_checksums = []
878882
invalid = []
879883

880884
@locked_specs.each do |s|
885+
missing_checksums << s if @locked_checksums && s.source.checksum_store.missing?(s)
886+
881887
validation = @locked_specs.validate_deps(s)
882888

883-
missing << s if validation == :missing
889+
missing_deps << s if validation == :missing
884890
invalid << s if validation == :invalid
885891
end
886892

887-
if missing.any?
888-
@locked_specs.delete(missing)
893+
@locked_spec_with_missing_checksums = missing_checksums.first.name if missing_checksums.any?
894+
895+
if missing_deps.any?
896+
@locked_specs.delete(missing_deps)
889897

890-
@locked_spec_with_missing_deps = missing.first.name
898+
@locked_spec_with_missing_deps = missing_deps.first.name
891899
end
892900

893901
if invalid.any?

lib/bundler/lockfile_parser.rb

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,6 @@ def parse_checksum(line)
239239
spaces = $1
240240
return unless spaces.size == 2
241241
checksums = $6
242-
return unless checksums
243242
name = $2
244243
version = $3
245244
platform = $4
@@ -249,10 +248,14 @@ def parse_checksum(line)
249248
full_name = Gem::NameTuple.new(name, version, platform).full_name
250249
return unless spec = @specs[full_name]
251250

252-
checksums.split(",") do |lock_checksum|
253-
column = line.index(lock_checksum) + 1
254-
checksum = Checksum.from_lock(lock_checksum, "#{@lockfile_path}:#{@pos.line}:#{column}")
255-
spec.source.checksum_store.register(spec, checksum)
251+
if checksums
252+
checksums.split(",") do |lock_checksum|
253+
column = line.index(lock_checksum) + 1
254+
checksum = Checksum.from_lock(lock_checksum, "#{@lockfile_path}:#{@pos.line}:#{column}")
255+
spec.source.checksum_store.register(spec, checksum)
256+
end
257+
else
258+
spec.source.checksum_store.register(spec, nil)
256259
end
257260
end
258261

lib/bundler/source/gemspec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ module Bundler
44
class Source
55
class Gemspec < Path
66
attr_reader :gemspec
7+
attr_writer :checksum_store
78

89
def initialize(options)
910
super

lib/bundler/source_list.rb

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,7 @@ def map_sources(replacement_sources)
183183
end
184184

185185
path = @path_sources.map do |source|
186-
next source if source.is_a?(Source::Gemspec)
187-
188-
replace_source(replacement_sources, source)
186+
replace_path_source(replacement_sources, source)
189187
end
190188

191189
[rubygems, path, git, plugin]
@@ -201,18 +199,31 @@ def replace_rubygems_source(replacement_sources, gemfile_source)
201199
replacement_source.remotes = gemfile_source.remotes
202200

203201
yield replacement_source if block_given?
202+
203+
replacement_source
204204
end
205205
end
206206

207207
def replace_source(replacement_sources, gemfile_source)
208208
replacement_source = replacement_sources.find {|s| s == gemfile_source }
209209
return gemfile_source unless replacement_source
210210

211-
yield replacement_source if block_given?
211+
replacement_source = yield(replacement_source) if block_given?
212212

213213
replacement_source
214214
end
215215

216+
def replace_path_source(replacement_sources, gemfile_source)
217+
replace_source(replacement_sources, gemfile_source) do |replacement_source|
218+
if gemfile_source.is_a?(Source::Gemspec)
219+
gemfile_source.checksum_store = replacement_source.checksum_store
220+
gemfile_source
221+
else
222+
replacement_source
223+
end
224+
end
225+
end
226+
216227
def different_sources?(lock_sources, replacement_sources)
217228
!equivalent_sources?(lock_sources, replacement_sources)
218229
end

spec/bundler/install/gemfile/sources_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1221,7 +1221,7 @@
12211221
12221222
DEPENDENCIES
12231223
myrack!
1224-
#{checksums_section}
1224+
12251225
BUNDLED WITH
12261226
#{Bundler::VERSION}
12271227
L

spec/bundler/lock/lockfile_spec.rb

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1613,6 +1613,39 @@
16131613
expect(the_bundle).not_to include_gems "myrack_middleware 1.0"
16141614
end
16151615

1616+
it "raises a clear error when frozen mode is set and lockfile is missing entries in CHECKSUMS section, and does not install any gems" do
1617+
lockfile <<-L
1618+
GEM
1619+
remote: https://gem.repo2/
1620+
specs:
1621+
myrack_middleware (1.0)
1622+
1623+
PLATFORMS
1624+
#{lockfile_platforms}
1625+
1626+
DEPENDENCIES
1627+
myrack_middleware
1628+
1629+
CHECKSUMS
1630+
1631+
BUNDLED WITH
1632+
#{Bundler::VERSION}
1633+
L
1634+
1635+
install_gemfile <<-G, env: { "BUNDLE_FROZEN" => "true" }, raise_on_error: false
1636+
source "https://gem.repo2"
1637+
gem "myrack_middleware"
1638+
G
1639+
1640+
expect(err).to eq <<~L.strip
1641+
Your lockfile is missing a checksums entry for \"myrack_middleware\", but can't be updated because frozen mode is set
1642+
1643+
Run `bundle install` elsewhere and add the updated Gemfile.lock to version control.
1644+
L
1645+
1646+
expect(the_bundle).not_to include_gems "myrack_middleware 1.0"
1647+
end
1648+
16161649
it "automatically fixes the lockfile when it's missing deps, they conflict with other locked deps, but conflicts are fixable" do
16171650
build_repo4 do
16181651
build_gem "other_dep", "0.9"

0 commit comments

Comments
 (0)