From d15f99514c4ae1a7fd820a852436a3097b2404a9 Mon Sep 17 00:00:00 2001 From: Douglas Eichelberger Date: Thu, 21 Mar 2024 10:48:43 -0700 Subject: [PATCH] Port Homebrew::DevCmd::Livecheck --- Library/Homebrew/dev-cmd/livecheck.rb | 236 +++++++++--------- .../Homebrew/test/dev-cmd/livecheck_spec.rb | 3 +- 2 files changed, 122 insertions(+), 117 deletions(-) diff --git a/Library/Homebrew/dev-cmd/livecheck.rb b/Library/Homebrew/dev-cmd/livecheck.rb index 351fcb8a18..8537ed3d6f 100644 --- a/Library/Homebrew/dev-cmd/livecheck.rb +++ b/Library/Homebrew/dev-cmd/livecheck.rb @@ -1,139 +1,143 @@ # typed: true # frozen_string_literal: true +require "abstract_command" require "cli/parser" require "formula" require "livecheck/livecheck" require "livecheck/strategy" module Homebrew - module_function + module DevCmd + class LivecheckCmd < AbstractCommand + sig { returns(String) } + def self.command_name = "livecheck" - sig { returns(CLI::Parser) } - def livecheck_args - Homebrew::CLI::Parser.new do - description <<~EOS - Check for newer versions of formulae and/or casks from upstream. - If no formula or cask argument is passed, the list of formulae and - casks to check is taken from `HOMEBREW_LIVECHECK_WATCHLIST` or - `~/.homebrew/livecheck_watchlist.txt`. - EOS - switch "--full-name", - description: "Print formulae and casks with fully-qualified names." - flag "--tap=", - description: "Check formulae and casks within the given tap, specified as `/`." - switch "--eval-all", - description: "Evaluate all available formulae and casks, whether installed or not, to check them." - switch "--installed", - description: "Check formulae and casks that are currently installed." - switch "--newer-only", - description: "Show the latest version only if it's newer than the formula/cask." - switch "--json", - description: "Output information in JSON format." - switch "-r", "--resources", - description: "Also check resources for formulae." - switch "-q", "--quiet", - description: "Suppress warnings, don't print a progress bar for JSON output." - switch "--formula", "--formulae", - description: "Only check formulae." - switch "--cask", "--casks", - description: "Only check casks." - switch "--extract-plist", - description: "Include casks using the ExtractPlist livecheck strategy." + cmd_args do + description <<~EOS + Check for newer versions of formulae and/or casks from upstream. + If no formula or cask argument is passed, the list of formulae and + casks to check is taken from `HOMEBREW_LIVECHECK_WATCHLIST` or + `~/.homebrew/livecheck_watchlist.txt`. + EOS + switch "--full-name", + description: "Print formulae and casks with fully-qualified names." + flag "--tap=", + description: "Check formulae and casks within the given tap, specified as `/`." + switch "--eval-all", + description: "Evaluate all available formulae and casks, whether installed or not, to check them." + switch "--installed", + description: "Check formulae and casks that are currently installed." + switch "--newer-only", + description: "Show the latest version only if it's newer than the formula/cask." + switch "--json", + description: "Output information in JSON format." + switch "-r", "--resources", + description: "Also check resources for formulae." + switch "-q", "--quiet", + description: "Suppress warnings, don't print a progress bar for JSON output." + switch "--formula", "--formulae", + description: "Only check formulae." + switch "--cask", "--casks", + description: "Only check casks." + switch "--extract-plist", + description: "Include casks using the ExtractPlist livecheck strategy." - conflicts "--debug", "--json" - conflicts "--tap=", "--eval-all", "--installed" - conflicts "--cask", "--formula" - conflicts "--formula", "--extract-plist" + conflicts "--debug", "--json" + conflicts "--tap=", "--eval-all", "--installed" + conflicts "--cask", "--formula" + conflicts "--formula", "--extract-plist" - named_args [:formula, :cask], without_api: true - end - end - - def watchlist_path - @watchlist_path ||= begin - watchlist = File.expand_path(Homebrew::EnvConfig.livecheck_watchlist) - - unless File.exist?(watchlist) - previous_default_watchlist = File.expand_path("~/.brew_livecheck_watchlist") - if File.exist?(previous_default_watchlist) - odisabled "~/.brew_livecheck_watchlist", "~/.homebrew/livecheck_watchlist.txt" - watchlist = previous_default_watchlist - end + named_args [:formula, :cask], without_api: true end - watchlist - end - end + sig { override.void } + def run + Homebrew.install_bundler_gems!(groups: ["livecheck"]) - def livecheck - args = livecheck_args.parse + all = args.eval_all? - Homebrew.install_bundler_gems!(groups: ["livecheck"]) - - all = args.eval_all? - - if args.debug? && args.verbose? - puts args - puts Homebrew::EnvConfig.livecheck_watchlist if Homebrew::EnvConfig.livecheck_watchlist.present? - end - - formulae_and_casks_to_check = Homebrew.with_no_api_env do - if args.tap - tap = Tap.fetch(args.tap) - formulae = args.cask? ? [] : tap.formula_files.map { |path| Formulary.factory(path) } - casks = args.formula? ? [] : tap.cask_files.map { |path| Cask::CaskLoader.load(path) } - formulae + casks - elsif args.installed? - formulae = args.cask? ? [] : Formula.installed - casks = args.formula? ? [] : Cask::Caskroom.casks - formulae + casks - elsif all - formulae = args.cask? ? [] : Formula.all(eval_all: args.eval_all?) - casks = args.formula? ? [] : Cask::Cask.all(eval_all: args.eval_all?) - formulae + casks - elsif args.named.present? - if args.formula? - args.named.to_formulae - elsif args.cask? - args.named.to_casks - else - args.named.to_formulae_and_casks + if args.debug? && args.verbose? + puts args + puts Homebrew::EnvConfig.livecheck_watchlist if Homebrew::EnvConfig.livecheck_watchlist.present? end - elsif File.exist?(watchlist_path) - begin - names = Pathname.new(watchlist_path).read.lines - .reject { |line| line.start_with?("#") || line.blank? } - .map(&:strip) - named_args = CLI::NamedArgs.new(*names, parent: args) - named_args.to_formulae_and_casks(ignore_unavailable: true) - rescue Errno::ENOENT => e - onoe e + formulae_and_casks_to_check = Homebrew.with_no_api_env do + if args.tap + tap = Tap.fetch(T.must(args.tap)) + formulae = args.cask? ? [] : tap.formula_files.map { |path| Formulary.factory(path) } + casks = args.formula? ? [] : tap.cask_files.map { |path| Cask::CaskLoader.load(path) } + formulae + casks + elsif args.installed? + formulae = args.cask? ? [] : Formula.installed + casks = args.formula? ? [] : Cask::Caskroom.casks + formulae + casks + elsif all + formulae = args.cask? ? [] : Formula.all(eval_all: args.eval_all?) + casks = args.formula? ? [] : Cask::Cask.all(eval_all: args.eval_all?) + formulae + casks + elsif args.named.present? + if args.formula? + args.named.to_formulae + elsif args.cask? + args.named.to_casks + else + args.named.to_formulae_and_casks + end + elsif File.exist?(watchlist_path) + begin + names = Pathname.new(watchlist_path).read.lines + .reject { |line| line.start_with?("#") || line.blank? } + .map(&:strip) + + named_args = CLI::NamedArgs.new(*names, parent: args) + named_args.to_formulae_and_casks(ignore_unavailable: true) + rescue Errno::ENOENT => e + onoe e + end + else + raise UsageError, "A watchlist file is required when no arguments are given." + end + end + + formulae_and_casks_to_check = formulae_and_casks_to_check.sort_by do |formula_or_cask| + formula_or_cask.respond_to?(:token) ? formula_or_cask.token : formula_or_cask.name + end + + raise UsageError, "No formulae or casks to check." if formulae_and_casks_to_check.blank? + + options = { + json: args.json?, + full_name: args.full_name?, + handle_name_conflict: !args.formula? && !args.cask?, + check_resources: args.resources?, + newer_only: args.newer_only?, + extract_plist: args.extract_plist?, + quiet: args.quiet?, + debug: args.debug?, + verbose: args.verbose?, + }.compact + + Livecheck.run_checks(formulae_and_casks_to_check, **options) + end + + private + + def watchlist_path + @watchlist_path ||= begin + watchlist = File.expand_path(Homebrew::EnvConfig.livecheck_watchlist) + + unless File.exist?(watchlist) + previous_default_watchlist = File.expand_path("~/.brew_livecheck_watchlist") + if File.exist?(previous_default_watchlist) + odisabled "~/.brew_livecheck_watchlist", "~/.homebrew/livecheck_watchlist.txt" + watchlist = previous_default_watchlist + end + end + + watchlist end - else - raise UsageError, "A watchlist file is required when no arguments are given." end end - - formulae_and_casks_to_check = formulae_and_casks_to_check.sort_by do |formula_or_cask| - formula_or_cask.respond_to?(:token) ? formula_or_cask.token : formula_or_cask.name - end - - raise UsageError, "No formulae or casks to check." if formulae_and_casks_to_check.blank? - - options = { - json: args.json?, - full_name: args.full_name?, - handle_name_conflict: !args.formula? && !args.cask?, - check_resources: args.resources?, - newer_only: args.newer_only?, - extract_plist: args.extract_plist?, - quiet: args.quiet?, - debug: args.debug?, - verbose: args.verbose?, - }.compact - - Livecheck.run_checks(formulae_and_casks_to_check, **options) end end diff --git a/Library/Homebrew/test/dev-cmd/livecheck_spec.rb b/Library/Homebrew/test/dev-cmd/livecheck_spec.rb index 686eb3a8da..413e6287d2 100644 --- a/Library/Homebrew/test/dev-cmd/livecheck_spec.rb +++ b/Library/Homebrew/test/dev-cmd/livecheck_spec.rb @@ -1,8 +1,9 @@ # frozen_string_literal: true require "cmd/shared_examples/args_parse" +require "dev-cmd/livecheck" -RSpec.describe "brew livecheck" do +RSpec.describe Homebrew::DevCmd::LivecheckCmd do it_behaves_like "parseable arguments" it "reports the latest version of a Formula", :integration_test, :needs_network do