From 16f4130dd81b45df697699f5bac7fa54489e8291 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sun, 22 Jan 2017 04:28:33 +0100 Subject: [PATCH 1/5] Add internal command to calculate appcast checkpoint. --- Library/Homebrew/cask/lib/hbc/audit.rb | 19 ++++---- Library/Homebrew/cask/lib/hbc/cli.rb | 1 + .../hbc/cli/internal_appcast_checkpoint.rb | 45 +++++++++++++++++++ Library/Homebrew/cask/lib/hbc/dsl/appcast.rb | 20 +++++++++ Library/Homebrew/cask/spec/cask/audit_spec.rb | 2 +- 5 files changed, 76 insertions(+), 11 deletions(-) create mode 100644 Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb diff --git a/Library/Homebrew/cask/lib/hbc/audit.rb b/Library/Homebrew/cask/lib/hbc/audit.rb index 955ecdbb00..12cefb9395 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{[^<]*}, "") - # 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 42c3982ba8..36fae30349 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 0000000000..6de76cbc77 --- /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 2f1245d3d9..94660e9366 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{[^<]*}, "") + + # 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 c12063a1d6..193b58fd60 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 From 2de6d96a10f00f6dc828711166a53b768f97bbab Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sun, 22 Jan 2017 21:56:54 +0100 Subject: [PATCH 2/5] Change regex to catch multi-line `pubDate` tags. --- Library/Homebrew/cask/lib/hbc/dsl/appcast.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb b/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb index 94660e9366..e27870622c 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb @@ -15,11 +15,7 @@ module Hbc 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{[^<]*}, "") - - # This step is necessary to replicate running `sed` from the command line - processed_appcast_text << "\n" unless processed_appcast_text.end_with?("\n") - + processed_appcast_text = result.stdout.gsub(%r{[^<]*}m, "") Digest::SHA2.hexdigest(processed_appcast_text) end From 53e232fc7e2f5f9372ba9b544e01abf99f96c99c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Galv=C3=A3o?= Date: Mon, 23 Jan 2017 01:03:19 +0000 Subject: [PATCH 3/5] Add --calculate (print current checkpoint without it) --- .../lib/hbc/cli/internal_appcast_checkpoint.rb | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb index 6de76cbc77..fc2d1049fc 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb @@ -2,13 +2,14 @@ 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? - appcask_checkpoint(cask_tokens) + appcask_checkpoint(cask_tokens, calculate) end - def self.appcask_checkpoint(cask_tokens) + def self.appcask_checkpoint(cask_tokens, calculate) count = 0 cask_tokens.each do |cask_token| @@ -17,9 +18,13 @@ module Hbc if cask.appcast.nil? opoo "Cask '#{cask}' is missing an `appcast` stanza." else - result = cask.appcast.calculate_checkpoint + if calculate + result = cask.appcast.calculate_checkpoint - checkpoint = result[: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}" @@ -34,7 +39,7 @@ module Hbc end def self.help - "calculates a given Cask's appcast checkpoint" + "prints (no flag) or calculates ('--calculate') a given Cask's appcast checkpoint" end def self.needs_init? From 2d5b659b0e4ba396f133156d368afc4fa1b8373c Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Mon, 23 Jan 2017 09:22:51 +0100 Subject: [PATCH 4/5] Add support for calculating appcast checkpoint from URLs. --- .../lib/hbc/cli/internal_appcast_checkpoint.rb | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb index fc2d1049fc..915ec314bb 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb @@ -6,7 +6,18 @@ module Hbc cask_tokens = cask_tokens_from(args) raise CaskUnspecifiedError if cask_tokens.empty? - appcask_checkpoint(cask_tokens, calculate) + 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) @@ -39,7 +50,7 @@ module Hbc end def self.help - "prints (no flag) or calculates ('--calculate') a given Cask's appcast checkpoint" + "prints (no flag) or calculates ('--calculate') a given Cask's (or URL's) appcast checkpoint" end def self.needs_init? From 2076b494a6233630025acd45d9a5766bd6bb785d Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Mon, 23 Jan 2017 16:23:01 +0100 Subject: [PATCH 5/5] Add manpage entry for _appcast_checkpoint. --- .../cask/lib/hbc/cli/internal_appcast_checkpoint.rb | 2 +- Library/Homebrew/manpages/brew-cask.1.md | 7 +++++++ manpages/brew-cask.1 | 9 +++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb index 915ec314bb..790e917b22 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb @@ -50,7 +50,7 @@ module Hbc end def self.help - "prints (no flag) or calculates ('--calculate') a given Cask's (or URL's) appcast checkpoint" + "prints or calculates a given Cask's or URL's appcast checkpoint" end def self.needs_init? diff --git a/Library/Homebrew/manpages/brew-cask.1.md b/Library/Homebrew/manpages/brew-cask.1.md index f0a70d4a76..a2c9c8c165 100644 --- a/Library/Homebrew/manpages/brew-cask.1.md +++ b/Library/Homebrew/manpages/brew-cask.1.md @@ -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] [ ... | ... ]: + 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. diff --git a/manpages/brew-cask.1 b/manpages/brew-cask.1 index 63aad2c56c..9b217fed54 100644 --- a/manpages/brew-cask.1 +++ b/manpages/brew-cask.1 @@ -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\. .