Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions bundler/lib/bundler/lockfile_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,17 @@ def initialize(lockfile, strict: false)
"Run `git checkout HEAD -- #{@lockfile_path}` first to get a clean lock."
end

@valid = lockfile.strip.empty? ||
lockfile.split(/(?:\r?\n)+/).any? {|l| KNOWN_SECTIONS.include?(l) }

unless @valid
SharedHelpers.feature_deprecated!(
"Your #{@lockfile_path} does not appear to be a valid lockfile. " \
"Run `rm #{@lockfile_path}` and then `bundle install` to generate a new lockfile. " \
"This will raise a LockfileError in a future version of Bundler."
)
end

lockfile.split(/((?:\r?\n)+)/) do |line|
# split alternates between the line and the following whitespace
next @pos.advance!(line) if line.match?(/^\s*$/)
Expand Down Expand Up @@ -164,6 +175,10 @@ def may_include_redundant_platform_specific_gems?
bundler_version.nil? || bundler_version < Gem::Version.new("1.16.2")
end

def valid?
@valid
end

private

TYPES = {
Expand Down
61 changes: 61 additions & 0 deletions spec/bundler/lockfile_parser_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@

shared_examples_for "parsing" do
it "parses correctly" do
expect(subject.valid?).to be(true)
expect(subject.sources).to eq sources
expect(subject.dependencies).to eq dependencies
expect(subject.specs).to eq specs
Expand Down Expand Up @@ -191,6 +192,66 @@
include_examples "parsing"
end

context "when the content does not contain any recognized lockfile sections" do
let(:lockfile_contents) { "hello world\nlorem ipsum\n" }

it "does not raise, is not valid, and deprecates" do
expect(Bundler::SharedHelpers).to receive(:feature_deprecated!).with(
/does not appear to be a valid lockfile.*future version of Bundler/m
)
parser = described_class.new(lockfile_contents)
expect(parser.valid?).to be(false)
expect(parser.specs).to eq([])
expect(parser.dependencies).to eq({})
end

it "does not raise when strict: true, and still deprecates" do
expect(Bundler::SharedHelpers).to receive(:feature_deprecated!).with(
/does not appear to be a valid lockfile.*future version of Bundler/m
)
parser = described_class.new(lockfile_contents, strict: true)
expect(parser.valid?).to be(false)
expect(parser.specs).to eq([])
expect(parser.dependencies).to eq({})
end
end

context "when the content looks like a Gemfile DSL" do
let(:lockfile_contents) { <<~G }
source "https://rubygems.org"
gem "rake"
G

it "does not raise, is not valid, and deprecates" do
expect(Bundler::SharedHelpers).to receive(:feature_deprecated!).with(
/does not appear to be a valid lockfile.*future version of Bundler/m
)
parser = described_class.new(lockfile_contents)
expect(parser.valid?).to be(false)
expect(parser.specs).to eq([])
expect(parser.dependencies).to eq({})
end

it "does not raise when strict: true, and still deprecates" do
expect(Bundler::SharedHelpers).to receive(:feature_deprecated!).with(
/does not appear to be a valid lockfile.*future version of Bundler/m
)
parser = described_class.new(lockfile_contents, strict: true)
expect(parser.valid?).to be(false)
expect(parser.specs).to eq([])
expect(parser.dependencies).to eq({})
end
end

context "when the content is empty" do
let(:lockfile_contents) { "" }

it "does not raise and is valid" do
expect { subject }.not_to raise_error
expect(subject.valid?).to be(true)
end
end

context "when CHECKSUMS has duplicate checksums in the lockfile that don't match" do
let(:bad_checksum) { "sha256=c0ffee11c0ffee11c0ffee11c0ffee11c0ffee11c0ffee11c0ffee11c0ffee11" }
let(:lockfile_contents) { super().split(/(?<=CHECKSUMS\n)/m).insert(1, " rake (10.3.2) #{bad_checksum}\n").join }
Expand Down