diff --git a/Library/Homebrew/livecheck/livecheck.rb b/Library/Homebrew/livecheck/livecheck.rb index eaf32fbf7a..2a90e613ef 100644 --- a/Library/Homebrew/livecheck/livecheck.rb +++ b/Library/Homebrew/livecheck/livecheck.rb @@ -2,6 +2,7 @@ # frozen_string_literal: true require "livecheck/error" +require "livecheck/skip_conditions" require "livecheck/strategy" require "ruby-progressbar" require "uri" @@ -114,6 +115,7 @@ module Homebrew formulae_checked = formulae_and_casks_to_check.map.with_index do |formula_or_cask, i| formula = formula_or_cask if formula_or_cask.is_a?(Formula) cask = formula_or_cask if formula_or_cask.is_a?(Cask::Cask) + name = formula_or_cask_name(formula_or_cask, full_name: full_name) if debug && i.positive? puts <<~EOS @@ -123,8 +125,13 @@ module Homebrew EOS end - skip_result = skip_conditions(formula_or_cask, json: json, full_name: full_name, quiet: quiet) - next skip_result if skip_result != false + skip_info = SkipConditions.skip_information(formula_or_cask, full_name: full_name, verbose: verbose) + if skip_info.present? + next skip_info if json + + SkipConditions.print_skip_information(skip_info) unless quiet + next + end formula&.head&.downloader&.shutup! @@ -176,8 +183,8 @@ module Homebrew is_newer_than_upstream = (formula&.stable? || cask) && (current > latest) info = {} - info[:formula] = formula_name(formula, full_name: full_name) if formula - info[:cask] = cask_name(cask, full_name: full_name) if cask + info[:formula] = name if formula + info[:cask] = name if cask info[:version] = { current: current.to_s, latest: latest.to_s, @@ -209,7 +216,7 @@ module Homebrew progress&.increment status_hash(formula_or_cask, "error", [e.to_s], full_name: full_name, verbose: verbose) elsif !quiet - onoe "#{Tty.blue}#{formula_or_cask_name(formula_or_cask, full_name: full_name)}#{Tty.reset}: #{e}" + onoe "#{Tty.blue}#{name}#{Tty.reset}: #{e}" $stderr.puts e.backtrace if debug && !e.is_a?(Livecheck::Error) nil end @@ -283,109 +290,6 @@ module Homebrew status_hash end - # If a formula has to be skipped, it prints or returns a Hash contaning the reason - # for doing so; returns false otherwise. - sig do - params( - formula_or_cask: T.any(Formula, Cask::Cask), - json: T::Boolean, - full_name: T::Boolean, - quiet: T::Boolean, - verbose: T::Boolean, - ).returns(T.nilable(T.any(Hash, T::Boolean))) - end - def skip_conditions(formula_or_cask, json: false, full_name: false, quiet: false, verbose: false) - case formula_or_cask - when Formula - formula = formula_or_cask - name = formula_name(formula, full_name: full_name) - when Cask::Cask - cask = formula_or_cask - name = cask_name(cask, full_name: full_name) - end - - if formula&.deprecated? && !formula.livecheckable? - return status_hash(formula, "deprecated", full_name: full_name, verbose: verbose) if json - - puts "#{Tty.red}#{name}#{Tty.reset} : deprecated" unless quiet - return - end - - if cask&.discontinued? && !cask.livecheckable? - return status_hash(cask, "discontinued", full_name: full_name, verbose: verbose) if json - - puts "#{Tty.red}#{name}#{Tty.reset} : discontinued" unless quiet - return - end - - if formula&.disabled? && !formula.livecheckable? - return status_hash(formula, "disabled", full_name: full_name, verbose: verbose) if json - - puts "#{Tty.red}#{name}#{Tty.reset} : disabled" unless quiet - return - end - - if formula&.versioned_formula? && !formula.livecheckable? - return status_hash(formula, "versioned", full_name: full_name, verbose: verbose) if json - - puts "#{Tty.red}#{name}#{Tty.reset} : versioned" unless quiet - return - end - - if cask.present? && cask.version&.latest? && !cask.livecheckable? - return status_hash(cask, "latest", full_name: full_name, verbose: verbose) if json - - puts "#{Tty.red}#{name}#{Tty.reset} : latest" unless quiet - return - end - - if cask.present? && cask.url&.unversioned? && !cask.livecheckable? - return status_hash(cask, "unversioned", full_name: full_name, verbose: verbose) if json - - puts "#{Tty.red}#{name}#{Tty.reset} : unversioned" unless quiet - return - end - - if formula&.head_only? && !formula.any_version_installed? - head_only_msg = "HEAD only formula must be installed to be livecheckable" - return status_hash(formula, "error", [head_only_msg], full_name: full_name, verbose: verbose) if json - - puts "#{Tty.red}#{name}#{Tty.reset} : #{head_only_msg}" unless quiet - return - end - - stable_from_google_code_archive = formula&.stable&.url&.match?( - %r{https?://storage\.googleapis\.com/google-code-archive-downloads/}i, - ) - stable_from_internet_archive = formula&.stable&.url&.match?(%r{https?://web\.archive\.org/}i) - stable_is_gist = formula&.stable&.url&.match?(%r{https?://gist\.github(?:usercontent)?\.com/}i) - if formula_or_cask.livecheck.skip? || - ((stable_from_google_code_archive || - stable_from_internet_archive || - stable_is_gist) && !formula&.livecheckable?) - skip_message = if formula_or_cask.livecheck.skip_msg.is_a?(String) && - formula_or_cask.livecheck.skip_msg.present? - formula_or_cask.livecheck.skip_msg.to_s.presence - elsif stable_from_google_code_archive - "Stable URL is from Google Code Archive" - elsif stable_from_internet_archive - "Stable URL is from Internet Archive" - elsif stable_is_gist - "Stable URL is a GitHub Gist" - end - - if json - skip_messages = skip_message ? [skip_message] : nil - return status_hash(formula_or_cask, "skipped", skip_messages, full_name: full_name, verbose: verbose) - end - - puts "#{Tty.red}#{name}#{Tty.reset} : skipped#{" - #{skip_message}" if skip_message}" unless quiet - return - end - - false - end - # Formats and prints the livecheck result for a formula. sig { params(info: Hash, verbose: T::Boolean).void } def print_latest_version(info, verbose:) diff --git a/Library/Homebrew/livecheck/livecheck.rbi b/Library/Homebrew/livecheck/livecheck.rbi index d8ad3c7921..b47d360b80 100644 --- a/Library/Homebrew/livecheck/livecheck.rbi +++ b/Library/Homebrew/livecheck/livecheck.rbi @@ -3,5 +3,9 @@ module Homebrew module Livecheck include ::Kernel + + module SkipConditions + include ::Kernel + end end end diff --git a/Library/Homebrew/livecheck/skip_conditions.rb b/Library/Homebrew/livecheck/skip_conditions.rb new file mode 100644 index 0000000000..c1222e52c5 --- /dev/null +++ b/Library/Homebrew/livecheck/skip_conditions.rb @@ -0,0 +1,229 @@ +# typed: true +# frozen_string_literal: true + +require "livecheck/livecheck" + +module Homebrew + module Livecheck + # The `Livecheck::SkipConditions` module primarily contains methods that + # check for various formula/cask conditions where a check should be skipped. + # + # @api private + module SkipConditions + extend T::Sig + + module_function + + sig do + params( + formula_or_cask: T.any(Formula, Cask::Cask), + livecheckable: T::Boolean, + full_name: T::Boolean, + verbose: T::Boolean, + ).returns(Hash) + end + def formula_or_cask_skip(formula_or_cask, livecheckable, full_name: false, verbose: false) + formula = formula_or_cask if formula_or_cask.is_a?(Formula) + + if stable_url = formula&.stable&.url + stable_is_gist = stable_url.match?(%r{https?://gist\.github(?:usercontent)?\.com/}i) + stable_from_google_code_archive = stable_url.match?( + %r{https?://storage\.googleapis\.com/google-code-archive-downloads/}i, + ) + stable_from_internet_archive = stable_url.match?(%r{https?://web\.archive\.org/}i) + end + + skip_message = if formula_or_cask.livecheck.skip_msg.present? + formula_or_cask.livecheck.skip_msg + elsif !livecheckable + if stable_from_google_code_archive + "Stable URL is from Google Code Archive" + elsif stable_from_internet_archive + "Stable URL is from Internet Archive" + elsif stable_is_gist + "Stable URL is a GitHub Gist" + end + end + + return {} if !formula_or_cask.livecheck.skip? && skip_message.blank? + + skip_messages = skip_message ? [skip_message] : nil + Livecheck.status_hash(formula_or_cask, "skipped", skip_messages, full_name: full_name, verbose: verbose) + end + + sig do + params( + formula: Formula, + _livecheckable: T::Boolean, + full_name: T::Boolean, + verbose: T::Boolean, + ).returns(Hash) + end + def formula_head_only(formula, _livecheckable, full_name: false, verbose: false) + return {} if !formula.head_only? || formula.any_version_installed? + + Livecheck.status_hash( + formula, + "error", + ["HEAD only formula must be installed to be livecheckable"], + full_name: full_name, + verbose: verbose, + ) + end + + sig do + params( + formula: Formula, + livecheckable: T::Boolean, + full_name: T::Boolean, + verbose: T::Boolean, + ).returns(Hash) + end + def formula_deprecated(formula, livecheckable, full_name: false, verbose: false) + return {} if !formula.deprecated? || livecheckable + + Livecheck.status_hash(formula, "deprecated", full_name: full_name, verbose: verbose) + end + + sig do + params( + formula: Formula, + livecheckable: T::Boolean, + full_name: T::Boolean, + verbose: T::Boolean, + ).returns(Hash) + end + def formula_disabled(formula, livecheckable, full_name: false, verbose: false) + return {} if !formula.disabled? || livecheckable + + Livecheck.status_hash(formula, "disabled", full_name: full_name, verbose: verbose) + end + + sig do + params( + formula: Formula, + livecheckable: T::Boolean, + full_name: T::Boolean, + verbose: T::Boolean, + ).returns(Hash) + end + def formula_versioned(formula, livecheckable, full_name: false, verbose: false) + return {} if !formula.versioned_formula? || livecheckable + + Livecheck.status_hash(formula, "versioned", full_name: full_name, verbose: verbose) + end + + sig do + params( + cask: Cask::Cask, + livecheckable: T::Boolean, + full_name: T::Boolean, + verbose: T::Boolean, + ).returns(Hash) + end + def cask_discontinued(cask, livecheckable, full_name: false, verbose: false) + return {} if !cask.discontinued? || livecheckable + + Livecheck.status_hash(cask, "discontinued", full_name: full_name, verbose: verbose) + end + + sig do + params( + cask: Cask::Cask, + livecheckable: T::Boolean, + full_name: T::Boolean, + verbose: T::Boolean, + ).returns(Hash) + end + def cask_version_latest(cask, livecheckable, full_name: false, verbose: false) + return {} if !(cask.present? && cask.version&.latest?) || livecheckable + + Livecheck.status_hash(cask, "latest", full_name: full_name, verbose: verbose) + end + + sig do + params( + cask: Cask::Cask, + livecheckable: T::Boolean, + full_name: T::Boolean, + verbose: T::Boolean, + ).returns(Hash) + end + def cask_url_unversioned(cask, livecheckable, full_name: false, verbose: false) + return {} if !(cask.present? && cask.url&.unversioned?) || livecheckable + + Livecheck.status_hash(cask, "unversioned", full_name: full_name, verbose: verbose) + end + + # Skip conditions for formulae. + FORMULA_CHECKS = [ + :formula_or_cask_skip, + :formula_head_only, + :formula_deprecated, + :formula_disabled, + :formula_versioned, + ].freeze + + # Skip conditions for casks. + CASK_CHECKS = [ + :formula_or_cask_skip, + :cask_discontinued, + :cask_version_latest, + :cask_url_unversioned, + ].freeze + + # If a formula/cask should be skipped, we return a hash from + # `Livecheck#status_hash`, which contains a `status` type and sometimes + # error `messages`. + sig do + params( + formula_or_cask: T.any(Formula, Cask::Cask), + full_name: T::Boolean, + verbose: T::Boolean, + ).returns(Hash) + end + def skip_information(formula_or_cask, full_name: false, verbose: false) + livecheckable = formula_or_cask.livecheckable? + + checks = case formula_or_cask + when Formula + FORMULA_CHECKS + when Cask::Cask + CASK_CHECKS + end + return {} unless checks + + checks.each do |method_name| + skip_hash = send(method_name, formula_or_cask, livecheckable, full_name: full_name, verbose: verbose) + return skip_hash if skip_hash.present? + end + + {} + end + + # Prints default livecheck output in relation to skip conditions. + sig { params(skip_hash: Hash).void } + def print_skip_information(skip_hash) + return unless skip_hash.is_a?(Hash) + + name = if skip_hash[:formula].is_a?(String) + skip_hash[:formula] + elsif skip_hash[:cask].is_a?(String) + skip_hash[:cask] + end + return unless name + + if skip_hash[:messages].is_a?(Array) && skip_hash[:messages].count.positive? + # TODO: Handle multiple messages, only if needed in the future + if skip_hash[:status] == "skipped" + puts "#{Tty.red}#{name}#{Tty.reset} : skipped - #{skip_hash[:messages][0]}" + else + puts "#{Tty.red}#{name}#{Tty.reset} : #{skip_hash[:messages][0]}" + end + elsif skip_hash[:status].present? + puts "#{Tty.red}#{name}#{Tty.reset} : #{skip_hash[:status]}" + end + end + end + end +end diff --git a/Library/Homebrew/test/livecheck/livecheck_spec.rb b/Library/Homebrew/test/livecheck/livecheck_spec.rb index de46d7341d..1f37d217ce 100644 --- a/Library/Homebrew/test/livecheck/livecheck_spec.rb +++ b/Library/Homebrew/test/livecheck/livecheck_spec.rb @@ -72,220 +72,6 @@ describe Homebrew::Livecheck do end end - describe "::skip_conditions" do - context "a deprecated formula without a livecheckable" do - let(:f_deprecated) do - formula("test_deprecated") do - desc "Deprecated test formula" - homepage "https://brew.sh" - url "https://brew.sh/test-0.0.1.tgz" - deprecate! date: "2020-06-25", because: :unmaintained - end - end - - it "skips" do - expect { livecheck.skip_conditions(f_deprecated) } - .to output("test_deprecated : deprecated\n").to_stdout - .and not_to_output.to_stderr - end - end - - context "a discontinued cask without a livecheckable" do - let(:c_discontinued) do - Cask::CaskLoader.load(+<<-RUBY) - cask "test_discontinued" do - version "0.0.1" - sha256 :no_check - - url "https://brew.sh/test-0.0.1.tgz" - name "Test Discontinued" - desc "Discontinued test cask" - homepage "https://brew.sh" - - caveats do - discontinued - end - end - RUBY - end - - it "skips" do - expect { livecheck.skip_conditions(c_discontinued) } - .to output("test_discontinued : discontinued\n").to_stdout - .and not_to_output.to_stderr - end - end - - context "a disabled formula without a livecheckable" do - let(:f_disabled) do - formula("test_disabled") do - desc "Disabled test formula" - homepage "https://brew.sh" - url "https://brew.sh/test-0.0.1.tgz" - disable! date: "2020-06-25", because: :unmaintained - end - end - - it "skips" do - expect { livecheck.skip_conditions(f_disabled) } - .to output("test_disabled : disabled\n").to_stdout - .and not_to_output.to_stderr - end - end - - context "a versioned formula without a livecheckable" do - let(:f_versioned) do - formula("test@0.0.1") do - desc "Versioned test formula" - homepage "https://brew.sh" - url "https://brew.sh/test-0.0.1.tgz" - end - end - - it "skips" do - expect { livecheck.skip_conditions(f_versioned) } - .to output("test@0.0.1 : versioned\n").to_stdout - .and not_to_output.to_stderr - end - end - - context "a cask containing `version :latest` without a livecheckable" do - let(:c_latest) do - Cask::CaskLoader.load(+<<-RUBY) - cask "test_latest" do - version :latest - sha256 :no_check - - url "https://brew.sh/test-0.0.1.tgz" - name "Test Latest" - desc "Latest test cask" - homepage "https://brew.sh" - end - RUBY - end - - it "skips" do - expect { livecheck.skip_conditions(c_latest) } - .to output("test_latest : latest\n").to_stdout - .and not_to_output.to_stderr - end - end - - context "a cask containing an unversioned URL without a livecheckable" do - # `URL#unversioned?` doesn't work properly when using the - # `Cask::CaskLoader.load` setup above, so we use `Cask::Cask.new` instead. - let(:c_unversioned) do - Cask::Cask.new "test_unversioned" do - version "1.2.3" - sha256 :no_check - - url "https://brew.sh/test.tgz" - name "Test Unversioned" - desc "Unversioned test cask" - homepage "https://brew.sh" - end - end - - it "skips" do - expect { livecheck.skip_conditions(c_unversioned) } - .to output("test_unversioned : unversioned\n").to_stdout - .and not_to_output.to_stderr - end - end - - context "a HEAD-only formula that is not installed" do - let(:f_head_only) do - formula("test_head_only") do - desc "HEAD-only test formula" - homepage "https://brew.sh" - head "https://github.com/Homebrew/brew.git" - end - end - - it "skips " do - expect { livecheck.skip_conditions(f_head_only) } - .to output("test_head_only : HEAD only formula must be installed to be livecheckable\n").to_stdout - .and not_to_output.to_stderr - end - end - - context "a formula with a GitHub Gist stable URL" do - let(:f_gist) do - formula("test_gist") do - desc "Gist test formula" - homepage "https://brew.sh" - url "https://gist.github.com/Homebrew/0000000000" - end - end - - it "skips" do - expect { livecheck.skip_conditions(f_gist) } - .to output("test_gist : skipped - Stable URL is a GitHub Gist\n").to_stdout - .and not_to_output.to_stderr - end - end - - context "a formula with a Google Code Archive stable URL" do - let(:f_google_code_archive) do - formula("test_google_code_archive") do - desc "Google Code Archive test formula" - homepage "https://brew.sh" - url "https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/brew/brew-1.0.0.tar.gz" - end - end - - it "skips" do - expect { livecheck.skip_conditions(f_google_code_archive) } - .to output("test_google_code_archive : skipped - Stable URL is from Google Code Archive\n").to_stdout - .and not_to_output.to_stderr - end - end - - context "a formula with an Internet Archive stable URL" do - let(:f_internet_archive) do - formula("test_internet_archive") do - desc "Internet Archive test formula" - homepage "https://brew.sh" - url "https://web.archive.org/web/20200101000000/https://brew.sh/test-0.0.1.tgz" - end - end - - it "skips" do - expect { livecheck.skip_conditions(f_internet_archive) } - .to output("test_internet_archive : skipped - Stable URL is from Internet Archive\n").to_stdout - .and not_to_output.to_stderr - end - end - - context "a formula with a `livecheck` block containing `skip`" do - let(:f_skip) do - formula("test_skip") do - desc "Skipped test formula" - homepage "https://brew.sh" - url "https://brew.sh/test-0.0.1.tgz" - - livecheck do - skip "Not maintained" - end - end - end - - it "skips" do - expect { livecheck.skip_conditions(f_skip) } - .to output("test_skip : skipped - Not maintained\n").to_stdout - .and not_to_output.to_stderr - end - end - - it "returns false for a non-skippable formula" do - expect(livecheck.skip_conditions(f)).to eq(false) - end - - it "returns false for a non-skippable cask" do - expect(livecheck.skip_conditions(c)).to eq(false) - end - end - describe "::checkable_urls" do it "returns the list of URLs to check" do expect(livecheck.checkable_urls(f)) diff --git a/Library/Homebrew/test/livecheck/skip_conditions_spec.rb b/Library/Homebrew/test/livecheck/skip_conditions_spec.rb new file mode 100644 index 0000000000..69a911f9fb --- /dev/null +++ b/Library/Homebrew/test/livecheck/skip_conditions_spec.rb @@ -0,0 +1,484 @@ +# typed: false +# Frozen_string_literal: true + +require "livecheck/skip_conditions" + +describe Homebrew::Livecheck::SkipConditions do + subject(:skip_conditions) { described_class } + + let(:formulae) do + { + basic: formula("test") do + desc "Test formula" + homepage "https://brew.sh" + url "https://brew.sh/test-0.0.1.tgz" + head "https://github.com/Homebrew/brew.git" + + livecheck do + url "https://formulae.brew.sh/api/formula/ruby.json" + regex(/"stable":"(\d+(?:\.\d+)+)"/i) + end + end, + deprecated: formula("test_deprecated") do + desc "Deprecated test formula" + homepage "https://brew.sh" + url "https://brew.sh/test-0.0.1.tgz" + deprecate! date: "2020-06-25", because: :unmaintained + end, + disabled: formula("test_disabled") do + desc "Disabled test formula" + homepage "https://brew.sh" + url "https://brew.sh/test-0.0.1.tgz" + disable! date: "2020-06-25", because: :unmaintained + end, + versioned: formula("test@0.0.1") do + desc "Versioned test formula" + homepage "https://brew.sh" + url "https://brew.sh/test-0.0.1.tgz" + end, + head_only: formula("test_head_only") do + desc "HEAD-only test formula" + homepage "https://brew.sh" + head "https://github.com/Homebrew/brew.git" + end, + gist: formula("test_gist") do + desc "Gist test formula" + homepage "https://brew.sh" + url "https://gist.github.com/Homebrew/0000000000" + end, + google_code_archive: formula("test_google_code_archive") do + desc "Google Code Archive test formula" + homepage "https://brew.sh" + url "https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/brew/brew-1.0.0.tar.gz" + end, + internet_archive: formula("test_internet_archive") do + desc "Internet Archive test formula" + homepage "https://brew.sh" + url "https://web.archive.org/web/20200101000000/https://brew.sh/test-0.0.1.tgz" + end, + skip: formula("test_skip") do + desc "Skipped test formula" + homepage "https://brew.sh" + url "https://brew.sh/test-0.0.1.tgz" + + livecheck do + skip + end + end, + skip_with_message: formula("test_skip_with_message") do + desc "Skipped test formula" + homepage "https://brew.sh" + url "https://brew.sh/test-0.0.1.tgz" + + livecheck do + skip "Not maintained" + end + end, + } + end + + let(:casks) do + { + basic: Cask::Cask.new("test") do + version "0.0.1,2" + + url "https://brew.sh/test-0.0.1.tgz" + name "Test" + desc "Test cask" + homepage "https://brew.sh" + + livecheck do + url "https://formulae.brew.sh/api/formula/ruby.json" + regex(/"stable":"(\d+(?:\.\d+)+)"/i) + end + end, + discontinued: Cask::Cask.new("test_discontinued") do + version "0.0.1" + sha256 :no_check + + url "https://brew.sh/test-0.0.1.tgz" + name "Test Discontinued" + desc "Discontinued test cask" + homepage "https://brew.sh" + + caveats do + discontinued + end + end, + latest: Cask::Cask.new("test_latest") do + version :latest + sha256 :no_check + + url "https://brew.sh/test-0.0.1.tgz" + name "Test Latest" + desc "Latest test cask" + homepage "https://brew.sh" + end, + unversioned: Cask::Cask.new("test_unversioned") do + version "1.2.3" + sha256 :no_check + + url "https://brew.sh/test.tgz" + name "Test Unversioned" + desc "Unversioned test cask" + homepage "https://brew.sh" + end, + skip: Cask::Cask.new("test_skip") do + version "0.0.1" + + url "https://brew.sh/test-0.0.1.tgz" + name "Test Skip" + desc "Skipped test cask" + homepage "https://brew.sh" + + livecheck do + skip + end + end, + skip_with_message: Cask::Cask.new("test_skip_with_message") do + version "0.0.1" + + url "https://brew.sh/test-0.0.1.tgz" + name "Test Skip" + desc "Skipped test cask" + homepage "https://brew.sh" + + livecheck do + skip "Not maintained" + end + end, + } + end + + let(:status_hashes) do + { + formula: { + deprecated: { + formula: "test_deprecated", + status: "deprecated", + meta: { + livecheckable: false, + }, + }, + disabled: { + formula: "test_disabled", + status: "disabled", + meta: { + livecheckable: false, + }, + }, + versioned: { + formula: "test@0.0.1", + status: "versioned", + meta: { + livecheckable: false, + }, + }, + head_only: { + formula: "test_head_only", + status: "error", + messages: ["HEAD only formula must be installed to be livecheckable"], + meta: { + head_only: true, + livecheckable: false, + }, + }, + gist: { + formula: "test_gist", + status: "skipped", + messages: ["Stable URL is a GitHub Gist"], + meta: { + livecheckable: false, + }, + }, + google_code_archive: { + formula: "test_google_code_archive", + status: "skipped", + messages: ["Stable URL is from Google Code Archive"], + meta: { + livecheckable: false, + }, + }, + internet_archive: { + formula: "test_internet_archive", + status: "skipped", + messages: ["Stable URL is from Internet Archive"], + meta: { + livecheckable: false, + }, + }, + skip: { + formula: "test_skip", + status: "skipped", + meta: { + livecheckable: true, + }, + }, + skip_with_message: { + formula: "test_skip_with_message", + status: "skipped", + messages: ["Not maintained"], + meta: { + livecheckable: true, + }, + }, + }, + cask: { + discontinued: { + cask: "test_discontinued", + status: "discontinued", + meta: { + livecheckable: false, + }, + }, + latest: { + cask: "test_latest", + status: "latest", + meta: { + livecheckable: false, + }, + }, + unversioned: { + cask: "test_unversioned", + status: "unversioned", + meta: { + livecheckable: false, + }, + }, + skip: { + cask: "test_skip", + status: "skipped", + meta: { + livecheckable: true, + }, + }, + skip_with_message: { + cask: "test_skip_with_message", + status: "skipped", + messages: ["Not maintained"], + meta: { + livecheckable: true, + }, + }, + }, + } + end + + describe "::skip_conditions" do + context "a deprecated formula without a livecheckable" do + it "skips" do + expect(skip_conditions.skip_information(formulae[:deprecated])) + .to eq(status_hashes[:formula][:deprecated]) + end + end + + context "a disabled formula without a livecheckable" do + it "skips" do + expect(skip_conditions.skip_information(formulae[:disabled])) + .to eq(status_hashes[:formula][:disabled]) + end + end + + context "a versioned formula without a livecheckable" do + it "skips" do + expect(skip_conditions.skip_information(formulae[:versioned])) + .to eq(status_hashes[:formula][:versioned]) + end + end + + context "a HEAD-only formula that is not installed" do + it "skips " do + expect(skip_conditions.skip_information(formulae[:head_only])) + .to eq(status_hashes[:formula][:head_only]) + end + end + + context "a formula with a GitHub Gist stable URL" do + it "skips" do + expect(skip_conditions.skip_information(formulae[:gist])) + .to eq(status_hashes[:formula][:gist]) + end + end + + context "a formula with a Google Code Archive stable URL" do + it "skips" do + expect(skip_conditions.skip_information(formulae[:google_code_archive])) + .to eq(status_hashes[:formula][:google_code_archive]) + end + end + + context "a formula with an Internet Archive stable URL" do + it "skips" do + expect(skip_conditions.skip_information(formulae[:internet_archive])) + .to eq(status_hashes[:formula][:internet_archive]) + end + end + + context "a formula with a `livecheck` block containing `skip`" do + it "skips" do + expect(skip_conditions.skip_information(formulae[:skip])) + .to eq(status_hashes[:formula][:skip]) + + expect(skip_conditions.skip_information(formulae[:skip_with_message])) + .to eq(status_hashes[:formula][:skip_with_message]) + end + end + + context "a discontinued cask without a livecheckable" do + it "skips" do + expect(skip_conditions.skip_information(casks[:discontinued])) + .to eq(status_hashes[:cask][:discontinued]) + end + end + + context "a cask containing `version :latest` without a livecheckable" do + it "skips" do + expect(skip_conditions.skip_information(casks[:latest])) + .to eq(status_hashes[:cask][:latest]) + end + end + + context "a cask containing an unversioned URL without a livecheckable" do + it "skips" do + expect(skip_conditions.skip_information(casks[:unversioned])) + .to eq(status_hashes[:cask][:unversioned]) + end + end + + context "a cask with a `livecheck` block containing `skip`" do + it "skips" do + expect(skip_conditions.skip_information(casks[:skip])) + .to eq(status_hashes[:cask][:skip]) + + expect(skip_conditions.skip_information(casks[:skip_with_message])) + .to eq(status_hashes[:cask][:skip_with_message]) + end + end + + it "returns an empty hash for a non-skippable formula" do + expect(skip_conditions.skip_information(formulae[:basic])).to eq({}) + end + + it "returns an empty hash for a non-skippable cask" do + expect(skip_conditions.skip_information(casks[:basic])).to eq({}) + end + end + + describe "::print_skip_information" do + context "a deprecated formula without a livecheckable" do + it "prints skip information" do + expect { skip_conditions.print_skip_information(status_hashes[:formula][:deprecated]) } + .to output("test_deprecated : deprecated\n").to_stdout + .and not_to_output.to_stderr + end + end + + context "a disabled formula without a livecheckable" do + it "prints skip information" do + expect { skip_conditions.print_skip_information(status_hashes[:formula][:disabled]) } + .to output("test_disabled : disabled\n").to_stdout + .and not_to_output.to_stderr + end + end + + context "a versioned formula without a livecheckable" do + it "prints skip information" do + expect { skip_conditions.print_skip_information(status_hashes[:formula][:versioned]) } + .to output("test@0.0.1 : versioned\n").to_stdout + .and not_to_output.to_stderr + end + end + + context "a HEAD-only formula that is not installed" do + it "prints skip information" do + expect { skip_conditions.print_skip_information(status_hashes[:formula][:head_only]) } + .to output("test_head_only : HEAD only formula must be installed to be livecheckable\n").to_stdout + .and not_to_output.to_stderr + end + end + + context "a formula with a GitHub Gist stable URL" do + it "prints skip information" do + expect { skip_conditions.print_skip_information(status_hashes[:formula][:gist]) } + .to output("test_gist : skipped - Stable URL is a GitHub Gist\n").to_stdout + .and not_to_output.to_stderr + end + end + + context "a formula with a Google Code Archive stable URL" do + it "prints skip information" do + expect { skip_conditions.print_skip_information(status_hashes[:formula][:google_code_archive]) } + .to output("test_google_code_archive : skipped - Stable URL is from Google Code Archive\n").to_stdout + .and not_to_output.to_stderr + end + end + + context "a formula with an Internet Archive stable URL" do + it "prints skip information" do + expect { skip_conditions.print_skip_information(status_hashes[:formula][:internet_archive]) } + .to output("test_internet_archive : skipped - Stable URL is from Internet Archive\n").to_stdout + .and not_to_output.to_stderr + end + end + + context "a formula with a `livecheck` block containing `skip`" do + it "prints skip information" do + expect { skip_conditions.print_skip_information(status_hashes[:formula][:skip]) } + .to output("test_skip : skipped\n").to_stdout + .and not_to_output.to_stderr + + expect { skip_conditions.print_skip_information(status_hashes[:formula][:skip_with_message]) } + .to output("test_skip_with_message : skipped - Not maintained\n").to_stdout + .and not_to_output.to_stderr + end + end + + context "a discontinued cask without a livecheckable" do + it "prints skip information" do + expect { skip_conditions.print_skip_information(status_hashes[:cask][:discontinued]) } + .to output("test_discontinued : discontinued\n").to_stdout + .and not_to_output.to_stderr + end + end + + context "a cask containing `version :latest` without a livecheckable" do + it "prints skip information" do + expect { skip_conditions.print_skip_information(status_hashes[:cask][:latest]) } + .to output("test_latest : latest\n").to_stdout + .and not_to_output.to_stderr + end + end + + context "a cask containing an unversioned URL without a livecheckable" do + it "prints skip information" do + expect { skip_conditions.print_skip_information(status_hashes[:cask][:unversioned]) } + .to output("test_unversioned : unversioned\n").to_stdout + .and not_to_output.to_stderr + end + end + + context "a cask with a `livecheck` block containing `skip`" do + it "prints skip information" do + expect { skip_conditions.print_skip_information(status_hashes[:cask][:skip]) } + .to output("test_skip : skipped\n").to_stdout + .and not_to_output.to_stderr + + expect { skip_conditions.print_skip_information(status_hashes[:cask][:skip_with_message]) } + .to output("test_skip_with_message : skipped - Not maintained\n").to_stdout + .and not_to_output.to_stderr + end + end + + context "a blank parameter" do + it "prints nothing" do + expect { skip_conditions.print_skip_information({}) } + .to not_to_output.to_stdout + .and not_to_output.to_stderr + + expect { skip_conditions.print_skip_information(nil) } + .to not_to_output.to_stdout + .and not_to_output.to_stderr + end + end + end +end