From 541b9556f80f1777ddfc5cb8ac8f5cda94f1209c Mon Sep 17 00:00:00 2001 From: EricFromCanada Date: Mon, 18 Oct 2021 23:56:41 -0400 Subject: [PATCH 1/2] tests.yml: install curl on macOS for TLS 1.3 support --- .github/workflows/tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d4abf62b05..93704bb55c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -309,6 +309,8 @@ jobs: brew sh -c "svn --homebrew=print-path" which svn which svnadmin + brew install curl + which curl - name: Create parallel test log directory run: mkdir tests From 811d0fa0bd42010f5597dca132e13ccddff146ed Mon Sep 17 00:00:00 2001 From: EricFromCanada Date: Fri, 24 Sep 2021 22:44:27 -0400 Subject: [PATCH 2/2] bump: add option to retrieve a subset of results Plus a few fixes for output. --- Library/Homebrew/cli/args.rbi | 3 ++ Library/Homebrew/dev-cmd/bump.rb | 45 ++++++++++++++------ Library/Homebrew/test/dev-cmd/bump_spec.rb | 2 +- Library/Homebrew/test/spec_helper.rb | 9 ++++ Library/Homebrew/test/utils/repology_spec.rb | 11 ++--- Library/Homebrew/utils/curl.rb | 6 +++ Library/Homebrew/utils/repology.rb | 39 ++++++++--------- completions/bash/brew | 1 + completions/fish/brew.fish | 1 + completions/zsh/_brew | 1 + docs/Manpage.md | 7 ++- manpages/brew.1 | 6 ++- 12 files changed, 85 insertions(+), 46 deletions(-) diff --git a/Library/Homebrew/cli/args.rbi b/Library/Homebrew/cli/args.rbi index a40455d226..a578179d31 100644 --- a/Library/Homebrew/cli/args.rbi +++ b/Library/Homebrew/cli/args.rbi @@ -192,6 +192,9 @@ module Homebrew sig { returns(T.nilable(String)) } def limit; end + sig { returns(T.nilable(String)) } + def start_with; end + sig { returns(T.nilable(String)) } def message; end diff --git a/Library/Homebrew/dev-cmd/bump.rb b/Library/Homebrew/dev-cmd/bump.rb index b71ce7d73b..93d11c3d7d 100644 --- a/Library/Homebrew/dev-cmd/bump.rb +++ b/Library/Homebrew/dev-cmd/bump.rb @@ -13,8 +13,9 @@ module Homebrew def bump_args Homebrew::CLI::Parser.new do description <<~EOS - 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. EOS switch "--full-name", description: "Print formulae/casks with fully-qualified names." @@ -26,6 +27,8 @@ module Homebrew description: "Check only casks." flag "--limit=", 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" @@ -53,6 +56,18 @@ module Homebrew 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? Livecheck.load_other_tap_strategies(formulae_and_casks) @@ -104,21 +119,25 @@ module Homebrew api_response = {} unless args.cask? 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 unless args.formula? 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 - api_response.each do |package_type, outdated_packages| + api_response.each_with_index do |(package_type, outdated_packages), idx| repository = if package_type == :formulae Repology::HOMEBREW_CORE else Repology::HOMEBREW_CASK end + puts if idx.positive? + oh1 package_type.capitalize if api_response.size > 1 outdated_packages.each_with_index do |(_name, repositories), i| + break if limit && i >= limit + homebrew_repo = repositories.find do |repo| repo["repo"] == repository end @@ -143,8 +162,6 @@ module Homebrew puts if i.positive? retrieve_and_display_info(formula_or_cask, name, repositories, args: args, ambiguous_cask: ambiguous_cask) - - break if limit && i >= limit end end end @@ -180,7 +197,7 @@ module Homebrew return "unable to get versions" if latest.blank? - latest.to_s + Version.new(latest) rescue => e "error: #{e}" end @@ -211,22 +228,24 @@ module Homebrew end 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 title = if current_version == repology_latest && current_version == livecheck_latest - "#{name} is up to date!" + "#{name} #{Tty.green}is up to date!#{Tty.reset}" else name end ohai title puts <<~EOS - Current formula version: #{current_version} - Latest Repology version: #{repology_latest} + Current #{formula_or_cask.is_a?(Formula) ? "formula version:" : "cask version: "} #{current_version} Latest livecheck version: #{livecheck_latest} + Latest Repology version: #{repology_latest} EOS - puts "Open pull requests: #{pull_requests}" unless args.no_pull_requests? + puts "Open pull requests: #{pull_requests}" unless pull_requests.nil? end end diff --git a/Library/Homebrew/test/dev-cmd/bump_spec.rb b/Library/Homebrew/test/dev-cmd/bump_spec.rb index d3daa15e98..3bea8640be 100644 --- a/Library/Homebrew/test/dev-cmd/bump_spec.rb +++ b/Library/Homebrew/test/dev-cmd/bump_spec.rb @@ -6,7 +6,7 @@ require "cmd/shared_examples/args_parse" describe "brew bump" do 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 install_test_formula "testball" diff --git a/Library/Homebrew/test/spec_helper.rb b/Library/Homebrew/test/spec_helper.rb index 8655b1c94a..82edc2c27c 100644 --- a/Library/Homebrew/test/spec_helper.rb +++ b/Library/Homebrew/test/spec_helper.rb @@ -169,6 +169,15 @@ RSpec.configure do |config| .append(svnadmin.dirname) 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 skip "Unzip is not installed." unless which("unzip") end diff --git a/Library/Homebrew/test/utils/repology_spec.rb b/Library/Homebrew/test/utils/repology_spec.rb index 71b5e4e837..a9830014b1 100644 --- a/Library/Homebrew/test/utils/repology_spec.rb +++ b/Library/Homebrew/test/utils/repology_spec.rb @@ -4,7 +4,7 @@ require "utils/repology" 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 response = described_class.single_package_query("invalidName", repository: "homebrew") @@ -14,15 +14,12 @@ describe Repology do it "returns a hash for existing package" do response = described_class.single_package_query("openclonk", repository: "homebrew") - expect(response).to be_nil - # TODO: uncomment (and remove line above) when we have a fix for Repology - # `curl` issues - # expect(response).not_to be_nil - # expect(response).to be_a(Hash) + expect(response).not_to be_nil + expect(response).to be_a(Hash) 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 limit = 1 response = described_class.parse_api_response(limit, repository: "homebrew") diff --git a/Library/Homebrew/utils/curl.rb b/Library/Homebrew/utils/curl.rb index 8a28e93217..2762aeb30b 100644 --- a/Library/Homebrew/utils/curl.rb +++ b/Library/Homebrew/utils/curl.rb @@ -357,6 +357,12 @@ module Utils file.unlink end + def homebrew_curl_available? + Formulary.factory("curl").present? + rescue FormulaUnavailableError + false + end + def http_status_ok?(status) (100..299).cover?(status.to_i) end diff --git a/Library/Homebrew/utils/repology.rb b/Library/Homebrew/utils/repology.rb index 9250acc4a6..215fdc6d20 100644 --- a/Library/Homebrew/utils/repology.rb +++ b/Library/Homebrew/utils/repology.rb @@ -15,33 +15,29 @@ module Repology MAX_PAGINATION = 15 private_constant :MAX_PAGINATION - def query_api(_last_package_in_response = "", repository:) - {} - # TODO: uncomment (and remove lines above) when we have a fix for Repology - # `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" + def query_api(last_package_in_response = "", repository:) + 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) - # JSON.parse(output) + output, _errors, _status = curl_output(url.to_s, use_homebrew_curl: OS.mac?) + JSON.parse(output) end 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}&" \ - # "name_type=srcname&target_page=api_v1_project&name=#{name}" + url = "https://repology.org/tools/project-by?repo=#{repository}&" \ + "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 - # data = JSON.parse(output) - # { name => data } - # rescue - # nil - # end + begin + data = JSON.parse(output) + { name => data } + rescue + nil + end end - def parse_api_response(limit = nil, repository:) + def parse_api_response(limit = nil, last_package = "", repository:) package_term = case repository when HOMEBREW_CORE "formula" @@ -55,14 +51,13 @@ module Repology page_no = 1 outdated_packages = {} - last_package = "" while page_no <= MAX_PAGINATION odebug "Paginating Repology API page: #{page_no}" response = query_api(last_package, repository: repository) outdated_packages.merge!(response) - last_package = response.keys.last + last_package = response.keys.max page_no += 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 + outdated_packages.sort.to_h end def latest_version(repositories) diff --git a/completions/bash/brew b/completions/bash/brew index a46f0eb730..eaf97ae700 100644 --- a/completions/bash/brew +++ b/completions/bash/brew @@ -436,6 +436,7 @@ _brew_bump() { --limit --no-pull-requests --quiet + --start-with --verbose " return diff --git a/completions/fish/brew.fish b/completions/fish/brew.fish index 08d4036da0..c261985779 100644 --- a/completions/fish/brew.fish +++ b/completions/fish/brew.fish @@ -388,6 +388,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 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 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; 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)' diff --git a/completions/zsh/_brew b/completions/zsh/_brew index bebf294997..b71eee4031 100644 --- a/completions/zsh/_brew +++ b/completions/zsh/_brew @@ -479,6 +479,7 @@ _brew_bump() { '--limit[Limit number of package results returned]' \ '--no-pull-requests[Do not retrieve pull requests from GitHub]' \ '--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]' \ - formula \ '(--cask)--formula[Check only formulae]' \ diff --git a/docs/Manpage.md b/docs/Manpage.md index 67067fb184..c78dc4e6c3 100644 --- a/docs/Manpage.md +++ b/docs/Manpage.md @@ -899,8 +899,9 @@ value, while `--no-rebuild` will remove it. ### `bump` [*`options`*] [*`formula`*|*`cask`* ...] -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. * `--full-name`: Print formulae/casks with fully-qualified names. @@ -912,6 +913,8 @@ Also displays whether a pull request has been opened with the URL. Check only casks. * `--limit`: 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`* diff --git a/manpages/brew.1 b/manpages/brew.1 index e6cc9e5c9a..a28552883a 100644 --- a/manpages/brew.1 +++ b/manpages/brew.1 @@ -1261,7 +1261,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\. . .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 \fB\-\-full\-name\fR @@ -1283,6 +1283,10 @@ Check only casks\. \fB\-\-limit\fR 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" Create a pull request to update \fIcask\fR with a new version\. .