diff --git a/Library/Homebrew/cask/lib/hbc/system_command.rb b/Library/Homebrew/cask/lib/hbc/system_command.rb index 0c6f0eb367..aee41e5672 100644 --- a/Library/Homebrew/cask/lib/hbc/system_command.rb +++ b/Library/Homebrew/cask/lib/hbc/system_command.rb @@ -137,48 +137,35 @@ module Hbc @exit_status = exit_status end - def plist - @plist ||= self.class._parse_plist(@command, @stdout.dup) - end - def success? @exit_status.zero? end - def merged_output - @merged_output ||= @stdout + @stderr - end + def plist + @plist ||= begin + output = stdout - def to_s - @stdout - end + if /\A(?.*?)<\?\s*xml/m =~ output + output = output.sub(/\A#{Regexp.escape(garbage)}/m, "") + warn_plist_garbage(garbage) + end - def self._warn_plist_garbage(command, garbage) - return true unless garbage =~ /\S/ - external = File.basename(command.first) - lines = garbage.strip.split("\n") - opoo "Non-XML stdout from #{external}:" - $stderr.puts lines.map { |l| " #{l}" } - end + if %r{<\s*/\s*plist\s*>(?.*?)\Z}m =~ output + output = output.sub(/#{Regexp.escape(garbage)}\Z/, "") + warn_plist_garbage(garbage) + end - def self._parse_plist(command, output) - raise CaskError, "Empty plist input" unless output =~ /\S/ - output.sub!(/\A(.*?)(<\?\s*xml)/m, '\2') - _warn_plist_garbage(command, Regexp.last_match[1]) if ARGV.debug? - output.sub!(%r{(<\s*/\s*plist\s*>)(.*?)\Z}m, '\1') - _warn_plist_garbage(command, Regexp.last_match[2]) - xml = Plist.parse_xml(output) - unless xml.respond_to?(:keys) && !xml.keys.empty? - raise CaskError, <<~EOS - Empty result parsing plist output from command. - command was: - #{command} - output we attempted to parse: - #{output} - EOS + Plist.parse_xml(output) end - xml end + + def warn_plist_garbage(garbage) + return unless ARGV.verbose? + return unless garbage =~ /\S/ + opoo "Received non-XML output from #{Formatter.identifier(command.first)}:" + $stderr.puts garbage.strip + end + private :warn_plist_garbage end end end diff --git a/Library/Homebrew/test/cask/system_command_result_spec.rb b/Library/Homebrew/test/cask/system_command_result_spec.rb index 18dd2d910d..b71838518a 100644 --- a/Library/Homebrew/test/cask/system_command_result_spec.rb +++ b/Library/Homebrew/test/cask/system_command_result_spec.rb @@ -1,10 +1,21 @@ require "hbc/system_command" describe Hbc::SystemCommand::Result, :cask do - describe "::_parse_plist" do - subject { described_class._parse_plist(command, input) } + describe "#plist" do + subject { described_class.new(command, stdout, "", 0).plist } - let(:command) { Hbc::SystemCommand.new("/usr/bin/true", {}) } + let(:command) { ["/usr/bin/true"] } + let(:garbage) { + <<~EOS + Hello there! I am in no way XML am I?!?! + + That's a little silly... you were expecting XML here! + + What is a parser to do? + + Hopefully explode! + EOS + } let(:plist) { <<~EOS @@ -53,29 +64,56 @@ describe Hbc::SystemCommand::Result, :cask do EOS } - context "when output contains garbage" do - let(:input) { + context "when stdout contains garbage before XML" do + let(:stdout) { <<~EOS - Hello there! I am in no way XML am I?!?! - - That's a little silly... you were expexting XML here! - - What is a parser to do? - - Hopefully explode! - + #{garbage} #{plist} EOS } - it "ignores garbage before xml" do - expect(subject.keys).to eq(["system-entities"]) + it "ignores garbage" do expect(subject["system-entities"].length).to eq(3) end + + context "when verbose" do + before(:each) do + allow(ARGV).to receive(:verbose?).and_return(true) + end + + it "warns about garbage" do + expect { subject } + .to output(a_string_containing(garbage)).to_stderr + end + end end - context "given a hdiutil output as input" do - let(:input) { plist } + context "when stdout contains garbage after XML" do + let(:stdout) { + <<~EOS + #{plist} + #{garbage} + EOS + } + + it "ignores garbage" do + expect(subject["system-entities"].length).to eq(3) + end + + context "when verbose" do + before(:each) do + allow(ARGV).to receive(:verbose?).and_return(true) + end + + it "warns about garbage" do + expect { subject } + .to output(a_string_containing(garbage)).to_stderr + end + end + end + + context "given a hdiutil stdout" do + let(:stdout) { plist } it "successfully parses it" do expect(subject.keys).to eq(["system-entities"]) @@ -85,11 +123,11 @@ describe Hbc::SystemCommand::Result, :cask do end end - context "given an empty input" do - let(:input) { "" } + context "when the stdout of the command is empty" do + let(:stdout) { "" } - it "raises an error" do - expect { subject }.to raise_error(Hbc::CaskError, /Empty plist input/) + it "returns nil" do + expect(subject).to be nil end end end diff --git a/Library/Homebrew/test/spec_helper.rb b/Library/Homebrew/test/spec_helper.rb index b7a657bf60..8bf3369c9f 100644 --- a/Library/Homebrew/test/spec_helper.rb +++ b/Library/Homebrew/test/spec_helper.rb @@ -166,3 +166,4 @@ end RSpec::Matchers.define_negated_matcher :not_to_output, :output RSpec::Matchers.alias_matcher :have_failed, :be_failed +RSpec::Matchers.alias_matcher :a_string_containing, :include