brew/Library/Homebrew/dev-cmd/livecheck.rb

155 lines
6.1 KiB
Ruby
Raw Normal View History

# typed: strict
# frozen_string_literal: true
2024-03-21 10:48:43 -07:00
require "abstract_command"
require "formula"
require "livecheck/livecheck"
require "livecheck/strategy"
module Homebrew
2024-03-21 10:48:43 -07:00
module DevCmd
class LivecheckCmd < AbstractCommand
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`.
2024-03-21 10:48:43 -07:00
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 <user>`/`<repo>."
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: "Enable checking multiple casks with ExtractPlist strategy."
switch "--autobump",
description: "Include packages that are autobumped by BrewTestBot. By default these are skipped."
2024-03-21 10:48:43 -07:00
conflicts "--debug", "--json"
conflicts "--tap=", "--eval-all", "--installed"
conflicts "--cask", "--formula"
conflicts "--formula", "--extract-plist"
named_args [:formula, :cask], without_api: true
end
sig { override.void }
def run
Homebrew.install_bundler_gems!(groups: ["livecheck"])
2024-03-21 10:48:43 -07:00
all = args.eval_all?
Allow configuring Homebrew with `.env` files For a long time people have requested some sort of configuration files for Homebrew. Now: here's the first version of that. Similarly to how you can configure Git for a system, a repository or a user: you can configure Homebrew for a system, a prefix or a user. The system-wide configuration file is `/etc/homebrew/brew.env`, the prefix-specific configuration file is `$HOMEBREW_PREFIX/etc/homebrew/brew.env` and the user-specific configuration file is `~/.homebrew/brew.env`. As we need to read these files from Bash in `bin/brew` (so they can) influence functionality ASAP: they are in a simple format that Bash can read. It may be that we have more complex array or hash data in future that's configured through JSON or YAML (most likely JSON as we use it more) and stored in a `brew.json`/`brew.yaml` file in the same directory. As this is relying on `eval` in Bash which is fairly dangerous: we filter the lines with a regex to ensure we're only permitting setting `HOMEBREW_*` variables and nothing more. To give a bit of power to system administrators, the `HOMEBREW_SYSTEM_ENV_TAKES_PRIORITY` variable can be set in `/etc/homebrew/brew.env` to ensure that the system-wide configuration file is loaded last and overrides any prefix or user settings. Now that we have an actual location for configuration files, let's also change the `brew livecheck` watchlist configuration file to be in this directory and deprecate the existing location. As this is a developer command and the mitigation is to just move the file: we don't need to follow the normal deprecation process here.
2023-07-28 17:17:14 +01:00
2024-03-21 10:48:43 -07:00
if args.debug? && args.verbose?
puts args
puts Homebrew::EnvConfig.livecheck_watchlist if Homebrew::EnvConfig.livecheck_watchlist.present?
Allow configuring Homebrew with `.env` files For a long time people have requested some sort of configuration files for Homebrew. Now: here's the first version of that. Similarly to how you can configure Git for a system, a repository or a user: you can configure Homebrew for a system, a prefix or a user. The system-wide configuration file is `/etc/homebrew/brew.env`, the prefix-specific configuration file is `$HOMEBREW_PREFIX/etc/homebrew/brew.env` and the user-specific configuration file is `~/.homebrew/brew.env`. As we need to read these files from Bash in `bin/brew` (so they can) influence functionality ASAP: they are in a simple format that Bash can read. It may be that we have more complex array or hash data in future that's configured through JSON or YAML (most likely JSON as we use it more) and stored in a `brew.json`/`brew.yaml` file in the same directory. As this is relying on `eval` in Bash which is fairly dangerous: we filter the lines with a regex to ensure we're only permitting setting `HOMEBREW_*` variables and nothing more. To give a bit of power to system administrators, the `HOMEBREW_SYSTEM_ENV_TAKES_PRIORITY` variable can be set in `/etc/homebrew/brew.env` to ensure that the system-wide configuration file is loaded last and overrides any prefix or user settings. Now that we have an actual location for configuration files, let's also change the `brew livecheck` watchlist configuration file to be in this directory and deprecate the existing location. As this is a developer command and the mitigation is to just move the file: we don't need to follow the normal deprecation process here.
2023-07-28 17:17:14 +01:00
end
2024-03-21 10:48:43 -07:00
formulae_and_casks_to_check = Homebrew.with_no_api_env do
if args.tap
2024-12-06 20:28:41 -08:00
tap = Tap.fetch(args.tap)
2024-03-21 10:48:43 -07:00
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?
args.named.to_formulae_and_casks_with_taps
2024-03-21 10:48:43 -07:00
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
Allow configuring Homebrew with `.env` files For a long time people have requested some sort of configuration files for Homebrew. Now: here's the first version of that. Similarly to how you can configure Git for a system, a repository or a user: you can configure Homebrew for a system, a prefix or a user. The system-wide configuration file is `/etc/homebrew/brew.env`, the prefix-specific configuration file is `$HOMEBREW_PREFIX/etc/homebrew/brew.env` and the user-specific configuration file is `~/.homebrew/brew.env`. As we need to read these files from Bash in `bin/brew` (so they can) influence functionality ASAP: they are in a simple format that Bash can read. It may be that we have more complex array or hash data in future that's configured through JSON or YAML (most likely JSON as we use it more) and stored in a `brew.json`/`brew.yaml` file in the same directory. As this is relying on `eval` in Bash which is fairly dangerous: we filter the lines with a regex to ensure we're only permitting setting `HOMEBREW_*` variables and nothing more. To give a bit of power to system administrators, the `HOMEBREW_SYSTEM_ENV_TAKES_PRIORITY` variable can be set in `/etc/homebrew/brew.env` to ensure that the system-wide configuration file is loaded last and overrides any prefix or user settings. Now that we have an actual location for configuration files, let's also change the `brew livecheck` watchlist configuration file to be in this directory and deprecate the existing location. As this is a developer command and the mitigation is to just move the file: we don't need to follow the normal deprecation process here.
2023-07-28 17:17:14 +01:00
# Skip packages that are autobumped by BrewTestBot, unless `--autobump`
# or `HOMEBREW_LIVECHECK_AUTOBUMP` are set.
if skip_autobump? && autobump_core_path.exist? && autobump_cask_path.exist?
autobump_core = File.read(autobump_core_path).lines.map(&:strip)
autobump_cask = File.read(autobump_cask_path).lines.map(&:strip)
formulae_and_casks_to_check = formulae_and_casks_to_check.reject do |formula_or_cask|
name = formula_or_cask.respond_to?(:token) ? formula_or_cask.token : formula_or_cask.name
if (autobump_core + autobump_cask).include?(name)
odebug "Skipping #{name} as it is autobumped."
true
end
end
end
2024-03-21 10:48:43 -07:00
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
2024-03-21 10:48:43 -07:00
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
2023-09-04 21:52:51 +01:00
2024-03-21 10:48:43 -07:00
private
sig { returns(String) }
2024-03-21 10:48:43 -07:00
def watchlist_path
@watchlist_path ||= T.let(File.expand_path(Homebrew::EnvConfig.livecheck_watchlist), T.nilable(String))
end
sig { returns(Pathname) }
def autobump_core_path
@autobump_core_path ||= T.let(Tap.fetch("homebrew/core").path/".github/autobump.txt", T.nilable(Pathname))
end
sig { returns(Pathname) }
def autobump_cask_path
@autobump_cask_path ||= T.let(Tap.fetch("homebrew/cask").path/".github/autobump.txt", T.nilable(Pathname))
end
sig { returns(T::Boolean) }
def skip_autobump?
!(args.autobump? || Homebrew::EnvConfig.livecheck_autobump?)
end
end
end
end