diff --git a/Library/Homebrew/cask/lib/hbc/audit.rb b/Library/Homebrew/cask/lib/hbc/audit.rb index 955ecdbb00df0b4a37af187f75ade9f75ae57fae..12cefb939542f9e573068b15b6b644b6ad0d3f63 100644 --- a/Library/Homebrew/cask/lib/hbc/audit.rb +++ b/Library/Homebrew/cask/lib/hbc/audit.rb @@ -133,20 +133,19 @@ module Hbc def check_appcast_checkpoint_accuracy odebug "Verifying appcast checkpoint is accurate" - result = @command.run("/usr/bin/curl", args: ["--compressed", "--location", "--user-agent", URL::FAKE_USER_AGENT, cask.appcast], print_stderr: false) - if result.success? - processed_appcast_text = result.stdout.gsub(%r{<pubDate>[^<]*</pubDate>}, "") - # This step is necessary to replicate running `sed` from the command line - processed_appcast_text << "\n" unless processed_appcast_text.end_with?("\n") + result = cask.appcast.calculate_checkpoint + + actual_checkpoint = result[:checkpoint] + + if actual_checkpoint.nil? + add_warning "error retrieving appcast: #{result[:command_result].stderr}" + else expected = cask.appcast.checkpoint - actual = Digest::SHA2.hexdigest(processed_appcast_text) - add_warning <<-EOS.undent unless expected == actual + add_warning <<-EOS.undent unless expected == actual_checkpoint appcast checkpoint mismatch Expected: #{expected} - Actual: #{actual} + Actual: #{actual_checkpoint} EOS - else - add_warning "error retrieving appcast: #{result.stderr}" end end diff --git a/Library/Homebrew/cask/lib/hbc/cli.rb b/Library/Homebrew/cask/lib/hbc/cli.rb index 42c3982ba8a3b83a5f669f3718d3e42524e8a97e..36fae30349fb43c795976db45ee03c7bef538e8f 100644 --- a/Library/Homebrew/cask/lib/hbc/cli.rb +++ b/Library/Homebrew/cask/lib/hbc/cli.rb @@ -23,6 +23,7 @@ require "hbc/cli/zap" require "hbc/cli/internal_use_base" require "hbc/cli/internal_audit_modified_casks" +require "hbc/cli/internal_appcast_checkpoint" require "hbc/cli/internal_checkurl" require "hbc/cli/internal_dump" require "hbc/cli/internal_help" diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb new file mode 100644 index 0000000000000000000000000000000000000000..6de76cbc77c1ab020e93fbede3ec816010ae194e --- /dev/null +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb @@ -0,0 +1,45 @@ +module Hbc + class CLI + class InternalAppcastCheckpoint < InternalUseBase + def self.run(*args) + cask_tokens = cask_tokens_from(args) + raise CaskUnspecifiedError if cask_tokens.empty? + + appcask_checkpoint(cask_tokens) + end + + def self.appcask_checkpoint(cask_tokens) + count = 0 + + cask_tokens.each do |cask_token| + cask = Hbc.load(cask_token) + + if cask.appcast.nil? + opoo "Cask '#{cask}' is missing an `appcast` stanza." + else + result = cask.appcast.calculate_checkpoint + + checkpoint = result[:checkpoint] + + if checkpoint.nil? + onoe "Could not retrieve `appcast` checkpoint for cask '#{cask}': #{result[:command_result].stderr}" + else + puts cask_tokens.count > 1 ? "#{checkpoint} #{cask}": checkpoint + count += 1 + end + end + end + + count == cask_tokens.count + end + + def self.help + "calculates a given Cask's appcast checkpoint" + end + + def self.needs_init? + true + end + end + end +end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb b/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb index 2f1245d3d942f3e19fd713be36b6ab5224947fa4..94660e9366bcd27b30b9d382ef352494a3ce8e43 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb @@ -1,3 +1,5 @@ +require "hbc/system_command" + module Hbc class DSL class Appcast @@ -9,6 +11,24 @@ module Hbc @checkpoint = @parameters[:checkpoint] end + def calculate_checkpoint + result = SystemCommand.run("/usr/bin/curl", args: ["--compressed", "--location", "--user-agent", URL::FAKE_USER_AGENT, @uri], print_stderr: false) + + checkpoint = if result.success? + processed_appcast_text = result.stdout.gsub(%r{<pubDate>[^<]*</pubDate>}, "") + + # This step is necessary to replicate running `sed` from the command line + processed_appcast_text << "\n" unless processed_appcast_text.end_with?("\n") + + Digest::SHA2.hexdigest(processed_appcast_text) + end + + { + checkpoint: checkpoint, + command_result: result, + } + end + def to_yaml [@uri, @parameters].to_yaml end diff --git a/Library/Homebrew/cask/spec/cask/audit_spec.rb b/Library/Homebrew/cask/spec/cask/audit_spec.rb index c12063a1d65acceb075b38222aab72f591ca21dc..193b58fd60144eb47e94020ed8aef64aa80fad95 100644 --- a/Library/Homebrew/cask/spec/cask/audit_spec.rb +++ b/Library/Homebrew/cask/spec/cask/audit_spec.rb @@ -162,7 +162,7 @@ describe Hbc::Audit do before do allow(audit).to receive(:check_appcast_http_code) - allow(fake_system_command).to receive(:run).and_return(fake_curl_result) + allow(Hbc::SystemCommand).to receive(:run).and_return(fake_curl_result) allow(fake_curl_result).to receive(:success?).and_return(success) end