From d49566ba06377a27dea66350a57c1a73b7042037 Mon Sep 17 00:00:00 2001 From: Mike McQuaid Date: Tue, 10 Jul 2018 09:29:26 +0100 Subject: [PATCH] tab: if parsing JSON fails output the filename. This should make it easier to debug and resolve things like #4439. --- Library/Homebrew/tab.rb | 6 +++++- Library/Homebrew/test/tab_spec.rb | 36 ++++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/Library/Homebrew/tab.rb b/Library/Homebrew/tab.rb index fb6d45cafb..c0eccc6372 100644 --- a/Library/Homebrew/tab.rb +++ b/Library/Homebrew/tab.rb @@ -58,7 +58,11 @@ class Tab < OpenStruct # Like Tab.from_file, but bypass the cache. def self.from_file_content(content, path) - attributes = JSON.parse(content) + attributes = begin + JSON.parse(content) + rescue JSON::ParserError => e + raise e, "Cannot parse #{path}: #{e}", e.backtrace + end attributes["tabfile"] = path attributes["source_modified_time"] ||= 0 attributes["source"] ||= {} diff --git a/Library/Homebrew/test/tab_spec.rb b/Library/Homebrew/test/tab_spec.rb index c8448964fc..bf55544119 100644 --- a/Library/Homebrew/test/tab_spec.rb +++ b/Library/Homebrew/test/tab_spec.rb @@ -191,10 +191,40 @@ describe Tab do expect(tab.head_version.to_s).to eq("HEAD-0000000") expect(tab.source["path"]).to eq(source_path) end + end + + describe "::from_file_content" do + it "parses a Tab from a file" do + path = Pathname.new("#{TEST_FIXTURE_DIR}/receipt.json") + tab = described_class.from_file_content(path.read, path) + source_path = "/usr/local/Library/Taps/homebrew/homebrew-core/Formula/foo.rb" + runtime_dependencies = [{ "full_name" => "foo", "version" => "1.0" }] + changed_files = %w[INSTALL_RECEIPT.json bin/foo] + + expect(tab.used_options.sort).to eq(used_options.sort) + expect(tab.unused_options.sort).to eq(unused_options.sort) + expect(tab.changed_files).to eq(changed_files) + expect(tab).not_to be_built_as_bottle + expect(tab).to be_poured_from_bottle + expect(tab).to be_stable + expect(tab).not_to be_devel + expect(tab).not_to be_head + expect(tab.tap.name).to eq("homebrew/core") + expect(tab.spec).to eq(:stable) + expect(tab.time).to eq(Time.at(1_403_827_774).to_i) + expect(tab.HEAD).to eq(TEST_SHA1) + expect(tab.cxxstdlib.compiler).to eq(:clang) + expect(tab.cxxstdlib.type).to eq(:libcxx) + expect(tab.runtime_dependencies).to eq(runtime_dependencies) + expect(tab.stable_version.to_s).to eq("2.14") + expect(tab.devel_version.to_s).to eq("2.15") + expect(tab.head_version.to_s).to eq("HEAD-0000000") + expect(tab.source["path"]).to eq(source_path) + end it "can parse an old Tab file" do path = Pathname.new("#{TEST_FIXTURE_DIR}/receipt_old.json") - tab = described_class.from_file(path) + tab = described_class.from_file_content(path.read, path) expect(tab.used_options.sort).to eq(used_options.sort) expect(tab.unused_options.sort).to eq(unused_options.sort) @@ -211,6 +241,10 @@ describe Tab do expect(tab.cxxstdlib.type).to eq(:libcxx) expect(tab.runtime_dependencies).to be nil end + + it "raises an parse exception message including the Tab filename" do + expect { described_class.from_file_content("''", "receipt.json") }.to raise_error(JSON::ParserError, /receipt.json:/) + end end describe "::create" do