Merge pull request #12121 from EricFromCanada/restore-repology

bump: add `--start-with` option to retrieve a subset of results
This commit is contained in:
Mike McQuaid 2021-10-20 09:02:48 +01:00 committed by GitHub
commit b77b08cf00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 87 additions and 46 deletions

View File

@ -309,6 +309,8 @@ jobs:
brew sh -c "svn --homebrew=print-path" brew sh -c "svn --homebrew=print-path"
which svn which svn
which svnadmin which svnadmin
brew install curl
which curl
- name: Create parallel test log directory - name: Create parallel test log directory
run: mkdir tests run: mkdir tests

View File

@ -192,6 +192,9 @@ module Homebrew
sig { returns(T.nilable(String)) } sig { returns(T.nilable(String)) }
def limit; end def limit; end
sig { returns(T.nilable(String)) }
def start_with; end
sig { returns(T.nilable(String)) } sig { returns(T.nilable(String)) }
def message; end def message; end

View File

@ -13,8 +13,9 @@ module Homebrew
def bump_args def bump_args
Homebrew::CLI::Parser.new do Homebrew::CLI::Parser.new do
description <<~EOS description <<~EOS
Display out-of-date brew formulae and the latest version available. Display out-of-date brew formulae and the latest version available. If the
Also displays whether a pull request has been opened with the URL. returned current and livecheck versions differ or when querying specific
formulae, also displays whether a pull request has been opened with the URL.
EOS EOS
switch "--full-name", switch "--full-name",
description: "Print formulae/casks with fully-qualified names." description: "Print formulae/casks with fully-qualified names."
@ -26,6 +27,8 @@ module Homebrew
description: "Check only casks." description: "Check only casks."
flag "--limit=", flag "--limit=",
description: "Limit number of package results returned." description: "Limit number of package results returned."
flag "--start-with=",
description: "Letter or word that the list of package results should alphabetically follow."
conflicts "--cask", "--formula" conflicts "--cask", "--formula"
@ -53,6 +56,18 @@ module Homebrew
limit = args.limit.to_i if args.limit.present? limit = args.limit.to_i if args.limit.present?
unless quiet_system(HOMEBREW_SHIMS_PATH/"shared/curl", "--tlsv1.3", "--head", "https://repology.org/")
begin
brewed_curl = Formula["curl"]
unless brewed_curl.any_version_installed?
ohai "Installing `curl` for Repology queries..."
safe_system HOMEBREW_BREW_FILE, "install", "--formula", brewed_curl.full_name
end
rescue FormulaUnavailableError
opoo "A `curl` with TLS 1.3 support is required for Repology queries"
end
end
if formulae_and_casks.present? if formulae_and_casks.present?
Livecheck.load_other_tap_strategies(formulae_and_casks) Livecheck.load_other_tap_strategies(formulae_and_casks)
@ -104,21 +119,25 @@ module Homebrew
api_response = {} api_response = {}
unless args.cask? unless args.cask?
api_response[:formulae] = api_response[:formulae] =
Repology.parse_api_response(limit, repository: Repology::HOMEBREW_CORE) Repology.parse_api_response(limit, args.start_with, repository: Repology::HOMEBREW_CORE)
end end
unless args.formula? unless args.formula?
api_response[:casks] = api_response[:casks] =
Repology.parse_api_response(limit, repository: Repology::HOMEBREW_CASK) Repology.parse_api_response(limit, args.start_with, repository: Repology::HOMEBREW_CASK)
end end
api_response.each do |package_type, outdated_packages| api_response.each_with_index do |(package_type, outdated_packages), idx|
repository = if package_type == :formulae repository = if package_type == :formulae
Repology::HOMEBREW_CORE Repology::HOMEBREW_CORE
else else
Repology::HOMEBREW_CASK Repology::HOMEBREW_CASK
end end
puts if idx.positive?
oh1 package_type.capitalize if api_response.size > 1
outdated_packages.each_with_index do |(_name, repositories), i| outdated_packages.each_with_index do |(_name, repositories), i|
break if limit && i >= limit
homebrew_repo = repositories.find do |repo| homebrew_repo = repositories.find do |repo|
repo["repo"] == repository repo["repo"] == repository
end end
@ -143,8 +162,6 @@ module Homebrew
puts if i.positive? puts if i.positive?
retrieve_and_display_info(formula_or_cask, name, repositories, args: args, ambiguous_cask: ambiguous_cask) retrieve_and_display_info(formula_or_cask, name, repositories, args: args, ambiguous_cask: ambiguous_cask)
break if limit && i >= limit
end end
end end
end end
@ -180,7 +197,7 @@ module Homebrew
return "unable to get versions" if latest.blank? return "unable to get versions" if latest.blank?
latest.to_s Version.new(latest)
rescue => e rescue => e
"error: #{e}" "error: #{e}"
end end
@ -211,22 +228,24 @@ module Homebrew
end end
livecheck_latest = livecheck_result(formula_or_cask) livecheck_latest = livecheck_result(formula_or_cask)
pull_requests = retrieve_pull_requests(formula_or_cask, name) unless args.no_pull_requests? pull_requests = if !args.no_pull_requests? && (args.named.present? || livecheck_latest != current_version)
retrieve_pull_requests(formula_or_cask, name)
end
name += " (cask)" if ambiguous_cask name += " (cask)" if ambiguous_cask
title = if current_version == repology_latest && title = if current_version == repology_latest &&
current_version == livecheck_latest current_version == livecheck_latest
"#{name} is up to date!" "#{name} #{Tty.green}is up to date!#{Tty.reset}"
else else
name name
end end
ohai title ohai title
puts <<~EOS puts <<~EOS
Current formula version: #{current_version} Current #{formula_or_cask.is_a?(Formula) ? "formula version:" : "cask version: "} #{current_version}
Latest Repology version: #{repology_latest}
Latest livecheck version: #{livecheck_latest} Latest livecheck version: #{livecheck_latest}
Latest Repology version: #{repology_latest}
EOS EOS
puts "Open pull requests: #{pull_requests}" unless args.no_pull_requests? puts "Open pull requests: #{pull_requests}" unless pull_requests.nil?
end end
end end

View File

@ -6,7 +6,7 @@ require "cmd/shared_examples/args_parse"
describe "brew bump" do describe "brew bump" do
it_behaves_like "parseable arguments" it_behaves_like "parseable arguments"
describe "formula", :integration_test, :needs_network do describe "formula", :integration_test, :needs_network, :needs_tls13 do
it "returns data for single valid specified formula" do it "returns data for single valid specified formula" do
install_test_formula "testball" install_test_formula "testball"

View File

@ -169,6 +169,15 @@ RSpec.configure do |config|
.append(svnadmin.dirname) .append(svnadmin.dirname)
end end
config.before(:each, :needs_tls13) do
begin
curl = Utils::Curl.curl_executable(use_homebrew_curl: OS.mac?)
rescue FormulaUnavailableError
skip "curl formula not available"
end
skip "Requires curl with TLS 1.3 support." unless quiet_system curl, "--tlsv1.3", "--head", "https://brew.sh/"
end
config.before(:each, :needs_unzip) do config.before(:each, :needs_unzip) do
skip "Unzip is not installed." unless which("unzip") skip "Unzip is not installed." unless which("unzip")
end end

View File

@ -4,7 +4,7 @@
require "utils/repology" require "utils/repology"
describe Repology do describe Repology do
describe "single_package_query", :needs_network do describe "single_package_query", :needs_network, :needs_tls13 do
it "returns nil for non-existent package" do it "returns nil for non-existent package" do
response = described_class.single_package_query("invalidName", repository: "homebrew") response = described_class.single_package_query("invalidName", repository: "homebrew")
@ -14,15 +14,12 @@ describe Repology do
it "returns a hash for existing package" do it "returns a hash for existing package" do
response = described_class.single_package_query("openclonk", repository: "homebrew") response = described_class.single_package_query("openclonk", repository: "homebrew")
expect(response).to be_nil expect(response).not_to be_nil
# TODO: uncomment (and remove line above) when we have a fix for Repology expect(response).to be_a(Hash)
# `curl` issues
# expect(response).not_to be_nil
# expect(response).to be_a(Hash)
end end
end end
describe "parse_api_response", :needs_network do describe "parse_api_response", :needs_network, :needs_tls13 do
it "returns a hash of data" do it "returns a hash of data" do
limit = 1 limit = 1
response = described_class.parse_api_response(limit, repository: "homebrew") response = described_class.parse_api_response(limit, repository: "homebrew")

View File

@ -357,6 +357,12 @@ module Utils
file.unlink file.unlink
end end
def homebrew_curl_available?
Formulary.factory("curl").present?
rescue FormulaUnavailableError
false
end
def http_status_ok?(status) def http_status_ok?(status)
(100..299).cover?(status.to_i) (100..299).cover?(status.to_i)
end end

View File

@ -15,33 +15,29 @@ module Repology
MAX_PAGINATION = 15 MAX_PAGINATION = 15
private_constant :MAX_PAGINATION private_constant :MAX_PAGINATION
def query_api(_last_package_in_response = "", repository:) def query_api(last_package_in_response = "", repository:)
{} last_package_in_response += "/" if last_package_in_response.present?
# TODO: uncomment (and remove lines above) when we have a fix for Repology url = "https://repology.org/api/v1/projects/#{last_package_in_response}?inrepo=#{repository}&outdated=1"
# `curl` issues
# last_package_in_response += "/" if last_package_in_response.present?
# url = "https://repology.org/api/v1/projects/#{last_package_in_response}?inrepo=#{repository}&outdated=1"
# output, _errors, _status = curl_output(url.to_s) output, _errors, _status = curl_output(url.to_s, use_homebrew_curl: OS.mac?)
# JSON.parse(output) JSON.parse(output)
end end
def single_package_query(name, repository:) def single_package_query(name, repository:)
# TODO: uncomment when we have a fix for Repology `curl` issues url = "https://repology.org/tools/project-by?repo=#{repository}&" \
# url = "https://repology.org/tools/project-by?repo=#{repository}&" \ "name_type=srcname&target_page=api_v1_project&name=#{name}"
# "name_type=srcname&target_page=api_v1_project&name=#{name}"
# output, _errors, _status = curl_output("--location", url.to_s) output, _errors, _status = curl_output("--location", url.to_s, use_homebrew_curl: OS.mac?)
# begin begin
# data = JSON.parse(output) data = JSON.parse(output)
# { name => data } { name => data }
# rescue rescue
# nil nil
# end end
end end
def parse_api_response(limit = nil, repository:) def parse_api_response(limit = nil, last_package = "", repository:)
package_term = case repository package_term = case repository
when HOMEBREW_CORE when HOMEBREW_CORE
"formula" "formula"
@ -55,14 +51,13 @@ module Repology
page_no = 1 page_no = 1
outdated_packages = {} outdated_packages = {}
last_package = ""
while page_no <= MAX_PAGINATION while page_no <= MAX_PAGINATION
odebug "Paginating Repology API page: #{page_no}" odebug "Paginating Repology API page: #{page_no}"
response = query_api(last_package, repository: repository) response = query_api(last_package, repository: repository)
outdated_packages.merge!(response) outdated_packages.merge!(response)
last_package = response.keys.last last_package = response.keys.max
page_no += 1 page_no += 1
break if (limit && outdated_packages.size >= limit) || response.size <= 1 break if (limit && outdated_packages.size >= limit) || response.size <= 1
@ -71,7 +66,7 @@ module Repology
puts "#{outdated_packages.size} outdated #{package_term.pluralize(outdated_packages.size)} found" puts "#{outdated_packages.size} outdated #{package_term.pluralize(outdated_packages.size)} found"
puts puts
outdated_packages outdated_packages.sort.to_h
end end
def latest_version(repositories) def latest_version(repositories)

View File

@ -437,6 +437,7 @@ _brew_bump() {
--limit --limit
--no-pull-requests --no-pull-requests
--quiet --quiet
--start-with
--verbose --verbose
" "
return return

View File

@ -389,6 +389,7 @@ __fish_brew_complete_arg 'bump' -l help -d 'Show this message'
__fish_brew_complete_arg 'bump' -l limit -d 'Limit number of package results returned' __fish_brew_complete_arg 'bump' -l limit -d 'Limit number of package results returned'
__fish_brew_complete_arg 'bump' -l no-pull-requests -d 'Do not retrieve pull requests from GitHub' __fish_brew_complete_arg 'bump' -l no-pull-requests -d 'Do not retrieve pull requests from GitHub'
__fish_brew_complete_arg 'bump' -l quiet -d 'Make some output more quiet' __fish_brew_complete_arg 'bump' -l quiet -d 'Make some output more quiet'
__fish_brew_complete_arg 'bump' -l start-with -d 'Letter or word that the list of package results should alphabetically follow'
__fish_brew_complete_arg 'bump' -l verbose -d 'Make some output more verbose' __fish_brew_complete_arg 'bump' -l verbose -d 'Make some output more verbose'
__fish_brew_complete_arg 'bump; and not __fish_seen_argument -l cask -l casks' -a '(__fish_brew_suggest_formulae_all)' __fish_brew_complete_arg 'bump; and not __fish_seen_argument -l cask -l casks' -a '(__fish_brew_suggest_formulae_all)'
__fish_brew_complete_arg 'bump; and not __fish_seen_argument -l formula -l formulae' -a '(__fish_brew_suggest_casks_all)' __fish_brew_complete_arg 'bump; and not __fish_seen_argument -l formula -l formulae' -a '(__fish_brew_suggest_casks_all)'

View File

@ -479,6 +479,7 @@ _brew_bump() {
'--limit[Limit number of package results returned]' \ '--limit[Limit number of package results returned]' \
'--no-pull-requests[Do not retrieve pull requests from GitHub]' \ '--no-pull-requests[Do not retrieve pull requests from GitHub]' \
'--quiet[Make some output more quiet]' \ '--quiet[Make some output more quiet]' \
'--start-with[Letter or word that the list of package results should alphabetically follow]' \
'--verbose[Make some output more verbose]' \ '--verbose[Make some output more verbose]' \
- formula \ - formula \
'(--cask)--formula[Check only formulae]' \ '(--cask)--formula[Check only formulae]' \

View File

@ -901,8 +901,9 @@ value, while `--no-rebuild` will remove it.
### `bump` [*`options`*] [*`formula`*|*`cask`* ...] ### `bump` [*`options`*] [*`formula`*|*`cask`* ...]
Display out-of-date brew formulae and the latest version available. Display out-of-date brew formulae and the latest version available. If the
Also displays whether a pull request has been opened with the URL. returned current and livecheck versions differ or when querying specific
formulae, also displays whether a pull request has been opened with the URL.
* `--full-name`: * `--full-name`:
Print formulae/casks with fully-qualified names. Print formulae/casks with fully-qualified names.
@ -914,6 +915,8 @@ Also displays whether a pull request has been opened with the URL.
Check only casks. Check only casks.
* `--limit`: * `--limit`:
Limit number of package results returned. Limit number of package results returned.
* `--start-with`:
Letter or word that the list of package results should alphabetically follow.
### `bump-cask-pr` [*`options`*] *`cask`* ### `bump-cask-pr` [*`options`*] *`cask`*

View File

@ -1265,7 +1265,7 @@ Use the specified \fIURL\fR as the root of the bottle\'s URL instead of Homebrew
Use the specified download strategy class for downloading the bottle\'s URL instead of Homebrew\'s default\. Use the specified download strategy class for downloading the bottle\'s URL instead of Homebrew\'s default\.
. .
.SS "\fBbump\fR [\fIoptions\fR] [\fIformula\fR|\fIcask\fR \.\.\.]" .SS "\fBbump\fR [\fIoptions\fR] [\fIformula\fR|\fIcask\fR \.\.\.]"
Display out\-of\-date brew formulae and the latest version available\. Also displays whether a pull request has been opened with the URL\. Display out\-of\-date brew formulae and the latest version available\. If the returned current and livecheck versions differ or when querying specific formulae, also displays whether a pull request has been opened with the URL\.
. .
.TP .TP
\fB\-\-full\-name\fR \fB\-\-full\-name\fR
@ -1287,6 +1287,10 @@ Check only casks\.
\fB\-\-limit\fR \fB\-\-limit\fR
Limit number of package results returned\. Limit number of package results returned\.
. .
.TP
\fB\-\-start\-with\fR
Letter or word that the list of package results should alphabetically follow\.
.
.SS "\fBbump\-cask\-pr\fR [\fIoptions\fR] \fIcask\fR" .SS "\fBbump\-cask\-pr\fR [\fIoptions\fR] \fIcask\fR"
Create a pull request to update \fIcask\fR with a new version\. Create a pull request to update \fIcask\fR with a new version\.
. .