2020-11-25 17:03:23 +01:00
|
|
|
# typed: true
|
2020-06-29 10:16:58 -05:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2020-06-29 09:47:19 -05:00
|
|
|
require "cli/parser"
|
2021-01-11 08:29:34 +05:30
|
|
|
require "livecheck/livecheck"
|
2020-06-29 09:47:19 -05:00
|
|
|
|
|
|
|
module Homebrew
|
2020-10-20 12:03:48 +02:00
|
|
|
extend T::Sig
|
|
|
|
|
2020-06-29 09:47:19 -05:00
|
|
|
module_function
|
|
|
|
|
2020-10-20 12:03:48 +02:00
|
|
|
sig { returns(CLI::Parser) }
|
2020-06-29 09:47:19 -05:00
|
|
|
def bump_args
|
|
|
|
Homebrew::CLI::Parser.new do
|
2021-01-15 15:04:02 -05:00
|
|
|
description <<~EOS
|
2020-07-28 09:30:19 -05:00
|
|
|
Display out-of-date brew formulae and the latest version available.
|
|
|
|
Also displays whether a pull request has been opened with the URL.
|
2020-06-29 09:47:19 -05:00
|
|
|
EOS
|
2021-03-04 01:39:37 +05:30
|
|
|
switch "--full-name",
|
|
|
|
description: "Print formulae/casks with fully-qualified names."
|
2021-02-17 00:09:02 +05:30
|
|
|
switch "--no-pull-requests",
|
|
|
|
description: "Do not retrieve pull requests from GitHub."
|
|
|
|
switch "--formula", "--formulae",
|
|
|
|
description: "Check only formulae."
|
|
|
|
switch "--cask", "--casks",
|
|
|
|
description: "Check only casks."
|
2020-11-12 10:40:41 -05:00
|
|
|
flag "--limit=",
|
|
|
|
description: "Limit number of package results returned."
|
2021-01-15 15:46:24 +05:30
|
|
|
|
2021-02-17 00:09:02 +05:30
|
|
|
conflicts "--cask", "--formula"
|
|
|
|
|
|
|
|
named_args [:formula, :cask]
|
2020-06-29 09:47:19 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def bump
|
2020-08-05 10:10:05 -05:00
|
|
|
args = bump_args.parse
|
2020-07-01 10:21:57 -05:00
|
|
|
|
2021-02-17 00:09:02 +05:30
|
|
|
if args.limit.present? && !args.formula? && !args.cask?
|
|
|
|
raise UsageError, "`--limit` must be used with either `--formula` or `--cask`."
|
|
|
|
end
|
2020-07-28 09:30:19 -05:00
|
|
|
|
2021-03-04 23:54:25 +05:30
|
|
|
formulae_and_casks = if args.formula?
|
|
|
|
args.named.to_formulae
|
|
|
|
elsif args.cask?
|
|
|
|
args.named.to_casks
|
|
|
|
else
|
|
|
|
args.named.to_formulae_and_casks
|
|
|
|
end
|
|
|
|
formulae_and_casks = formulae_and_casks&.sort_by do |formula_or_cask|
|
|
|
|
formula_or_cask.respond_to?(:token) ? formula_or_cask.token : formula_or_cask.name
|
|
|
|
end
|
2020-08-16 20:38:03 -05:00
|
|
|
|
2021-02-17 00:09:02 +05:30
|
|
|
limit = args.limit.to_i if args.limit.present?
|
|
|
|
|
2021-05-09 18:07:33 +05:30
|
|
|
if formulae_and_casks.present?
|
2021-02-17 00:09:02 +05:30
|
|
|
Livecheck.load_other_tap_strategies(formulae_and_casks)
|
|
|
|
|
2021-03-04 01:01:56 +05:30
|
|
|
ambiguous_casks = []
|
|
|
|
if !args.formula? && !args.cask?
|
2021-03-04 23:54:25 +05:30
|
|
|
ambiguous_casks = formulae_and_casks.group_by { |item| Livecheck.formula_or_cask_name(item, full_name: true) }
|
|
|
|
.values
|
|
|
|
.select { |items| items.length > 1 }
|
|
|
|
.flatten
|
|
|
|
.select { |item| item.is_a?(Cask::Cask) }
|
2021-03-04 01:01:56 +05:30
|
|
|
end
|
|
|
|
|
2021-03-04 01:39:37 +05:30
|
|
|
ambiguous_names = []
|
|
|
|
unless args.full_name?
|
2021-03-04 23:54:25 +05:30
|
|
|
ambiguous_names =
|
|
|
|
(formulae_and_casks - ambiguous_casks).group_by { |item| Livecheck.formula_or_cask_name(item) }
|
|
|
|
.values
|
|
|
|
.select { |items| items.length > 1 }
|
|
|
|
.flatten
|
2021-03-04 01:39:37 +05:30
|
|
|
end
|
|
|
|
|
2021-02-17 00:09:02 +05:30
|
|
|
formulae_and_casks.each_with_index do |formula_or_cask, i|
|
2021-01-11 08:29:34 +05:30
|
|
|
puts if i.positive?
|
2020-07-02 17:06:39 +00:00
|
|
|
|
2021-03-04 01:39:37 +05:30
|
|
|
use_full_name = args.full_name? || ambiguous_names.include?(formula_or_cask)
|
|
|
|
name = Livecheck.formula_or_cask_name(formula_or_cask, full_name: use_full_name)
|
2021-02-17 00:09:02 +05:30
|
|
|
repository = if formula_or_cask.is_a?(Formula)
|
|
|
|
if formula_or_cask.head_only?
|
|
|
|
ohai name
|
|
|
|
puts "Formula is HEAD-only."
|
|
|
|
next
|
|
|
|
end
|
|
|
|
|
2021-02-17 02:04:13 +05:30
|
|
|
Repology::HOMEBREW_CORE
|
2021-02-17 00:09:02 +05:30
|
|
|
else
|
2021-02-17 02:04:13 +05:30
|
|
|
Repology::HOMEBREW_CASK
|
2021-01-11 08:29:34 +05:30
|
|
|
end
|
2020-07-28 09:30:19 -05:00
|
|
|
|
2021-02-17 00:09:02 +05:30
|
|
|
package_data = Repology.single_package_query(name, repository: repository)
|
2021-03-04 01:01:56 +05:30
|
|
|
retrieve_and_display_info(
|
|
|
|
formula_or_cask,
|
|
|
|
name,
|
|
|
|
package_data&.values&.first,
|
|
|
|
args: args,
|
|
|
|
ambiguous_cask: ambiguous_casks.include?(formula_or_cask),
|
|
|
|
)
|
2020-08-16 20:38:03 -05:00
|
|
|
end
|
2021-01-11 08:29:34 +05:30
|
|
|
else
|
2021-02-17 00:09:02 +05:30
|
|
|
api_response = {}
|
2021-02-17 02:04:13 +05:30
|
|
|
unless args.cask?
|
|
|
|
api_response[:formulae] =
|
|
|
|
Repology.parse_api_response(limit, repository: Repology::HOMEBREW_CORE)
|
|
|
|
end
|
|
|
|
unless args.formula?
|
|
|
|
api_response[:casks] =
|
|
|
|
Repology.parse_api_response(limit, repository: Repology::HOMEBREW_CASK)
|
|
|
|
end
|
2021-02-17 00:09:02 +05:30
|
|
|
|
|
|
|
api_response.each do |package_type, outdated_packages|
|
|
|
|
repository = if package_type == :formulae
|
2021-02-17 02:04:13 +05:30
|
|
|
Repology::HOMEBREW_CORE
|
2021-02-17 00:09:02 +05:30
|
|
|
else
|
2021-02-17 02:04:13 +05:30
|
|
|
Repology::HOMEBREW_CASK
|
2021-01-11 08:29:34 +05:30
|
|
|
end
|
|
|
|
|
2021-02-17 00:09:02 +05:30
|
|
|
outdated_packages.each_with_index do |(_name, repositories), i|
|
|
|
|
homebrew_repo = repositories.find do |repo|
|
|
|
|
repo["repo"] == repository
|
|
|
|
end
|
2021-01-11 08:29:34 +05:30
|
|
|
|
2021-02-17 00:09:02 +05:30
|
|
|
next if homebrew_repo.blank?
|
|
|
|
|
|
|
|
formula_or_cask = begin
|
2021-02-17 02:04:13 +05:30
|
|
|
if repository == Repology::HOMEBREW_CORE
|
2021-02-17 00:09:02 +05:30
|
|
|
Formula[homebrew_repo["srcname"]]
|
|
|
|
else
|
|
|
|
Cask::CaskLoader.load(homebrew_repo["srcname"])
|
|
|
|
end
|
|
|
|
rescue
|
|
|
|
next
|
|
|
|
end
|
|
|
|
name = Livecheck.formula_or_cask_name(formula_or_cask)
|
2021-03-04 01:01:56 +05:30
|
|
|
ambiguous_cask = begin
|
2021-03-04 23:54:25 +05:30
|
|
|
formula_or_cask.is_a?(Cask::Cask) && !args.cask? && Formula[name]
|
2021-03-04 01:01:56 +05:30
|
|
|
rescue FormulaUnavailableError
|
|
|
|
false
|
|
|
|
end
|
2020-08-16 20:38:03 -05:00
|
|
|
|
2021-02-17 00:09:02 +05:30
|
|
|
puts if i.positive?
|
2021-03-04 01:01:56 +05:30
|
|
|
retrieve_and_display_info(formula_or_cask, name, repositories, args: args, ambiguous_cask: ambiguous_cask)
|
2021-01-11 08:29:34 +05:30
|
|
|
|
2021-02-17 00:09:02 +05:30
|
|
|
break if limit && i >= limit
|
|
|
|
end
|
2020-08-16 20:38:03 -05:00
|
|
|
end
|
2021-01-11 08:29:34 +05:30
|
|
|
end
|
|
|
|
end
|
2020-08-16 20:38:03 -05:00
|
|
|
|
2021-02-17 00:09:02 +05:30
|
|
|
def livecheck_result(formula_or_cask)
|
2021-07-19 12:55:57 -04:00
|
|
|
name = Livecheck.formula_or_cask_name(formula_or_cask)
|
|
|
|
|
|
|
|
referenced_formula_or_cask, =
|
|
|
|
Livecheck.resolve_livecheck_reference(formula_or_cask, full_name: false, debug: false)
|
|
|
|
|
|
|
|
# Check skip conditions for a referenced formula/cask
|
|
|
|
if referenced_formula_or_cask
|
|
|
|
skip_info = Livecheck::SkipConditions.referenced_skip_information(
|
|
|
|
referenced_formula_or_cask,
|
|
|
|
name,
|
|
|
|
full_name: false,
|
|
|
|
verbose: false,
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
skip_info ||= Livecheck::SkipConditions.skip_information(formula_or_cask, full_name: false, verbose: false)
|
|
|
|
if skip_info.present?
|
|
|
|
return "#{skip_info[:status]}#{" - #{skip_info[:messages].join(", ")}" if skip_info[:messages].present?}"
|
2020-08-05 10:10:05 -05:00
|
|
|
end
|
2020-08-16 19:22:24 -05:00
|
|
|
|
2021-01-11 08:29:34 +05:30
|
|
|
version_info = Livecheck.latest_version(
|
2021-02-17 00:09:02 +05:30
|
|
|
formula_or_cask,
|
2021-07-19 12:55:57 -04:00
|
|
|
referenced_formula_or_cask: referenced_formula_or_cask,
|
|
|
|
json: true, full_name: false, verbose: false, debug: false
|
2021-01-11 08:29:34 +05:30
|
|
|
)
|
|
|
|
latest = version_info[:latest] if version_info.present?
|
|
|
|
|
2021-01-24 19:07:17 +05:30
|
|
|
return "unable to get versions" if latest.blank?
|
2021-01-11 08:29:34 +05:30
|
|
|
|
|
|
|
latest.to_s
|
2021-02-17 02:36:29 +05:30
|
|
|
rescue => e
|
|
|
|
"error: #{e}"
|
2020-07-02 17:06:39 +00:00
|
|
|
end
|
|
|
|
|
2021-02-17 00:09:02 +05:30
|
|
|
def retrieve_pull_requests(formula_or_cask, name)
|
2021-03-21 12:35:45 -04:00
|
|
|
tap_remote_repo = formula_or_cask.tap&.remote_repo || formula_or_cask.tap&.full_name
|
|
|
|
pull_requests = GitHub.fetch_pull_requests(name, tap_remote_repo, state: "open")
|
2021-01-11 08:29:34 +05:30
|
|
|
if pull_requests.try(:any?)
|
|
|
|
pull_requests = pull_requests.map { |pr| "#{pr["title"]} (#{Formatter.url(pr["html_url"])})" }.join(", ")
|
|
|
|
end
|
|
|
|
|
|
|
|
return "none" if pull_requests.blank?
|
|
|
|
|
|
|
|
pull_requests
|
2020-07-06 03:32:18 +00:00
|
|
|
end
|
|
|
|
|
2021-03-04 01:01:56 +05:30
|
|
|
def retrieve_and_display_info(formula_or_cask, name, repositories, args:, ambiguous_cask: false)
|
2021-02-17 00:09:02 +05:30
|
|
|
current_version = if formula_or_cask.is_a?(Formula)
|
|
|
|
formula_or_cask.stable.version
|
|
|
|
else
|
|
|
|
Version.new(formula_or_cask.version)
|
|
|
|
end
|
2021-01-25 17:12:43 +05:30
|
|
|
|
|
|
|
repology_latest = if repositories.present?
|
|
|
|
Repology.latest_version(repositories)
|
|
|
|
else
|
|
|
|
"not found"
|
|
|
|
end
|
|
|
|
|
2021-02-17 00:09:02 +05:30
|
|
|
livecheck_latest = livecheck_result(formula_or_cask)
|
|
|
|
pull_requests = retrieve_pull_requests(formula_or_cask, name) unless args.no_pull_requests?
|
2020-07-31 10:52:37 -05:00
|
|
|
|
2021-03-04 01:01:56 +05:30
|
|
|
name += " (cask)" if ambiguous_cask
|
2021-01-24 19:07:17 +05:30
|
|
|
title = if current_version == repology_latest &&
|
|
|
|
current_version == livecheck_latest
|
2021-02-27 22:39:12 +05:30
|
|
|
"#{name} is up to date!"
|
2021-01-11 08:29:34 +05:30
|
|
|
else
|
2021-02-27 22:39:12 +05:30
|
|
|
name
|
2020-07-02 17:06:39 +00:00
|
|
|
end
|
2021-01-11 08:29:34 +05:30
|
|
|
|
|
|
|
ohai title
|
2021-01-24 21:25:12 -05:00
|
|
|
puts <<~EOS
|
|
|
|
Current formula version: #{current_version}
|
|
|
|
Latest Repology version: #{repology_latest}
|
|
|
|
Latest livecheck version: #{livecheck_latest}
|
|
|
|
EOS
|
2021-02-17 00:09:02 +05:30
|
|
|
puts "Open pull requests: #{pull_requests}" unless args.no_pull_requests?
|
2020-06-29 09:47:19 -05:00
|
|
|
end
|
|
|
|
end
|