
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.
135 lines
4.6 KiB
Ruby
135 lines
4.6 KiB
Ruby
# typed: true
|
|
# frozen_string_literal: true
|
|
|
|
require "cli/parser"
|
|
require "formula"
|
|
require "livecheck/livecheck"
|
|
require "livecheck/strategy"
|
|
|
|
module Homebrew
|
|
module_function
|
|
|
|
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 <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."
|
|
|
|
conflicts "--debug", "--json"
|
|
conflicts "--tap=", "--eval-all", "--installed"
|
|
conflicts "--cask", "--formula"
|
|
|
|
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)
|
|
odeprecated "~/.brew_livecheck_watchlist", "~/.homebrew/livecheck_watchlist.txt"
|
|
watchlist = previous_default_watchlist
|
|
end
|
|
end
|
|
|
|
watchlist
|
|
end
|
|
end
|
|
|
|
def livecheck
|
|
args = livecheck_args.parse
|
|
|
|
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
|
|
casks = args.formula? ? [] : Cask::Cask.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?,
|
|
quiet: args.quiet?,
|
|
debug: args.debug?,
|
|
verbose: args.verbose?,
|
|
}.compact
|
|
|
|
Livecheck.run_checks(formulae_and_casks_to_check, **options)
|
|
end
|
|
end
|