Skip to content

Commit

Permalink
Merge pull request #1894 from reitermarkus/appcast-checkpoint
Browse files Browse the repository at this point in the history
Add internal command to calculate appcast checkpoint.
  • Loading branch information
reitermarkus committed Jan 23, 2017
2 parents 4459669 + 2076b49 commit e59ada5
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 11 deletions.
19 changes: 9 additions & 10 deletions Library/Homebrew/cask/lib/hbc/audit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -133,20 +133,19 @@ def check_appcast_http_code

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

Expand Down
1 change: 1 addition & 0 deletions Library/Homebrew/cask/lib/hbc/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

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"
Expand Down
61 changes: 61 additions & 0 deletions Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
module Hbc
class CLI
class InternalAppcastCheckpoint < InternalUseBase
def self.run(*args)
calculate = args.include? "--calculate"
cask_tokens = cask_tokens_from(args)
raise CaskUnspecifiedError if cask_tokens.empty?

if cask_tokens.all? { |t| t =~ %r{^https?://} && t !~ /\.rb$/ }
appcask_checkpoint_for_url(cask_tokens)
else
appcask_checkpoint(cask_tokens, calculate)
end
end

def self.appcask_checkpoint_for_url(urls)
urls.each do |url|
appcast = DSL::Appcast.new(url)
puts appcast.calculate_checkpoint[:checkpoint]
end
end

def self.appcask_checkpoint(cask_tokens, calculate)
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
if calculate
result = cask.appcast.calculate_checkpoint

checkpoint = result[:checkpoint]
else
checkpoint = cask.appcast.checkpoint
end

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
"prints or calculates a given Cask's or URL's appcast checkpoint"
end

def self.needs_init?
true
end
end
end
end
16 changes: 16 additions & 0 deletions Library/Homebrew/cask/lib/hbc/dsl/appcast.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
require "hbc/system_command"

module Hbc
class DSL
class Appcast
Expand All @@ -9,6 +11,20 @@ def initialize(uri, parameters = {})
@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>}m, "")
Digest::SHA2.hexdigest(processed_appcast_text)
end

{
checkpoint: checkpoint,
command_result: result,
}
end

def to_yaml
[@uri, @parameters].to_yaml
end
Expand Down
2 changes: 1 addition & 1 deletion Library/Homebrew/cask/spec/cask/audit_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@

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

Expand Down
7 changes: 7 additions & 0 deletions Library/Homebrew/manpages/brew-cask.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,13 @@ names, and other aspects of this manual are still subject to change.

**`zap` may remove files which are shared between applications.**

## INTERNAL COMMANDS

* `_appcast_checkpoint` [--calculate] [ <token> ... | <URL> ... ]:
Given a `token`, returns the current appcast checkpoint, or calculates
the appcast checkpoint if the `--calculate` flag is specified.
Given a `URL`, calculates the appcast checkpoint for it.

## OPTIONS

To make these options persistent, see the ENVIRONMENT section, below.
Expand Down
9 changes: 9 additions & 0 deletions manpages/brew-cask.1
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,15 @@ If the Cask definition contains a \fBzap\fR stanza, performs additional \fBzap\f
.
.IP "" 0
.
.SH "INTERNAL COMMANDS"
.
.TP
\fB_appcast_checkpoint\fR [\-\-calculate] [ \fItoken\fR \.\.\. | \fIURL\fR \.\.\. ]
Given a \fBtoken\fR, returns the current appcast checkpoint, or calculates the appcast checkpoint if the \fB\-\-calculate\fR flag is specified\.
.
.br
Given a \fBURL\fR, calculates the appcast checkpoint for it\.
.
.SH "OPTIONS"
To make these options persistent, see the ENVIRONMENT section, below\.
.
Expand Down

0 comments on commit e59ada5

Please sign in to comment.