mirror of
https://github.com/Homebrew/brew.git
synced 2025-07-14 16:09:03 +08:00
Merge pull request #12121 from EricFromCanada/restore-repology
bump: add `--start-with` option to retrieve a subset of results
This commit is contained in:
commit
b77b08cf00
2
.github/workflows/tests.yml
vendored
2
.github/workflows/tests.yml
vendored
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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"
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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")
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -437,6 +437,7 @@ _brew_bump() {
|
|||||||
--limit
|
--limit
|
||||||
--no-pull-requests
|
--no-pull-requests
|
||||||
--quiet
|
--quiet
|
||||||
|
--start-with
|
||||||
--verbose
|
--verbose
|
||||||
"
|
"
|
||||||
return
|
return
|
||||||
|
@ -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)'
|
||||||
|
@ -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]' \
|
||||||
|
@ -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`*
|
||||||
|
|
||||||
|
@ -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\.
|
||||||
.
|
.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user