diff --git a/.github/dependabot.yml b/.github/dependabot.yml index e28c5eb3df..a5b222935f 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,90 +1,44 @@ +# This file is synced from the `.github` repository, do not modify it directly. +--- version: 2 - updates: - - package-ecosystem: github-actions - directory: / - schedule: - interval: weekly - day: "friday" - time: "08:00" - timezone: "Etc/UTC" - allow: - - dependency-type: all - groups: - github-actions: - patterns: - - "*" +- package-ecosystem: github-actions + directory: "/" + schedule: + interval: weekly + day: friday + time: '08:00' + timezone: Etc/UTC + allow: + - dependency-type: all + groups: + github-actions: + patterns: + - "*" +- package-ecosystem: docker + directory: "/" + schedule: + interval: weekly + day: friday + time: '08:00' + timezone: Etc/UTC + allow: + - dependency-type: all + groups: + docker: + patterns: + - "*" +- package-ecosystem: devcontainers + directory: "/" + schedule: + interval: weekly + day: friday + time: '08:00' + timezone: Etc/UTC + allow: + - dependency-type: all + groups: + devcontainers: + patterns: + - "*" - - package-ecosystem: bundler - directories: - - / - - /Library/Homebrew - schedule: - interval: weekly - day: "friday" - time: "08:00" - timezone: "Etc/UTC" - allow: - - dependency-type: all - groups: - bundler: - patterns: - - "*" - - - package-ecosystem: npm - directory: / - schedule: - interval: weekly - day: "friday" - time: "08:00" - timezone: "Etc/UTC" - allow: - - dependency-type: all - groups: - npm: - patterns: - - "*" - - - package-ecosystem: docker - directory: / - schedule: - interval: weekly - day: "friday" - time: "08:00" - timezone: "Etc/UTC" - allow: - - dependency-type: all - groups: - docker: - patterns: - - "*" - - - package-ecosystem: devcontainers - directory: / - schedule: - interval: weekly - day: "friday" - time: "08:00" - timezone: "Etc/UTC" - allow: - - dependency-type: all - groups: - devcontainers: - patterns: - - "*" - - - package-ecosystem: pip - directories: - - / - - /Library/Homebrew/formula-analytics/ - schedule: - interval: weekly - day: "friday" - time: "08:00" - timezone: "Etc/UTC" - allow: - - dependency-type: all - groups: - pip: - patterns: - - "*" diff --git a/.github/workflows/actionlint.yml b/.github/workflows/actionlint.yml index d35fac7a95..3185517144 100644 --- a/.github/workflows/actionlint.yml +++ b/.github/workflows/actionlint.yml @@ -77,7 +77,7 @@ jobs: path: results.sarif - name: Upload SARIF file - uses: github/codeql-action/upload-sarif@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 + uses: github/codeql-action/upload-sarif@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19 with: sarif_file: results.sarif category: zizmor diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 939da5f9e7..a3386e59c4 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -28,7 +28,7 @@ jobs: persist-credentials: false - name: Initialize CodeQL - uses: github/codeql-action/init@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 + uses: github/codeql-action/init@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19 with: languages: ruby config: | @@ -36,4 +36,4 @@ jobs: - Library/Homebrew/vendor - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 + uses: github/codeql-action/analyze@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5742f294cb..5ee26c11ff 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -80,7 +80,7 @@ jobs: name: tap syntax needs: syntax if: github.repository_owner == 'Homebrew' - runs-on: macos-14 + runs-on: macos-15 steps: - name: Set up Homebrew id: set-up-homebrew @@ -141,7 +141,7 @@ jobs: id: set-up-homebrew uses: Homebrew/actions/setup-homebrew@master with: - core: true + core: false cask: false test-bot: false @@ -164,7 +164,7 @@ jobs: id: set-up-homebrew uses: Homebrew/actions/setup-homebrew@master with: - core: true + core: false cask: true test-bot: false @@ -213,10 +213,10 @@ jobs: strategy: matrix: include: - - name: update-test (Ubuntu) + - name: update-test (Linux) runs-on: ubuntu-latest - name: update-test (macOS) - runs-on: macos-15 + runs-on: macos-latest steps: - name: Set up Homebrew id: set-up-homebrew @@ -237,7 +237,6 @@ jobs: name: ${{ matrix.name }} needs: syntax runs-on: ${{ matrix.runs-on }} - container: ${{ matrix.container }} strategy: matrix: include: @@ -247,17 +246,10 @@ jobs: - name: tests (generic OS) test-flags: --generic --coverage runs-on: ubuntu-latest - - name: tests (Ubuntu 24.04) + - name: tests (Linux) test-flags: --coverage runs-on: ubuntu-24.04 - - name: tests (Ubuntu 22.04) - test-flags: --coverage - runs-on: ubuntu-22.04 - - name: tests (Ubuntu 20.04) - test-flags: --coverage - runs-on: ubuntu-latest - container: ghcr.io/homebrew/ubuntu20.04:latest - - name: tests (macOS 15 arm64) + - name: tests (macOS) test-flags: --coverage runs-on: macos-15 steps: @@ -349,7 +341,7 @@ jobs: disable_search: true token: ${{ secrets.CODECOV_TOKEN }} - test-default-formula: + test-bot: name: ${{ matrix.name }} needs: syntax if: github.repository_owner == 'Homebrew' && github.event_name != 'push' @@ -358,36 +350,76 @@ jobs: strategy: matrix: include: - - name: test default formula (Ubuntu 24.04) - runs-on: ubuntu-latest + - name: test-bot (Linux arm64) + runs-on: ubuntu-24.04-arm container: ghcr.io/homebrew/ubuntu24.04:latest - - name: test default formula (Ubuntu 22.04) + - name: test-bot (Linux x86_64) runs-on: ubuntu-latest container: ghcr.io/homebrew/ubuntu22.04:master - - name: test default formula (Ubuntu 20.04) + # Use Debian Old Stable for testing Homebrew's glibc support. + - name: test-bot (Linux Homebrew glibc) runs-on: ubuntu-latest - container: ghcr.io/homebrew/ubuntu20.04:latest - - name: test default formula (macOS 13 x86_64) + container: debian:oldstable + - name: test-bot (macOS x86_64) runs-on: macos-13 - - name: test default formula (macOS 15 arm64) + - name: test-bot (macOS arm64) runs-on: macos-15 env: HOMEBREW_TEST_BOT_ANALYTICS: 1 HOMEBREW_ENFORCE_SBOM: 1 steps: + - name: Install Homebrew and Homebrew's dependencies + # All other images are built from our Homebrew Dockerfile. + # This is the only one that needs to be set up manually. + if: matrix.container == 'debian:oldstable' + run: | + # Slimmed down version from the Homebrew Dockerfile + apt-get update + apt-get install -y --no-install-recommends \ + bzip2 \ + ca-certificates \ + curl \ + file \ + g++ \ + git-core \ + less \ + locales \ + make \ + netbase \ + patch \ + procps \ + sudo \ + uuid-runtime \ + tzdata + + # Install Homebrew + mkdir -p /home/linuxbrew/.linuxbrew/bin + # Don't do shallow clone or it's unshallowed by "Set up Homebrew" + git clone https://github.com/Homebrew/brew.git /home/linuxbrew/.linuxbrew/Homebrew + cd /home/linuxbrew/.linuxbrew/bin + ln -s ../Homebrew/bin/brew brew + echo "/home/linuxbrew/.linuxbrew/bin" >>"$GITHUB_PATH" + - name: Set up Homebrew id: set-up-homebrew uses: Homebrew/actions/setup-homebrew@master with: - core: true + core: false cask: false test-bot: true - run: brew test-bot --only-cleanup-before - name: Setup environment variables - if: matrix.container == 'ghcr.io/homebrew/ubuntu20.04:latest' - run: echo "HOMEBREW_GLIBC_TESTING=1" >> "$GITHUB_ENV" + run: | + # Set enviroment variables to bypass `brew doctor` failures on Tier >=2 configurations + if [[ "${MATRIX_NAME}" == "test-bot (Linux arm64)" ]]; then + echo "HOMEBREW_ARM64_TESTING=1" >> "$GITHUB_ENV" + elif [[ "${MATRIX_NAME}" == "test-bot (Linux Homebrew glibc)" ]]; then + echo "HOMEBREW_GLIBC_TESTING=1" >> "$GITHUB_ENV" + fi + env: + MATRIX_NAME: ${{ matrix.name }} - run: brew test-bot --only-setup @@ -395,7 +427,7 @@ jobs: - run: brew test-bot --only-formulae --only-json-tab --test-default-formula - test-brew-bundle-services: + bundle-and-services: name: ${{ matrix.name }} needs: syntax if: github.repository_owner == 'Homebrew' && github.event_name != 'push' @@ -403,16 +435,16 @@ jobs: strategy: matrix: include: - - name: test brew bundle and brew services (Ubuntu) + - name: bundle and services (Linux) runs-on: ubuntu-latest - - name: test brew bundle and brew services (macOS) - runs-on: macos-15 + - name: bundle and services (macOS) + runs-on: macos-latest steps: - name: Set up Homebrew id: set-up-homebrew uses: Homebrew/actions/setup-homebrew@master with: - core: true + core: false cask: false test-bot: false @@ -449,13 +481,16 @@ jobs: brew services cleanup brew bundle cleanup --force - test-analytics: - runs-on: ${{ matrix.os }} + analytics: + name: ${{ matrix.name }} + runs-on: ${{ matrix.runs-on }} strategy: matrix: - os: - - ubuntu-latest - - macos-latest + include: + - name: analytics (Linux) + runs-on: ubuntu-latest + - name: analytics (macOS) + runs-on: macos-latest needs: syntax if: github.repository_owner == 'Homebrew' && github.event_name != 'push' steps: diff --git a/Library/Homebrew/api.rb b/Library/Homebrew/api.rb index 2a4a920c21..3948bcde3d 100644 --- a/Library/Homebrew/api.rb +++ b/Library/Homebrew/api.rb @@ -122,14 +122,14 @@ module Homebrew end end - sig { params(json: Hash).returns(Hash) } - def self.merge_variations(json) + sig { params(json: Hash, bottle_tag: T.nilable(::Utils::Bottles::Tag)).returns(Hash) } + def self.merge_variations(json, bottle_tag: nil) return json unless json.key?("variations") - bottle_tag = ::Utils::Bottles::Tag.new(system: Homebrew::SimulateSystem.current_os, - arch: Homebrew::SimulateSystem.current_arch) + bottle_tag ||= Homebrew::SimulateSystem.current_tag - if (variation = json.dig("variations", bottle_tag.to_s).presence) + if (variation = json.dig("variations", bottle_tag.to_s).presence) || + (variation = json.dig("variations", bottle_tag.to_sym).presence) json = json.merge(variation) end diff --git a/Library/Homebrew/api/cask.rb b/Library/Homebrew/api/cask.rb index 03b94f848a..5de578f0ed 100644 --- a/Library/Homebrew/api/cask.rb +++ b/Library/Homebrew/api/cask.rb @@ -1,7 +1,7 @@ # typed: true # rubocop:todo Sorbet/StrictSigil # frozen_string_literal: true -require "extend/cachable" +require "cachable" require "api/download" module Homebrew @@ -12,6 +12,13 @@ module Homebrew DEFAULT_API_FILENAME = "cask.jws.json" + sig { returns(String) } + def self.api_filename + return DEFAULT_API_FILENAME unless ENV.fetch("HOMEBREW_USE_INTERNAL_API", false) + + "cask.#{SimulateSystem.current_tag}.jws.json" + end + private_class_method :cache sig { params(token: String).returns(Hash) } @@ -41,12 +48,12 @@ module Homebrew end def self.cached_json_file_path - HOMEBREW_CACHE_API/DEFAULT_API_FILENAME + HOMEBREW_CACHE_API/api_filename end sig { returns(T::Boolean) } def self.download_and_cache_data! - json_casks, updated = Homebrew::API.fetch_json_api_file DEFAULT_API_FILENAME + json_casks, updated = Homebrew::API.fetch_json_api_file api_filename cache["renames"] = {} cache["casks"] = json_casks.to_h do |json_cask| diff --git a/Library/Homebrew/api/formula.rb b/Library/Homebrew/api/formula.rb index 1bcd622da4..5ef30a0f0a 100644 --- a/Library/Homebrew/api/formula.rb +++ b/Library/Homebrew/api/formula.rb @@ -1,7 +1,7 @@ # typed: strict # frozen_string_literal: true -require "extend/cachable" +require "cachable" require "api/download" module Homebrew @@ -12,6 +12,13 @@ module Homebrew DEFAULT_API_FILENAME = "formula.jws.json" + sig { returns(String) } + def self.api_filename + return DEFAULT_API_FILENAME unless ENV.fetch("HOMEBREW_USE_INTERNAL_API", false) + + "internal/formula.#{SimulateSystem.current_tag}.jws.json" + end + private_class_method :cache sig { params(name: String).returns(T::Hash[String, T.untyped]) } @@ -42,12 +49,12 @@ module Homebrew sig { returns(Pathname) } def self.cached_json_file_path - HOMEBREW_CACHE_API/DEFAULT_API_FILENAME + HOMEBREW_CACHE_API/api_filename end sig { returns(T::Boolean) } def self.download_and_cache_data! - json_formulae, updated = Homebrew::API.fetch_json_api_file DEFAULT_API_FILENAME + json_formulae, updated = Homebrew::API.fetch_json_api_file api_filename cache["aliases"] = {} cache["renames"] = {} diff --git a/Library/Homebrew/extend/api_hashable.rb b/Library/Homebrew/api_hashable.rb similarity index 100% rename from Library/Homebrew/extend/api_hashable.rb rename to Library/Homebrew/api_hashable.rb diff --git a/Library/Homebrew/brew.sh b/Library/Homebrew/brew.sh index beaaa1a3a8..537ee55a4e 100644 --- a/Library/Homebrew/brew.sh +++ b/Library/Homebrew/brew.sh @@ -600,6 +600,11 @@ case "$1" in homebrew-version exit 0 ;; + mcp-server) + source "${HOMEBREW_LIBRARY}/Homebrew/cmd/mcp-server.sh" + homebrew-mcp-server "$@" + exit 0 + ;; esac # TODO: bump version when new macOS is released or announced and update references in: @@ -1078,6 +1083,22 @@ else export HOMEBREW_GITHUB_PACKAGES_AUTH="Bearer QQ==" fi +# Avoid picking up any random `sudo` in `PATH`. +if [[ -x /usr/bin/sudo ]] +then + SUDO=/usr/bin/sudo +else + # Do this after ensuring we're using default Bash builtins. + SUDO="$(command -v sudo 2>/dev/null)" +fi + +# Reset sudo timestamp to avoid running unauthorized sudo commands +if [[ -n "${SUDO}" ]] +then + "${SUDO}" --reset-timestamp 2>/dev/null || true +fi +unset SUDO + if [[ -n "${HOMEBREW_BASH_COMMAND}" ]] then # source rather than executing directly to ensure the entire file is read into diff --git a/Library/Homebrew/bundle.rb b/Library/Homebrew/bundle.rb index e5676f1094..43f8de77a5 100644 --- a/Library/Homebrew/bundle.rb +++ b/Library/Homebrew/bundle.rb @@ -130,6 +130,9 @@ module Homebrew @formula_versions_from_env[formula_env_name] end + sig { void } + def prepend_pkgconf_path_if_needed!; end + sig { void } def reset! @mas_installed = T.let(nil, T.nilable(T::Boolean)) diff --git a/Library/Homebrew/bundle/commands/exec.rb b/Library/Homebrew/bundle/commands/exec.rb index 103706dd76..588de100e2 100644 --- a/Library/Homebrew/bundle/commands/exec.rb +++ b/Library/Homebrew/bundle/commands/exec.rb @@ -64,14 +64,8 @@ module Homebrew ENV.prepend_path "PATH", Pathname.new(dep_root)/"shims" end - # Setup pkg-config, if present, to help locate packages - # Only need this on Linux as Homebrew provides a shim on macOS - # TODO: use extend/OS here - # rubocop:todo Homebrew/MoveToExtendOS - if OS.linux? && (pkgconf = Formulary.factory("pkgconf")) && pkgconf.any_version_installed? - ENV.prepend_path "PATH", pkgconf.opt_bin.to_s - end - # rubocop:enable Homebrew/MoveToExtendOS + # Setup pkgconf, if needed, to help locate packages + Bundle.prepend_pkgconf_path_if_needed! # For commands which aren't either absolute or relative # Add the command directory to PATH, since it may get blown away by superenv @@ -170,6 +164,18 @@ module Homebrew end end return + elsif subcommand == "sh" + preferred_path = Utils::Shell.preferred_path(default: "/bin/bash") + notice = unless Homebrew::EnvConfig.no_env_hints? + <<~EOS + Your shell has been configured to use a build environment from your `Brewfile`. + This should help you build stuff. + Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`). + When done, type `exit`. + EOS + end + ENV["HOMEBREW_FORCE_API_AUTO_UPDATE"] = nil + args = [Utils::Shell.shell_with_prompt("brew bundle", preferred_path:, notice:)] end if services diff --git a/Library/Homebrew/bundle/skipper.rb b/Library/Homebrew/bundle/skipper.rb index f2788907a2..8c49f042b3 100644 --- a/Library/Homebrew/bundle/skipper.rb +++ b/Library/Homebrew/bundle/skipper.rb @@ -11,19 +11,6 @@ module Homebrew def skip?(entry, silent: false) require "bundle/brew_dumper" - # TODO: use extend/OS here - # rubocop:todo Homebrew/MoveToExtendOS - if (Hardware::CPU.arm? || OS.linux?) && - Homebrew.default_prefix? && - entry.type == :brew && entry.name.exclude?("/") && - (formula = BrewDumper.formulae_by_full_name(entry.name)) && - formula[:official_tap] && - !formula[:bottled] - reason = Hardware::CPU.arm? ? "Apple Silicon" : "Linux" - puts Formatter.warning "Skipping #{entry.name} (no bottle for #{reason})" unless silent - return true - end - # rubocop:enable Homebrew/MoveToExtendOS return true if @failed_taps&.any? do |tap| prefix = "#{tap}/" entry.name.start_with?(prefix) || entry.options[:full_name]&.start_with?(prefix) diff --git a/Library/Homebrew/extend/cachable.rb b/Library/Homebrew/cachable.rb similarity index 100% rename from Library/Homebrew/extend/cachable.rb rename to Library/Homebrew/cachable.rb diff --git a/Library/Homebrew/cask/cask.rb b/Library/Homebrew/cask/cask.rb index 4ce56d4011..b59b876072 100644 --- a/Library/Homebrew/cask/cask.rb +++ b/Library/Homebrew/cask/cask.rb @@ -8,7 +8,7 @@ require "cask/dsl" require "cask/metadata" require "cask/tab" require "utils/bottles" -require "extend/api_hashable" +require "api_hashable" module Cask # An instance of a cask. @@ -416,16 +416,14 @@ module Cask if @dsl.on_system_blocks_exist? begin - OnSystem::ALL_OS_ARCH_COMBINATIONS.each do |os, arch| - bottle_tag = ::Utils::Bottles::Tag.new(system: os, arch:) - next unless bottle_tag.valid_combination? + OnSystem::VALID_OS_ARCH_TAGS.each do |bottle_tag| next if bottle_tag.linux? && @dsl.os.nil? next if bottle_tag.macos? && depends_on.macos && !@dsl.depends_on_set_in_block? && !depends_on.macos.allows?(bottle_tag.to_macos_version) - Homebrew::SimulateSystem.with(os:, arch:) do + Homebrew::SimulateSystem.with_tag(bottle_tag) do refresh to_h.each do |key, value| diff --git a/Library/Homebrew/cask/cask_loader.rb b/Library/Homebrew/cask/cask_loader.rb index bdf4bded72..24befa53a3 100644 --- a/Library/Homebrew/cask/cask_loader.rb +++ b/Library/Homebrew/cask/cask_loader.rb @@ -6,6 +6,7 @@ require "cask/cask" require "uri" require "utils/curl" require "extend/hash/keys" +require "api" module Cask # Loads a cask from various sources. @@ -104,8 +105,8 @@ module Cask return end - return if %w[.rb .json].exclude?(path.extname) return unless path.expand_path.exist? + return if invalid_path?(path) return if Homebrew::EnvConfig.forbid_packages_from_paths? && !path.realpath.to_s.start_with?("#{Caskroom.path}/", "#{HOMEBREW_LIBRARY}/Taps/") @@ -113,6 +114,14 @@ module Cask new(path) end + sig { params(pathname: Pathname, valid_extnames: T::Array[String]).returns(T::Boolean) } + def self.invalid_path?(pathname, valid_extnames: %w[.rb .json]) + return true if valid_extnames.exclude?(pathname.extname) + + @invalid_basenames ||= %w[INSTALL_RECEIPT.json sbom.spdx.json].freeze + @invalid_basenames.include?(pathname.basename.to_s) + end + attr_reader :token, :path sig { params(path: T.any(Pathname, String), token: String).void } @@ -135,8 +144,10 @@ module Cask @content = path.read(encoding: "UTF-8") @config = config - if path.extname == ".json" - return FromAPILoader.new(token, from_json: JSON.parse(@content), path:).load(config:) + if !self.class.invalid_path?(path, valid_extnames: %w[.json]) && + (from_json = JSON.parse(@content).presence) && + from_json.is_a?(Hash) + return FromAPILoader.new(token, from_json:, path:).load(config:) end begin @@ -284,7 +295,7 @@ module Cask sig { returns(Pathname) } attr_reader :path - sig { returns(T.nilable(Hash)) } + sig { returns(T.nilable(T::Hash[T.any(String, Symbol), T.anything])) } attr_reader :from_json sig { @@ -306,7 +317,13 @@ module Cask new("#{tap}/#{token}") end - sig { params(token: String, from_json: Hash, path: T.nilable(Pathname)).void } + sig { + params( + token: String, + from_json: T.nilable(T::Hash[T.any(String, Symbol), T.anything]), + path: T.nilable(Pathname), + ).void + } def initialize(token, from_json: T.unsafe(nil), path: nil) @token = token.sub(%r{^homebrew/(?:homebrew-)?cask/}i, "") @sourcefile_path = path || Homebrew::API::Cask.cached_json_file_path @@ -400,7 +417,7 @@ module Cask container(**container_hash) end - json_cask[:artifacts].each do |artifact| + json_cask[:artifacts]&.each do |artifact| # convert generic string replacements into actual ones artifact = cask.loader.from_h_gsubs(artifact, appdir) key = artifact.keys.first diff --git a/Library/Homebrew/cask/dsl.rb b/Library/Homebrew/cask/dsl.rb index ca35eebe39..2bd371b6e2 100644 --- a/Library/Homebrew/cask/dsl.rb +++ b/Library/Homebrew/cask/dsl.rb @@ -26,7 +26,7 @@ require "cask/dsl/version" require "cask/url" require "cask/utils" -require "extend/on_system" +require "on_system" module Cask # Class representing the domain-specific language used for casks. diff --git a/Library/Homebrew/cask/dsl/base.rb b/Library/Homebrew/cask/dsl/base.rb index 900889a59e..e9932dae84 100644 --- a/Library/Homebrew/cask/dsl/base.rb +++ b/Library/Homebrew/cask/dsl/base.rb @@ -2,7 +2,7 @@ # frozen_string_literal: true require "cask/utils" -require "extend/on_system" +require "on_system" module Cask class DSL diff --git a/Library/Homebrew/cask/installer.rb b/Library/Homebrew/cask/installer.rb index de73305989..dc9cb82f5e 100644 --- a/Library/Homebrew/cask/installer.rb +++ b/Library/Homebrew/cask/installer.rb @@ -149,7 +149,7 @@ module Cask oh1 "Installing Cask #{Formatter.identifier(@cask)}" # GitHub Actions globally disables Gatekeeper. - opoo "macOS's Gatekeeper has been disabled for this Cask" if !quarantine? && !GitHub::Actions.env_set? + opoo_outside_github_actions "macOS's Gatekeeper has been disabled for this Cask" unless quarantine? stage @cask.config = @cask.default_config.merge(old_config) diff --git a/Library/Homebrew/caveats.rb b/Library/Homebrew/caveats.rb index b843926058..c473590630 100644 --- a/Library/Homebrew/caveats.rb +++ b/Library/Homebrew/caveats.rb @@ -14,40 +14,54 @@ class Caveats sig { params(formula: Formula).void } def initialize(formula) @formula = formula + @caveats = T.let(nil, T.nilable(String)) + @completions_and_elisp = T.let(nil, T.nilable(T::Array[String])) end sig { returns(String) } def caveats - caveats = [] - build = formula.build - begin - formula.build = Tab.for_formula(formula) - string = formula.caveats.to_s - caveats << "#{string.chomp}\n" unless string.empty? - ensure - formula.build = build + @caveats ||= begin + caveats = [] + build = formula.build + begin + formula.build = Tab.for_formula(formula) + string = formula.caveats.to_s + caveats << "#{string.chomp}\n" unless string.empty? + ensure + formula.build = build + end + caveats << keg_only_text + caveats << service_caveats + caveats.compact.join("\n") end - caveats << keg_only_text - - valid_shells = [:bash, :zsh, :fish, :pwsh].freeze - current_shell = Utils::Shell.preferred || Utils::Shell.parent - shells = if current_shell.present? && - (shell_sym = current_shell.to_sym) && - valid_shells.include?(shell_sym) - [shell_sym] - else - valid_shells - end - shells.each do |shell| - caveats << function_completion_caveats(shell) - end - - caveats << service_caveats - caveats << elisp_caveats - caveats.compact.join("\n") end - delegate [:empty?, :to_s] => :caveats + sig { returns(T::Boolean) } + def empty? + caveats.blank? && completions_and_elisp.blank? + end + + delegate [:to_s] => :caveats + + sig { returns(T::Array[String]) } + def completions_and_elisp + @completions_and_elisp ||= begin + valid_shells = [:bash, :zsh, :fish, :pwsh].freeze + current_shell = Utils::Shell.preferred || Utils::Shell.parent + shells = if current_shell.present? && + (shell_sym = current_shell.to_sym) && + valid_shells.include?(shell_sym) + [shell_sym] + else + valid_shells + end + completions_and_elisp = shells.map do |shell| + function_completion_caveats(shell) + end + completions_and_elisp << elisp_caveats + completions_and_elisp.compact + end + end sig { params(skip_reason: T::Boolean).returns(T.nilable(String)) } def keg_only_text(skip_reason: false) diff --git a/Library/Homebrew/cli/parser.rb b/Library/Homebrew/cli/parser.rb index eda01f6274..9d6e4b3314 100644 --- a/Library/Homebrew/cli/parser.rb +++ b/Library/Homebrew/cli/parser.rb @@ -208,11 +208,15 @@ module Homebrew return if global_switch description = option_description(description, *names, hidden:) - process_option(*names, description, type: :switch, hidden:) unless disable - + env, counterpart = env + if env && @non_global_processed_options.any? + affix = counterpart ? " and `#{counterpart}` is passed." : "." + description += " Enabled by default if `$HOMEBREW_#{env.upcase}` is set#{affix}" + end if replacement || disable description += " (#{disable ? "disabled" : "deprecated"}#{"; replaced by #{replacement}" if replacement})" end + process_option(*names, description, type: :switch, hidden:) unless disable @parser.public_send(method, *names, *wrap_option_desc(description)) do |value| # This odeprecated should stick around indefinitely. diff --git a/Library/Homebrew/cmd/bundle.rb b/Library/Homebrew/cmd/bundle.rb index 4dfb7a60f0..b942802e5f 100755 --- a/Library/Homebrew/cmd/bundle.rb +++ b/Library/Homebrew/cmd/bundle.rb @@ -73,11 +73,10 @@ module Homebrew description: "`install` prints output from commands as they are run. " \ "`check` lists all missing dependencies." switch "--no-upgrade", - env: :bundle_no_upgrade, description: "`install` does not run `brew upgrade` on outdated dependencies. " \ "`check` does not check for outdated dependencies. " \ - "Note they may still be upgraded by `brew install` if needed. " \ - "This is enabled by default if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set." + "Note they may still be upgraded by `brew install` if needed.", + env: :bundle_no_upgrade switch "--upgrade", description: "`install` runs `brew upgrade` on outdated dependencies, " \ "even if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set." @@ -87,18 +86,15 @@ module Homebrew switch "--install", description: "Run `install` before continuing to other operations e.g. `exec`." switch "--services", - env: :bundle_services, - description: "Temporarily start services while running the `exec` or `sh` command. " \ - "This is enabled by default if `$HOMEBREW_BUNDLE_SERVICES` is set." + description: "Temporarily start services while running the `exec` or `sh` command.", + env: :bundle_services switch "-f", "--force", description: "`install` runs with `--force`/`--overwrite`. " \ "`dump` overwrites an existing `Brewfile`. " \ "`cleanup` actually performs its cleanup operations." switch "--cleanup", - env: :bundle_install_cleanup, - description: "`install` performs cleanup operation, same as running `cleanup --force`. " \ - "This is enabled by default if `$HOMEBREW_BUNDLE_INSTALL_CLEANUP` is set and " \ - "`--global` is passed." + description: "`install` performs cleanup operation, same as running `cleanup --force`.", + env: [:bundle_install_cleanup, "--global"] switch "--all", description: "`list` all dependencies." switch "--formula", "--brews", @@ -114,14 +110,12 @@ module Homebrew switch "--vscode", description: "`list`, `dump` or `cleanup` VSCode (and forks/variants) extensions." switch "--no-vscode", - env: :bundle_dump_no_vscode, - description: "`dump` without VSCode (and forks/variants) extensions. " \ - "This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_NO_VSCODE` is set." + description: "`dump` without VSCode (and forks/variants) extensions.", + env: :bundle_dump_no_vscode switch "--describe", - env: :bundle_dump_describe, description: "`dump` adds a description comment above each line, unless the " \ - "dependency does not have a description. " \ - "This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_DESCRIBE` is set." + "dependency does not have a description.", + env: :bundle_dump_describe switch "--no-restart", description: "`dump` does not add `restart_service` to formula lines." switch "--zap", @@ -282,17 +276,7 @@ module Homebrew _subcommand, *named_args = args.named named_args when "sh" - preferred_path = Utils::Shell.preferred_path(default: "/bin/bash") - notice = unless Homebrew::EnvConfig.no_env_hints? - <<~EOS - Your shell has been configured to use a build environment from your `Brewfile`. - This should help you build stuff. - Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`). - When done, type `exit`. - EOS - end - ENV["HOMEBREW_FORCE_API_AUTO_UPDATE"] = nil - [Utils::Shell.shell_with_prompt("brew bundle", preferred_path:, notice:)] + ["sh"] when "env" ["env"] end diff --git a/Library/Homebrew/cmd/deps.rb b/Library/Homebrew/cmd/deps.rb index 5aeb277dbc..06eb7c1817 100644 --- a/Library/Homebrew/cmd/deps.rb +++ b/Library/Homebrew/cmd/deps.rb @@ -18,8 +18,7 @@ module Homebrew If any version of each formula argument is installed and no other options are passed, this command displays their actual runtime dependencies (similar - to `brew linkage`), which may differ from the current versions' stated - dependencies if the installed versions are outdated. + to `brew linkage`), which may differ from a formula's declared dependencies. *Note:* `--missing` and `--skip-recommended` have precedence over `--include-*`. EOS @@ -97,21 +96,45 @@ module Homebrew Formulary.enable_factory_cache! SimulateSystem.with(os:, arch:) do - recursive = !args.direct? - installed = args.installed? || dependents(args.named.to_formulae_and_casks).all?(&:any_version_installed?) + @use_runtime_dependencies = true - @use_runtime_dependencies = installed && recursive && - !args.tree? && - !args.graph? && - !args.HEAD? && - !args.include_implicit? && - !args.include_build? && - !args.include_test? && - !args.include_optional? && - !args.skip_recommended? && - !args.missing? && - args.os.nil? && - args.arch.nil? + installed = args.installed? || dependents(args.named.to_formulae_and_casks).all?(&:any_version_installed?) + unless installed + not_using_runtime_dependencies_reason = if args.installed? + "not all the named formulae were installed" + else + "`--installed` was not passed" + end + + @use_runtime_dependencies = false + end + + %w[direct tree graph HEAD skip_recommended missing + include_implicit include_build include_test include_optional].each do |arg| + next unless args.public_send("#{arg}?") + + not_using_runtime_dependencies_reason = "--#{arg.tr("_", "-")} was passed" + + @use_runtime_dependencies = false + end + + %w[os arch].each do |arg| + next if args.public_send(arg).nil? + + not_using_runtime_dependencies_reason = "--#{arg.tr("_", "-")} was passed" + + @use_runtime_dependencies = false + end + + if !@use_runtime_dependencies && !Homebrew::EnvConfig.no_env_hints? + opoo <<~EOS + `brew deps` is not the actual runtime dependencies because #{not_using_runtime_dependencies_reason}! + This means dependencies may differ from a formula's declared dependencies. + Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`). + EOS + end + + recursive = !args.direct? if args.tree? || args.graph? dependents = if args.named.present? diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb index 3dfd07d756..644415950e 100644 --- a/Library/Homebrew/cmd/install.rb +++ b/Library/Homebrew/cmd/install.rb @@ -33,8 +33,8 @@ module Homebrew description: "If brewing fails, open an interactive debugging session with access to IRB " \ "or a shell inside the temporary build directory." switch "--display-times", - env: :display_install_times, - description: "Print install times for each package at the end of the run." + description: "Print install times for each package at the end of the run.", + env: :display_install_times switch "-f", "--force", description: "Install formulae without checking for previously installed keg-only or " \ "non-migrated versions. When installing casks, overwrite existing files " \ @@ -44,9 +44,9 @@ module Homebrew switch "-n", "--dry-run", description: "Show what would be installed, but do not actually install anything." switch "--ask", - env: :ask, description: "Ask for confirmation before downloading and installing formulae. " \ - "Print bottles and dependencies download size and install size." + "Print download and install sizes of bottles and dependencies.", + env: :ask [ [:switch, "--formula", "--formulae", { description: "Treat all named arguments as formulae.", diff --git a/Library/Homebrew/cmd/mcp-server.rb b/Library/Homebrew/cmd/mcp-server.rb new file mode 100644 index 0000000000..9a31e2a3e4 --- /dev/null +++ b/Library/Homebrew/cmd/mcp-server.rb @@ -0,0 +1,23 @@ +# typed: strong +# frozen_string_literal: true + +require "abstract_command" +require "shell_command" + +module Homebrew + module Cmd + class McpServerCmd < AbstractCommand + # This is a shell command as MCP servers need a faster startup time + # than a normal Homebrew Ruby command allows. + include ShellCommand + + cmd_args do + description <<~EOS + Starts the Homebrew MCP (Model Context Protocol) server. + EOS + switch "-d", "--debug", description: "Enable debug logging to stderr." + switch "--ping", description: "Start the server, act as if receiving a ping and then exit.", hidden: true + end + end + end +end diff --git a/Library/Homebrew/cmd/mcp-server.sh b/Library/Homebrew/cmd/mcp-server.sh new file mode 100644 index 0000000000..692eec5ed4 --- /dev/null +++ b/Library/Homebrew/cmd/mcp-server.sh @@ -0,0 +1,14 @@ +# Documentation defined in Library/Homebrew/cmd/mcp-server.rb + +# This is a shell command as MCP servers need a faster startup time +# than a normal Homebrew Ruby command allows. + +# HOMEBREW_LIBRARY is set by brew.sh +# HOMEBREW_BREW_FILE is set by extend/ENV/super.rb +# shellcheck disable=SC2154 +homebrew-mcp-server() { + source "${HOMEBREW_LIBRARY}/Homebrew/utils/ruby.sh" + setup-ruby-path + export HOMEBREW_VERSION + "${HOMEBREW_RUBY_PATH}" "-r${HOMEBREW_LIBRARY}/Homebrew/mcp_server.rb" -e "Homebrew::McpServer.new.run" "$@" +} diff --git a/Library/Homebrew/cmd/outdated.rb b/Library/Homebrew/cmd/outdated.rb index 3acc2fcf84..6b4d81f179 100644 --- a/Library/Homebrew/cmd/outdated.rb +++ b/Library/Homebrew/cmd/outdated.rb @@ -32,12 +32,10 @@ module Homebrew "formula is outdated. Otherwise, the repository's HEAD will only be checked for " \ "updates when a new stable or development version has been released." switch "-g", "--greedy", - env: :upgrade_greedy, - description: "Also include outdated casks with `auto_updates true` or `version :latest`." - + description: "Also include outdated casks with `auto_updates true` or `version :latest`.", + env: :upgrade_greedy switch "--greedy-latest", description: "Also include outdated casks including those with `version :latest`." - switch "--greedy-auto-updates", description: "Also include outdated casks including those with `auto_updates true`." diff --git a/Library/Homebrew/cmd/reinstall.rb b/Library/Homebrew/cmd/reinstall.rb index 4c6d2d27c6..01e44115f8 100644 --- a/Library/Homebrew/cmd/reinstall.rb +++ b/Library/Homebrew/cmd/reinstall.rb @@ -32,8 +32,8 @@ module Homebrew description: "If brewing fails, open an interactive debugging session with access to IRB " \ "or a shell inside the temporary build directory." switch "--display-times", - env: :display_install_times, - description: "Print install times for each package at the end of the run." + description: "Print install times for each package at the end of the run.", + env: :display_install_times switch "-f", "--force", description: "Install without checking for previously installed keg-only or " \ "non-migrated versions." @@ -41,7 +41,7 @@ module Homebrew description: "Print the verification and post-install steps." switch "--ask", description: "Ask for confirmation before downloading and upgrading formulae. " \ - "Print bottles and dependencies download size, install and net install size.", + "Print download, install and net install sizes of bottles and dependencies.", env: :ask [ [:switch, "--formula", "--formulae", { description: "Treat all named arguments as formulae." }], diff --git a/Library/Homebrew/cmd/shellenv.rb b/Library/Homebrew/cmd/shellenv.rb index 03c530f502..6e5c959046 100644 --- a/Library/Homebrew/cmd/shellenv.rb +++ b/Library/Homebrew/cmd/shellenv.rb @@ -13,18 +13,20 @@ module Homebrew description <<~EOS Valid shells: bash|csh|fish|pwsh|sh|tcsh|zsh - Print export statements. When run in a shell, this installation of Homebrew will be added to your `PATH`, `MANPATH`, and `INFOPATH`. + Print export statements. When run in a shell, this installation of Homebrew will be added to your + `$PATH`, `$MANPATH`, and `$INFOPATH`. The variables `$HOMEBREW_PREFIX`, `$HOMEBREW_CELLAR` and `$HOMEBREW_REPOSITORY` are also exported to avoid querying them multiple times. To help guarantee idempotence, this command produces no output when Homebrew's `bin` and `sbin` directories - are first and second respectively in your `PATH`. Consider adding evaluation of this command's output to + are first and second respectively in your `$PATH`. Consider adding evaluation of this command's output to your dotfiles (e.g. `~/.bash_profile` or ~/.zprofile` on macOS and ~/.bashrc` or ~/.zshrc` on Linux) with: `eval "$(brew shellenv)"` The shell can be specified explicitly with a supported shell name parameter. Unknown shells will output POSIX exports. EOS + named_args :shell end end diff --git a/Library/Homebrew/cmd/update.sh b/Library/Homebrew/cmd/update.sh index efb3796146..81439dbe21 100644 --- a/Library/Homebrew/cmd/update.sh +++ b/Library/Homebrew/cmd/update.sh @@ -725,31 +725,53 @@ EOS local tmp_failure_file="${DIR}/.git/TMP_FETCH_FAILURES" rm -f "${tmp_failure_file}" - if [[ -n "${HOMEBREW_UPDATE_AUTO}" ]] + if ! git fetch --tags --force "${QUIET_ARGS[@]}" origin \ + "refs/heads/${UPSTREAM_BRANCH_DIR}:refs/remotes/origin/${UPSTREAM_BRANCH_DIR}" 2>>"${tmp_failure_file}" then - git fetch --tags --force "${QUIET_ARGS[@]}" origin \ - "refs/heads/${UPSTREAM_BRANCH_DIR}:refs/remotes/origin/${UPSTREAM_BRANCH_DIR}" 2>/dev/null - else - # Capture stderr to tmp_failure_file - if ! git fetch --tags --force "${QUIET_ARGS[@]}" origin \ - "refs/heads/${UPSTREAM_BRANCH_DIR}:refs/remotes/origin/${UPSTREAM_BRANCH_DIR}" 2>>"${tmp_failure_file}" + if [[ -f "${tmp_failure_file}" ]] then - # Reprint fetch errors to stderr - [[ -f "${tmp_failure_file}" ]] && cat "${tmp_failure_file}" 1>&2 - - if [[ "${UPSTREAM_SHA_HTTP_CODE}" == "404" ]] + local git_errors + git_errors="$(cat "${tmp_failure_file}")" + if [[ "${git_errors}" == "fatal: couldn't find remote ref refs/heads/master" ]] then - TAP="${DIR#"${HOMEBREW_LIBRARY}"/Taps/}" - echo "${TAP} does not exist! Run \`brew untap ${TAP}\` to remove it." >>"${update_failed_file}" - else - echo "Fetching ${DIR} failed!" >>"${update_failed_file}" - - if [[ -f "${tmp_failure_file}" ]] && - [[ "$(cat "${tmp_failure_file}")" == "fatal: couldn't find remote ref refs/heads/${UPSTREAM_BRANCH_DIR}" ]] + # Attempt migration from master to main branch. + if git fetch --tags --force "${QUIET_ARGS[@]}" origin \ + "refs/heads/main:refs/remotes/origin/main" 2>>"${tmp_failure_file}" then - echo "${DIR}" >>"${missing_remote_ref_dirs_file}" + rm -f "${DIR}/.git/refs/remotes/origin/HEAD" "${DIR}/.git/refs/remotes/origin/master" + UPSTREAM_BRANCH_DIR="$(upstream_branch)" + declare UPSTREAM_BRANCH"${TAP_VAR}"="${UPSTREAM_BRANCH_DIR}" + git branch -m master main "${QUIET_ARGS[@]}" + git branch -u origin/main main "${QUIET_ARGS[@]}" + rm -f "${tmp_failure_file}" + exit fi fi + + rm -f "${tmp_failure_file}" + fi + + # Don't output errors if HOMEBREW_UPDATE_AUTO is set. + if [[ -n "${HOMEBREW_UPDATE_AUTO}" ]] + then + exit + fi + + # Reprint fetch errors to stderr + [[ -n "${git_errors}" ]] && echo "${git_errors}" 1>&2 + + if [[ "${UPSTREAM_SHA_HTTP_CODE}" == "404" ]] + then + TAP="${DIR#"${HOMEBREW_LIBRARY}"/Taps/}" + echo "${TAP} does not exist! Run \`brew untap ${TAP}\` to remove it." >>"${update_failed_file}" + else + echo "Fetching ${DIR} failed!" >>"${update_failed_file}" + + if [[ -f "${tmp_failure_file}" ]] && + [[ "$(cat "${tmp_failure_file}")" == "fatal: couldn't find remote ref refs/heads/${UPSTREAM_BRANCH_DIR}" ]] + then + echo "${DIR}" >>"${missing_remote_ref_dirs_file}" + fi fi fi diff --git a/Library/Homebrew/cmd/upgrade.rb b/Library/Homebrew/cmd/upgrade.rb index 80f987e905..52fe6e4f76 100644 --- a/Library/Homebrew/cmd/upgrade.rb +++ b/Library/Homebrew/cmd/upgrade.rb @@ -29,8 +29,8 @@ module Homebrew description: "If brewing fails, open an interactive debugging session with access to IRB " \ "or a shell inside the temporary build directory." switch "--display-times", - env: :display_install_times, - description: "Print install times for each package at the end of the run." + description: "Print install times for each package at the end of the run.", + env: :display_install_times switch "-f", "--force", description: "Install formulae without checking for previously installed keg-only or " \ "non-migrated versions. When installing casks, overwrite existing files " \ @@ -41,7 +41,7 @@ module Homebrew description: "Show what would be upgraded, but do not actually upgrade anything." switch "--ask", description: "Ask for confirmation before downloading and upgrading formulae. " \ - "Print bottles and dependencies download size, install and net install size.", + "Print download, install and net install sizes of bottles and dependencies.", env: :ask [ [:switch, "--formula", "--formulae", { diff --git a/Library/Homebrew/cmd/vendor-install.sh b/Library/Homebrew/cmd/vendor-install.sh index 8825d9fccd..3d58dab372 100644 --- a/Library/Homebrew/cmd/vendor-install.sh +++ b/Library/Homebrew/cmd/vendor-install.sh @@ -101,6 +101,7 @@ fetch() { local first_try=1 local vendor_locations local temporary_path + local curl_exit_code=0 curl_args=() @@ -149,19 +150,27 @@ fetch() { # HOMEBREW_CURL is set by brew.sh (and isn't misspelt here) # shellcheck disable=SC2153 "${HOMEBREW_CURL}" "${curl_args[@]}" -C - "${url}" -o "${temporary_path}" - if [[ $? -eq 33 ]] + curl_exit_code="$?" + if [[ "${curl_exit_code}" -eq 33 ]] then [[ -n "${HOMEBREW_QUIET}" ]] || echo "Trying a full download" >&2 rm -f "${temporary_path}" "${HOMEBREW_CURL}" "${curl_args[@]}" "${url}" -o "${temporary_path}" + curl_exit_code="$?" fi else "${HOMEBREW_CURL}" "${curl_args[@]}" "${url}" -o "${temporary_path}" + curl_exit_code="$?" fi [[ -f "${temporary_path}" ]] && break done + if [[ "${curl_exit_code}" -ne 0 ]] + then + rm -f "${temporary_path}" + fi + if [[ ! -f "${temporary_path}" ]] then vendor_locations="$(printf " - %s\n" "${VENDOR_URLs[@]}")" diff --git a/Library/Homebrew/dependency_collector.rb b/Library/Homebrew/dependency_collector.rb index 6420504515..cddae5fcdc 100644 --- a/Library/Homebrew/dependency_collector.rb +++ b/Library/Homebrew/dependency_collector.rb @@ -5,7 +5,7 @@ require "dependency" require "dependencies" require "requirement" require "requirements" -require "extend/cachable" +require "cachable" # A dependency is a formula that another formula needs to install. # A requirement is something other than a formula that another formula diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index 24e69cb463..7b20891797 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -43,7 +43,7 @@ module Homebrew description: "Only check formulae and casks that are currently installed." switch "--eval-all", description: "Evaluate all available formulae and casks, whether installed or not, to audit them. " \ - "Implied if `HOMEBREW_EVAL_ALL` is set." + "Implied if `$HOMEBREW_EVAL_ALL` is set." switch "--new", description: "Run various additional style checks to determine if a new formula or cask is eligible " \ "for Homebrew. This should be used when creating new formulae or casks and implies " \ diff --git a/Library/Homebrew/dev-cmd/bottle.rb b/Library/Homebrew/dev-cmd/bottle.rb index 04307077bc..cb69bb464c 100644 --- a/Library/Homebrew/dev-cmd/bottle.rb +++ b/Library/Homebrew/dev-cmd/bottle.rb @@ -227,7 +227,7 @@ module Homebrew private sig { - params(string: String, keg: Keg, ignores: T::Array[String], + params(string: String, keg: Keg, ignores: T::Array[Regexp], formula_and_runtime_deps_names: T.nilable(T::Array[String])).returns(T::Boolean) } def keg_contain?(string, keg, ignores, formula_and_runtime_deps_names = nil) @@ -373,35 +373,17 @@ module Homebrew [gnu_tar(gnu_tar_formula), reproducible_gnutar_args(mtime)].freeze end - sig { params(formula: T.untyped).returns(T::Array[T.untyped]) } + sig { params(formula: Formula).returns(T::Array[Regexp]) } def formula_ignores(formula) - ignores = [] - cellar_regex = Regexp.escape(HOMEBREW_CELLAR) - prefix_regex = Regexp.escape(HOMEBREW_PREFIX) - # Ignore matches to go keg, because all go binaries are statically linked. any_go_deps = formula.deps.any? do |dep| Version.formula_optionally_versioned_regex(:go).match?(dep.name) end - if any_go_deps - go_regex = Version.formula_optionally_versioned_regex(:go, full: false) - ignores << %r{#{cellar_regex}/#{go_regex}/[\d.]+/libexec} - end + return [] unless any_go_deps - # TODO: Refactor and move to extend/os - # rubocop:disable Homebrew/MoveToExtendOS - ignores << case formula.name - # On Linux, GCC installation can be moved so long as the whole directory tree is moved together: - # https://gcc-help.gcc.gnu.narkive.com/GnwuCA7l/moving-gcc-from-the-installation-path-is-it-allowed. - when Version.formula_optionally_versioned_regex(:gcc) - Regexp.union(%r{#{cellar_regex}/gcc}, %r{#{prefix_regex}/opt/gcc}) if OS.linux? - # binutils is relocatable for the same reason: https://github.com/Homebrew/brew/pull/11899#issuecomment-906804451. - when Version.formula_optionally_versioned_regex(:binutils) - %r{#{cellar_regex}/binutils} if OS.linux? - end - # rubocop:enable Homebrew/MoveToExtendOS - - ignores.compact + cellar_regex = Regexp.escape(HOMEBREW_CELLAR) + go_regex = Version.formula_optionally_versioned_regex(:go, full: false) + Array(%r{#{cellar_regex}/#{go_regex}/[\d.]+/libexec}) end sig { params(formula: Formula).void } diff --git a/Library/Homebrew/dev-cmd/bump.rb b/Library/Homebrew/dev-cmd/bump.rb index e9422d9e56..1d510088fa 100644 --- a/Library/Homebrew/dev-cmd/bump.rb +++ b/Library/Homebrew/dev-cmd/bump.rb @@ -118,7 +118,7 @@ module Homebrew else raise UsageError, "`brew bump` without named arguments needs `--installed` or `--eval-all` passed or " \ - "`HOMEBREW_EVAL_ALL` set!" + "`$HOMEBREW_EVAL_ALL` set!" end if args.start_with diff --git a/Library/Homebrew/dev-cmd/contributions.rb b/Library/Homebrew/dev-cmd/contributions.rb index 2be6135a48..57a5fe79a3 100644 --- a/Library/Homebrew/dev-cmd/contributions.rb +++ b/Library/Homebrew/dev-cmd/contributions.rb @@ -88,16 +88,21 @@ module Homebrew contributions << "#{Utils.pluralize("time", grand_totals[username].values.sum, include_count: true)} (total)" - puts [ + contributions_string = [ "#{username} contributed", *contributions.to_sentence, "#{time_period(from:, to: args.to)}.", ].join(" ") + if args.csv? + $stderr.puts contributions_string + else + puts contributions_string + end end return unless args.csv? - puts + $stderr.puts puts generate_csv(grand_totals) end diff --git a/Library/Homebrew/dev-cmd/determine-test-runners.rb b/Library/Homebrew/dev-cmd/determine-test-runners.rb index 39449ea83f..52757b3f8d 100644 --- a/Library/Homebrew/dev-cmd/determine-test-runners.rb +++ b/Library/Homebrew/dev-cmd/determine-test-runners.rb @@ -21,7 +21,8 @@ module Homebrew "dependents.", env: :eval_all switch "--dependents", - description: "Determine runners for testing dependents. Requires `--eval-all` or `HOMEBREW_EVAL_ALL`.", + description: "Determine runners for testing dependents. " \ + "Requires `--eval-all` or `$HOMEBREW_EVAL_ALL` to be set.", depends_on: "--eval-all" named_args max: 2 diff --git a/Library/Homebrew/dev-cmd/edit.rb b/Library/Homebrew/dev-cmd/edit.rb index d88d603735..bee0caf795 100644 --- a/Library/Homebrew/dev-cmd/edit.rb +++ b/Library/Homebrew/dev-cmd/edit.rb @@ -9,10 +9,9 @@ module Homebrew class Edit < AbstractCommand cmd_args do description <<~EOS - Open a , or in the editor set by `EDITOR` or `HOMEBREW_EDITOR`, + Open a , or in the editor set by `$EDITOR` or `$HOMEBREW_EDITOR`, or open the Homebrew repository for editing if no argument is provided. EOS - switch "--formula", "--formulae", description: "Treat all named arguments as formulae." switch "--cask", "--casks", diff --git a/Library/Homebrew/dev-cmd/generate-analytics-api.rb b/Library/Homebrew/dev-cmd/generate-analytics-api.rb index 3d3fe20ede..a07abe2694 100755 --- a/Library/Homebrew/dev-cmd/generate-analytics-api.rb +++ b/Library/Homebrew/dev-cmd/generate-analytics-api.rb @@ -77,7 +77,7 @@ module Homebrew analytics_data_dir = root_dir/"_data/analytics" analytics_api_dir = root_dir/"api/analytics" - threads = [] + analytics_output_queue = Queue.new CATEGORIES.each do |category| formula_analytics_args = [] @@ -124,15 +124,40 @@ module Homebrew DAYS.each do |days| next if days != "30" && category_name == "build-error" && !data_source.nil? - threads << Thread.new do - args = %W[--days-ago=#{days}] - (analytics_data_path/"#{days}d.json").write run_formula_analytics(*formula_analytics_args, *args) - (analytics_api_path/"#{days}d.json").write analytics_json_template(category_name, data_source:) - end + analytics_output_queue << { + formula_analytics_args: formula_analytics_args.dup, + days: days, + analytics_data_path: analytics_data_path, + analytics_api_path: analytics_api_path, + category_name: category_name, + data_source: data_source, + } end end - threads.each(&:join) + workers = [] + 4.times do + workers << Thread.new do + until analytics_output_queue.empty? + analytics_output_type = begin + analytics_output_queue.pop(true) + rescue ThreadError + break + end + + days = analytics_output_type[:days] + args = ["--days-ago=#{days}"] + + (analytics_output_type[:analytics_data_path]/"#{days}d.json").write \ + run_formula_analytics(*analytics_output_type[:formula_analytics_args], *args) + + data_source = analytics_output_type[:data_source] + (analytics_output_type[:analytics_api_path]/"#{days}d.json").write \ + analytics_json_template(analytics_output_type[:category_name], data_source:) + end + end + end + workers.each(&:join) end end end diff --git a/Library/Homebrew/dev-cmd/generate-cask-api.rb b/Library/Homebrew/dev-cmd/generate-cask-api.rb index 40b3a1c7da..9f639aec52 100644 --- a/Library/Homebrew/dev-cmd/generate-cask-api.rb +++ b/Library/Homebrew/dev-cmd/generate-cask-api.rb @@ -33,7 +33,7 @@ module Homebrew raise TapUnavailableError, tap.name unless tap.installed? unless args.dry_run? - directories = ["_data/cask", "api/cask", "api/cask-source", "cask", "api/internal/v3"].freeze + directories = ["_data/cask", "api/cask", "api/cask-source", "cask", "api/internal"].freeze FileUtils.rm_rf directories FileUtils.mkdir_p directories end @@ -44,12 +44,14 @@ module Homebrew Cask::Cask.generating_hash! + all_casks = {} latest_macos = MacOSVersion.new((HOMEBREW_MACOS_NEWEST_UNSUPPORTED.to_i - 1).to_s).to_sym Homebrew::SimulateSystem.with(os: latest_macos, arch: :arm) do tap.cask_files.each do |path| cask = Cask::CaskLoader.load(path) name = cask.token - json = JSON.pretty_generate(cask.to_hash_with_variations) + all_casks[name] = cask.to_hash_with_variations + json = JSON.pretty_generate(all_casks[name]) cask_source = path.read html_template_name = html_template(name) @@ -67,6 +69,14 @@ module Homebrew canonical_json = JSON.pretty_generate(tap.cask_renames) File.write("_data/cask_canonical.json", "#{canonical_json}\n") unless args.dry_run? + + OnSystem::VALID_OS_ARCH_TAGS.each do |bottle_tag| + variation_casks = all_casks.map do |_, cask| + Homebrew::API.merge_variations(cask, bottle_tag:) + end + + File.write("api/internal/cask.#{bottle_tag}.json", JSON.generate(variation_casks)) unless args.dry_run? + end end end diff --git a/Library/Homebrew/dev-cmd/generate-formula-api.rb b/Library/Homebrew/dev-cmd/generate-formula-api.rb index ac8d5dd63b..5741ce6872 100644 --- a/Library/Homebrew/dev-cmd/generate-formula-api.rb +++ b/Library/Homebrew/dev-cmd/generate-formula-api.rb @@ -32,7 +32,7 @@ module Homebrew raise TapUnavailableError, tap.name unless tap.installed? unless args.dry_run? - directories = ["_data/formula", "api/formula", "formula", "api/internal/v3"] + directories = ["_data/formula", "api/formula", "formula", "api/internal"] FileUtils.rm_rf directories + ["_data/formula_canonical.json"] FileUtils.mkdir_p directories end @@ -44,12 +44,14 @@ module Homebrew Formulary.enable_factory_cache! Formula.generating_hash! + all_formulae = {} latest_macos = MacOSVersion.new((HOMEBREW_MACOS_NEWEST_UNSUPPORTED.to_i - 1).to_s).to_sym Homebrew::SimulateSystem.with(os: latest_macos, arch: :arm) do tap.formula_names.each do |name| formula = Formulary.factory(name) name = formula.name - json = JSON.pretty_generate(formula.to_hash_with_variations) + all_formulae[name] = formula.to_hash_with_variations + json = JSON.pretty_generate(all_formulae[name]) html_template_name = html_template(name) unless args.dry_run? @@ -65,6 +67,30 @@ module Homebrew canonical_json = JSON.pretty_generate(tap.formula_renames.merge(tap.alias_table)) File.write("_data/formula_canonical.json", "#{canonical_json}\n") unless args.dry_run? + + OnSystem::VALID_OS_ARCH_TAGS.each do |bottle_tag| + variation_formulae = all_formulae.to_h do |name, formula| + formula = Homebrew::API.merge_variations(formula, bottle_tag:) + + version = Version.new(formula.dig("versions", "stable")) + pkg_version = PkgVersion.new(version, formula["revision"]) + rebuild = formula.dig("bottle", "stable", "rebuild") || 0 + + bottle_collector = Utils::Bottles::Collector.new + formula.dig("bottle", "stable", "files")&.each do |tag, data| + tag = Utils::Bottles::Tag.from_symbol(tag) + bottle_collector.add tag, checksum: Checksum.new(data["sha256"]), cellar: :any + end + + sha256 = bottle_collector.specification_for(bottle_tag)&.checksum&.to_s + + [name, [pkg_version.to_s, rebuild, sha256]] + end + + unless args.dry_run? + File.write("api/internal/formula.#{bottle_tag}.json", JSON.generate(variation_formulae)) + end + end end end diff --git a/Library/Homebrew/dev-cmd/irb.rb b/Library/Homebrew/dev-cmd/irb.rb index 31cf968bcc..55107b78c1 100644 --- a/Library/Homebrew/dev-cmd/irb.rb +++ b/Library/Homebrew/dev-cmd/irb.rb @@ -44,8 +44,8 @@ module Homebrew switch "--examples", description: "Show several examples." switch "--pry", - env: :pry, - description: "Use Pry instead of IRB. Implied if `HOMEBREW_PRY` is set." + description: "Use Pry instead of IRB.", + env: :pry end # work around IRB modifying ARGV. diff --git a/Library/Homebrew/dev-cmd/linkage.rb b/Library/Homebrew/dev-cmd/linkage.rb index 23462cc98a..73ce789aed 100644 --- a/Library/Homebrew/dev-cmd/linkage.rb +++ b/Library/Homebrew/dev-cmd/linkage.rb @@ -23,7 +23,7 @@ module Homebrew description: "For every library that a keg references, print its dylib path followed by the " \ "binaries that link to it." switch "--cached", - description: "Print the cached linkage values stored in `HOMEBREW_CACHE`, set by a previous " \ + description: "Print the cached linkage values stored in `$HOMEBREW_CACHE`, set by a previous " \ "`brew linkage` run." named_args :installed_formula diff --git a/Library/Homebrew/dev-cmd/livecheck.rb b/Library/Homebrew/dev-cmd/livecheck.rb index dee478de47..af56300ab9 100644 --- a/Library/Homebrew/dev-cmd/livecheck.rb +++ b/Library/Homebrew/dev-cmd/livecheck.rb @@ -13,7 +13,7 @@ module Homebrew 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 + casks to check is taken from `$HOMEBREW_LIVECHECK_WATCHLIST` or `~/.homebrew/livecheck_watchlist.txt`. EOS switch "--full-name", diff --git a/Library/Homebrew/dev-cmd/sh.rb b/Library/Homebrew/dev-cmd/sh.rb index c6161dd1ad..2ba18a56e9 100644 --- a/Library/Homebrew/dev-cmd/sh.rb +++ b/Library/Homebrew/dev-cmd/sh.rb @@ -13,11 +13,11 @@ module Homebrew Enter an interactive shell for Homebrew's build environment. Use years-battle-hardened build logic to help your `./configure && make && make install` and even your `gem install` succeed. Especially handy if you run Homebrew - in an Xcode-only configuration since it adds tools like `make` to your `PATH` + in an Xcode-only configuration since it adds tools like `make` to your `$PATH` which build systems would not find otherwise. EOS flag "--env=", - description: "Use the standard `PATH` instead of superenv's when `std` is passed." + description: "Use the standard `$PATH` instead of superenv's when `std` is passed." flag "-c=", "--cmd=", description: "Execute commands in a non-interactive shell." diff --git a/Library/Homebrew/dev-cmd/tests.rb b/Library/Homebrew/dev-cmd/tests.rb index 4df8acd792..7e0329b1be 100644 --- a/Library/Homebrew/dev-cmd/tests.rb +++ b/Library/Homebrew/dev-cmd/tests.rb @@ -28,6 +28,8 @@ module Homebrew description: "Only runs tests on files that were changed from the master branch." switch "--fail-fast", description: "Exit early on the first failing test." + switch "--no-parallel", + description: "Run tests serially." flag "--only=", description: "Run only `_spec.rb`. Appending `:` will start at a " \ "specific line." @@ -49,7 +51,7 @@ module Homebrew HOMEBREW_LIBRARY_PATH.cd do setup_environment! - parallel = true + parallel = !args.no_parallel? only = args.only files = if only @@ -120,29 +122,13 @@ module Homebrew ] bundle_args << "--fail-fast" if args.fail_fast? bundle_args << "--profile" << args.profile if args.profile - - # TODO: Refactor and move to extend/os - # rubocop:disable Homebrew/MoveToExtendOS - unless OS.mac? - bundle_args << "--tag" << "~needs_macos" << "--tag" << "~cask" - files = files.grep_v(%r{^test/(os/mac|cask)(/.*|_spec\.rb)$}) - end - - unless OS.linux? - bundle_args << "--tag" << "~needs_linux" - files = files.grep_v(%r{^test/os/linux(/.*|_spec\.rb)$}) - end - # rubocop:enable Homebrew/MoveToExtendOS - bundle_args << "--tag" << "~needs_arm" unless Hardware::CPU.arm? - bundle_args << "--tag" << "~needs_intel" unless Hardware::CPU.intel? - bundle_args << "--tag" << "~needs_network" unless args.online? - unless ENV["CI"] - bundle_args << "--tag" << "~needs_ci" \ - << "--tag" << "~needs_svn" - end + bundle_args << "--tag" << "~needs_ci" unless ENV["CI"] + + bundle_args = os_bundle_args(bundle_args) + files = os_files(files) puts "Randomized with seed #{seed}" @@ -170,6 +156,41 @@ module Homebrew private + sig { params(bundle_args: T::Array[String]).returns(T::Array[String]) } + def os_bundle_args(bundle_args) + # for generic tests, remove macOS or Linux specific tests + non_linux_bundle_args(non_macos_bundle_args(bundle_args)) + end + + sig { params(bundle_args: T::Array[String]).returns(T::Array[String]) } + def non_macos_bundle_args(bundle_args) + bundle_args << "--tag" << "~needs_homebrew_core" if ENV["CI"] + bundle_args << "--tag" << "~needs_svn" unless args.online? + + bundle_args << "--tag" << "~needs_macos" << "--tag" << "~cask" + end + + sig { params(bundle_args: T::Array[String]).returns(T::Array[String]) } + def non_linux_bundle_args(bundle_args) + bundle_args << "--tag" << "~needs_linux" << "--tag" << "~needs_systemd" + end + + sig { params(files: T::Array[String]).returns(T::Array[String]) } + def os_files(files) + # for generic tests, remove macOS or Linux specific files + non_linux_files(non_macos_files(files)) + end + + sig { params(files: T::Array[String]).returns(T::Array[String]) } + def non_macos_files(files) + files.grep_v(%r{^test/(os/mac|cask)(/.*|_spec\.rb)$}) + end + + sig { params(files: T::Array[String]).returns(T::Array[String]) } + def non_linux_files(files) + files.grep_v(%r{^test/os/linux(/.*|_spec\.rb)$}) + end + sig { returns(T::Array[String]) } def changed_test_files changed_files = Utils.popen_read("git", "diff", "--name-only", "master") @@ -221,9 +242,6 @@ module Homebrew ENV["HOMEBREW_SORBET_RUNTIME"] = "1" ENV["HOMEBREW_NO_FORCE_BREW_WRAPPER"] = "1" - # TODO: remove this and fix tests when possible. - ENV["HOMEBREW_NO_INSTALL_FROM_API"] = "1" - ENV["USER"] ||= system_command!("id", args: ["-nu"]).stdout.chomp # Avoid local configuration messing with tests, e.g. git being configured @@ -249,3 +267,5 @@ module Homebrew end end end + +require "extend/os/dev-cmd/tests" diff --git a/Library/Homebrew/dev-cmd/unbottled.rb b/Library/Homebrew/dev-cmd/unbottled.rb index 3fb1880093..d439868d22 100644 --- a/Library/Homebrew/dev-cmd/unbottled.rb +++ b/Library/Homebrew/dev-cmd/unbottled.rb @@ -23,7 +23,7 @@ module Homebrew description: "Print the `homebrew/core` commits where bottles were lost in the last week." switch "--eval-all", description: "Evaluate all available formulae and casks, whether installed or not, to check them. " \ - "Implied if `HOMEBREW_EVAL_ALL` is set." + "Implied if `$HOMEBREW_EVAL_ALL` is set." conflicts "--dependents", "--total", "--lost" @@ -68,7 +68,7 @@ module Homebrew all = args.eval_all? if args.total? if !all && !Homebrew::EnvConfig.eval_all? - raise UsageError, "`brew unbottled --total` needs `--eval-all` passed or `HOMEBREW_EVAL_ALL` set!" + raise UsageError, "`brew unbottled --total` needs `--eval-all` passed or `$HOMEBREW_EVAL_ALL` set!" end all = true @@ -119,7 +119,7 @@ module Homebrew elsif args.dependents? if !args.eval_all? && !Homebrew::EnvConfig.eval_all? raise UsageError, - "`brew unbottled --dependents` needs `--eval-all` passed or `HOMEBREW_EVAL_ALL` set!" + "`brew unbottled --dependents` needs `--eval-all` passed or `$HOMEBREW_EVAL_ALL` set!" end formulae = all_formulae = Formula.all(eval_all: args.eval_all?) @@ -136,7 +136,7 @@ module Homebrew if analytics.blank? raise UsageError, "default sort by analytics data requires " \ - "`HOMEBREW_NO_GITHUB_API` and `HOMEBREW_NO_ANALYTICS` to be unset" + "`$HOMEBREW_NO_GITHUB_API` and `$HOMEBREW_NO_ANALYTICS` to be unset." end formulae = analytics["items"].filter_map do |i| diff --git a/Library/Homebrew/dev-cmd/update-test.rb b/Library/Homebrew/dev-cmd/update-test.rb index eb975b73fd..45a0257797 100644 --- a/Library/Homebrew/dev-cmd/update-test.rb +++ b/Library/Homebrew/dev-cmd/update-test.rb @@ -15,7 +15,7 @@ module Homebrew If no options are passed, use `origin/master` as the start commit. EOS switch "--to-tag", - description: "Set `HOMEBREW_UPDATE_TO_TAG` to test updating between tags." + description: "Set `$HOMEBREW_UPDATE_TO_TAG` to test updating between tags." switch "--keep-tmp", description: "Retain the temporary directory containing the new repository clone." flag "--commit=", diff --git a/Library/Homebrew/env_config.rb b/Library/Homebrew/env_config.rb index 7fc446340d..1af588add6 100644 --- a/Library/Homebrew/env_config.rb +++ b/Library/Homebrew/env_config.rb @@ -463,7 +463,7 @@ module Homebrew default_text: "`~/.ssh/config`", }, HOMEBREW_SUDO_THROUGH_SUDO_USER: { - description: "If set, Homebrew will use the `SUDO_USER` environment variable to define the user to " \ + description: "If set, Homebrew will use the `$SUDO_USER` environment variable to define the user to " \ "`sudo`(8) through when running `sudo`(8).", boolean: true, }, diff --git a/Library/Homebrew/extend/ENV.rb b/Library/Homebrew/extend/ENV.rb index b7a9afb644..4a449993f7 100644 --- a/Library/Homebrew/extend/ENV.rb +++ b/Library/Homebrew/extend/ENV.rb @@ -7,16 +7,6 @@ require "extend/ENV/shared" require "extend/ENV/std" require "extend/ENV/super" -module Kernel - sig { params(env: T.nilable(String)).returns(T::Boolean) } - def superenv?(env) - return false if env == "std" - - !Superenv.bin.nil? - end - private :superenv? -end - # # @!parse # # `ENV` is not actually a class, but this makes YARD happy diff --git a/Library/Homebrew/extend/kernel.rb b/Library/Homebrew/extend/kernel.rb index 56eb04b97d..948c0b3fba 100644 --- a/Library/Homebrew/extend/kernel.rb +++ b/Library/Homebrew/extend/kernel.rb @@ -5,6 +5,14 @@ # TODO: move these out of `Kernel`. module Kernel + sig { params(env: T.nilable(String)).returns(T::Boolean) } + def superenv?(env) + return false if env == "std" + + !Superenv.bin.nil? + end + private :superenv? + def require?(path) return false if path.nil? @@ -82,6 +90,17 @@ module Kernel end end + # Print a warning message only if not running in GitHub Actions. + # + # @api public + sig { params(message: T.any(String, Exception)).void } + def opoo_outside_github_actions(message) + require "utils/github/actions" + return if GitHub::Actions.env_set? + + opoo(message) + end + # Print an error message. # # @api public diff --git a/Library/Homebrew/extend/os/dev-cmd/tests.rb b/Library/Homebrew/extend/os/dev-cmd/tests.rb new file mode 100644 index 0000000000..556052a63f --- /dev/null +++ b/Library/Homebrew/extend/os/dev-cmd/tests.rb @@ -0,0 +1,5 @@ +# typed: strict +# frozen_string_literal: true + +require "extend/os/linux/dev-cmd/tests" if OS.linux? +require "extend/os/mac/dev-cmd/tests" if OS.mac? diff --git a/Library/Homebrew/extend/os/linux/bundle/bundle.rb b/Library/Homebrew/extend/os/linux/bundle/bundle.rb index 71c2e41625..1acbb70541 100644 --- a/Library/Homebrew/extend/os/linux/bundle/bundle.rb +++ b/Library/Homebrew/extend/os/linux/bundle/bundle.rb @@ -9,6 +9,16 @@ module OS def mas_installed? false end + + # Setup pkg-config, if present, to help locate packages + # Only need this on Linux as Homebrew provides a shim on macOS + sig { void } + def prepend_pkgconf_path_if_needed! + pkgconf = Formulary.factory("pkgconf") + return unless pkgconf.any_version_installed? + + ENV.prepend_path "PATH", pkgconf.opt_bin.to_s + end end end end diff --git a/Library/Homebrew/extend/os/linux/dev-cmd/tests.rb b/Library/Homebrew/extend/os/linux/dev-cmd/tests.rb new file mode 100644 index 0000000000..e7f3d30d65 --- /dev/null +++ b/Library/Homebrew/extend/os/linux/dev-cmd/tests.rb @@ -0,0 +1,23 @@ +# typed: strict +# frozen_string_literal: true + +module OS + module Linux + module DevCmd + module Tests + extend T::Helpers + + requires_ancestor { Homebrew::DevCmd::Tests } + + private + + sig { params(bundle_args: T::Array[String]).returns(T::Array[String]) } + def os_bundle_args(bundle_args) + non_macos_bundle_args(bundle_args) + end + end + end + end +end + +Homebrew::DevCmd::Tests.prepend(OS::Linux::DevCmd::Tests) diff --git a/Library/Homebrew/extend/os/mac/dev-cmd/bottle.rb b/Library/Homebrew/extend/os/mac/dev-cmd/bottle.rb index 9d07b43695..e75eeab739 100644 --- a/Library/Homebrew/extend/os/mac/dev-cmd/bottle.rb +++ b/Library/Homebrew/extend/os/mac/dev-cmd/bottle.rb @@ -18,6 +18,26 @@ module OS def gnu_tar(gnu_tar_formula) "#{gnu_tar_formula.opt_bin}/gtar" end + + sig { params(formula: Formula).returns(T::Array[Regexp]) } + def formula_ignores(formula) + ignores = super + + cellar_regex = Regexp.escape(HOMEBREW_CELLAR) + prefix_regex = Regexp.escape(HOMEBREW_PREFIX) + + ignores << case formula.name + # On Linux, GCC installation can be moved so long as the whole directory tree is moved together: + # https://gcc-help.gcc.gnu.narkive.com/GnwuCA7l/moving-gcc-from-the-installation-path-is-it-allowed. + when Version.formula_optionally_versioned_regex(:gcc) + Regexp.union(%r{#{cellar_regex}/gcc}, %r{#{prefix_regex}/opt/gcc}) if OS.linux? + # binutils is relocatable for the same reason: https://github.com/Homebrew/brew/pull/11899#issuecomment-906804451. + when Version.formula_optionally_versioned_regex(:binutils) + %r{#{cellar_regex}/binutils} if OS.linux? + end + + ignores.compact + end end end end diff --git a/Library/Homebrew/extend/os/mac/dev-cmd/tests.rb b/Library/Homebrew/extend/os/mac/dev-cmd/tests.rb new file mode 100644 index 0000000000..112ad3b6c8 --- /dev/null +++ b/Library/Homebrew/extend/os/mac/dev-cmd/tests.rb @@ -0,0 +1,23 @@ +# typed: strict +# frozen_string_literal: true + +module OS + module Mac + module DevCmd + module Tests + extend T::Helpers + + requires_ancestor { Homebrew::DevCmd::Tests } + + private + + sig { params(bundle_args: T::Array[String]).returns(T::Array[String]) } + def os_bundle_args(bundle_args) + non_linux_bundle_args(bundle_args) + end + end + end + end +end + +Homebrew::DevCmd::Tests.prepend(OS::Mac::DevCmd::Tests) diff --git a/Library/Homebrew/extend/os/mac/diagnostic.rb b/Library/Homebrew/extend/os/mac/diagnostic.rb index 311b68167e..c3d92eb374 100644 --- a/Library/Homebrew/extend/os/mac/diagnostic.rb +++ b/Library/Homebrew/extend/os/mac/diagnostic.rb @@ -425,8 +425,8 @@ module OS end def check_deprecated_caskroom_taps - tapped_caskroom_taps = Tap.select { |t| t.user == "caskroom" || t.name == "phinze/cask" } - .map(&:name) + tapped_caskroom_taps = ::Tap.select { |t| t.user == "caskroom" || t.name == "phinze/cask" } + .map(&:name) return if tapped_caskroom_taps.empty? <<~EOS diff --git a/Library/Homebrew/extend/os/mac/readall.rb b/Library/Homebrew/extend/os/mac/readall.rb index 23f71e403c..90e89c17d5 100644 --- a/Library/Homebrew/extend/os/mac/readall.rb +++ b/Library/Homebrew/extend/os/mac/readall.rb @@ -8,7 +8,7 @@ module OS requires_ancestor { Kernel } - sig { params(tap: Tap, os_name: T.nilable(Symbol), arch: T.nilable(Symbol)).returns(T::Boolean) } + sig { params(tap: ::Tap, os_name: T.nilable(Symbol), arch: T.nilable(Symbol)).returns(T::Boolean) } def valid_casks?(tap, os_name: nil, arch: ::Hardware::CPU.type) return true if os_name == :linux diff --git a/Library/Homebrew/extend/os/mac/tap.rb b/Library/Homebrew/extend/os/mac/tap.rb new file mode 100644 index 0000000000..2213a4f757 --- /dev/null +++ b/Library/Homebrew/extend/os/mac/tap.rb @@ -0,0 +1,17 @@ +# typed: strict +# frozen_string_literal: true + +module OS + module Mac + module Tap + module ClassMethods + sig { returns(T::Array[::Tap]) } + def core_taps + [CoreTap.instance, CoreCaskTap.instance].freeze + end + end + end + end +end + +Tap.singleton_class.prepend(OS::Mac::Tap::ClassMethods) diff --git a/Library/Homebrew/extend/os/mac/utils/bottles.rb b/Library/Homebrew/extend/os/mac/utils/bottles.rb index 754aeaec64..9b4c71a914 100644 --- a/Library/Homebrew/extend/os/mac/utils/bottles.rb +++ b/Library/Homebrew/extend/os/mac/utils/bottles.rb @@ -47,7 +47,7 @@ module Utils return if tag_version.blank? tags.find do |candidate| - next if candidate.arch != tag.arch + next if candidate.standardized_arch != tag.standardized_arch candidate.to_macos_version <= tag_version rescue MacOSVersion::Error diff --git a/Library/Homebrew/extend/os/tap.rb b/Library/Homebrew/extend/os/tap.rb new file mode 100644 index 0000000000..e6662ff704 --- /dev/null +++ b/Library/Homebrew/extend/os/tap.rb @@ -0,0 +1,4 @@ +# typed: strict +# frozen_string_literal: true + +require "extend/os/mac/tap" if OS.mac? diff --git a/Library/Homebrew/extend/pathname.rb b/Library/Homebrew/extend/pathname.rb index 91337f81d1..2e28057a2c 100644 --- a/Library/Homebrew/extend/pathname.rb +++ b/Library/Homebrew/extend/pathname.rb @@ -1,79 +1,9 @@ # typed: true # rubocop:todo Sorbet/StrictSigil # frozen_string_literal: true -module DiskUsageExtension - extend T::Helpers - - requires_ancestor { Pathname } - - sig { returns(Integer) } - def disk_usage - return @disk_usage if defined?(@disk_usage) - - compute_disk_usage - @disk_usage - end - - sig { returns(Integer) } - def file_count - return @file_count if defined?(@file_count) - - compute_disk_usage - @file_count - end - - sig { returns(String) } - def abv - out = +"" - compute_disk_usage - out << "#{number_readable(@file_count)} files, " if @file_count > 1 - out << disk_usage_readable(@disk_usage).to_s - out.freeze - end - - private - - sig { void } - def compute_disk_usage - if symlink? && !exist? - @file_count = 1 - @disk_usage = 0 - return - end - - path = if symlink? - resolved_path - else - self - end - - if path.directory? - scanned_files = Set.new - @file_count = 0 - @disk_usage = 0 - path.find do |f| - if f.directory? - @disk_usage += f.lstat.size - else - @file_count += 1 if f.basename.to_s != ".DS_Store" - # use Pathname#lstat instead of Pathname#stat to get info of symlink itself. - stat = f.lstat - file_id = [stat.dev, stat.ino] - # count hardlinks only once. - unless scanned_files.include?(file_id) - @disk_usage += stat.size - scanned_files.add(file_id) - end - end - end - else - @file_count = 1 - @disk_usage = path.lstat.size - end - end -end - require "system_command" +require "extend/pathname/disk_usage_extension" +require "extend/pathname/observer_pathname_extension" # Homebrew extends Ruby's `Pathname` to make our code more readable. # @see https://ruby-doc.org/stdlib-2.6.3/libdoc/pathname/rdoc/Pathname.html Ruby's Pathname API @@ -524,92 +454,3 @@ class Pathname end end require "extend/os/pathname" - -require "context" - -module ObserverPathnameExtension - extend T::Helpers - - requires_ancestor { Pathname } - - class << self - include Context - - sig { returns(Integer) } - attr_accessor :n, :d - - sig { void } - def reset_counts! - @n = @d = 0 - @put_verbose_trimmed_warning = false - end - - sig { returns(Integer) } - def total - n + d - end - - sig { returns([Integer, Integer]) } - def counts - [n, d] - end - - MAXIMUM_VERBOSE_OUTPUT = 100 - private_constant :MAXIMUM_VERBOSE_OUTPUT - - sig { returns(T::Boolean) } - def verbose? - return super unless ENV["CI"] - return false unless super - - if total < MAXIMUM_VERBOSE_OUTPUT - true - else - unless @put_verbose_trimmed_warning - puts "Only the first #{MAXIMUM_VERBOSE_OUTPUT} operations were output." - @put_verbose_trimmed_warning = true - end - false - end - end - end - - sig { void } - def unlink - super - puts "rm #{self}" if ObserverPathnameExtension.verbose? - ObserverPathnameExtension.n += 1 - end - - sig { void } - def mkpath - super - puts "mkdir -p #{self}" if ObserverPathnameExtension.verbose? - end - - sig { void } - def rmdir - super - puts "rmdir #{self}" if ObserverPathnameExtension.verbose? - ObserverPathnameExtension.d += 1 - end - - sig { params(src: Pathname).void } - def make_relative_symlink(src) - super - puts "ln -s #{src.relative_path_from(dirname)} #{basename}" if ObserverPathnameExtension.verbose? - ObserverPathnameExtension.n += 1 - end - - sig { void } - def install_info - super - puts "info #{self}" if ObserverPathnameExtension.verbose? - end - - sig { void } - def uninstall_info - super - puts "uninfo #{self}" if ObserverPathnameExtension.verbose? - end -end diff --git a/Library/Homebrew/extend/pathname/disk_usage_extension.rb b/Library/Homebrew/extend/pathname/disk_usage_extension.rb new file mode 100644 index 0000000000..4781ebfeb5 --- /dev/null +++ b/Library/Homebrew/extend/pathname/disk_usage_extension.rb @@ -0,0 +1,74 @@ +# typed: true # rubocop:todo Sorbet/StrictSigil +# frozen_string_literal: true + +module DiskUsageExtension + extend T::Helpers + + requires_ancestor { Pathname } + + sig { returns(Integer) } + def disk_usage + return @disk_usage if defined?(@disk_usage) + + compute_disk_usage + @disk_usage + end + + sig { returns(Integer) } + def file_count + return @file_count if defined?(@file_count) + + compute_disk_usage + @file_count + end + + sig { returns(String) } + def abv + out = +"" + compute_disk_usage + out << "#{number_readable(@file_count)} files, " if @file_count > 1 + out << disk_usage_readable(@disk_usage).to_s + out.freeze + end + + private + + sig { void } + def compute_disk_usage + if symlink? && !exist? + @file_count = 1 + @disk_usage = 0 + return + end + + path = if symlink? + resolved_path + else + self + end + + if path.directory? + scanned_files = Set.new + @file_count = 0 + @disk_usage = 0 + path.find do |f| + if f.directory? + @disk_usage += f.lstat.size + else + @file_count += 1 if f.basename.to_s != ".DS_Store" + # use Pathname#lstat instead of Pathname#stat to get info of symlink itself. + stat = f.lstat + file_id = [stat.dev, stat.ino] + # count hardlinks only once. + unless scanned_files.include?(file_id) + @disk_usage += stat.size + scanned_files.add(file_id) + end + end + end + else + @file_count = 1 + @disk_usage = path.lstat.size + end + end +end diff --git a/Library/Homebrew/extend/pathname/observer_pathname_extension.rb b/Library/Homebrew/extend/pathname/observer_pathname_extension.rb new file mode 100644 index 0000000000..2ef2035cb7 --- /dev/null +++ b/Library/Homebrew/extend/pathname/observer_pathname_extension.rb @@ -0,0 +1,91 @@ +# typed: true # rubocop:todo Sorbet/StrictSigil +# frozen_string_literal: true + +require "context" + +module ObserverPathnameExtension + extend T::Helpers + + requires_ancestor { Pathname } + + class << self + include Context + + sig { returns(Integer) } + attr_accessor :n, :d + + sig { void } + def reset_counts! + @n = @d = 0 + @put_verbose_trimmed_warning = false + end + + sig { returns(Integer) } + def total + n + d + end + + sig { returns([Integer, Integer]) } + def counts + [n, d] + end + + MAXIMUM_VERBOSE_OUTPUT = 100 + private_constant :MAXIMUM_VERBOSE_OUTPUT + + sig { returns(T::Boolean) } + def verbose? + return super unless ENV["CI"] + return false unless super + + if total < MAXIMUM_VERBOSE_OUTPUT + true + else + unless @put_verbose_trimmed_warning + puts "Only the first #{MAXIMUM_VERBOSE_OUTPUT} operations were output." + @put_verbose_trimmed_warning = true + end + false + end + end + end + + sig { void } + def unlink + super + puts "rm #{self}" if ObserverPathnameExtension.verbose? + ObserverPathnameExtension.n += 1 + end + + sig { void } + def mkpath + super + puts "mkdir -p #{self}" if ObserverPathnameExtension.verbose? + end + + sig { void } + def rmdir + super + puts "rmdir #{self}" if ObserverPathnameExtension.verbose? + ObserverPathnameExtension.d += 1 + end + + sig { params(src: Pathname).void } + def make_relative_symlink(src) + super + puts "ln -s #{src.relative_path_from(dirname)} #{basename}" if ObserverPathnameExtension.verbose? + ObserverPathnameExtension.n += 1 + end + + sig { void } + def install_info + super + puts "info #{self}" if ObserverPathnameExtension.verbose? + end + + sig { void } + def uninstall_info + super + puts "uninfo #{self}" if ObserverPathnameExtension.verbose? + end +end diff --git a/Library/Homebrew/extend/time.rb b/Library/Homebrew/extend/time.rb index 75a79b864b..2d266db5ff 100644 --- a/Library/Homebrew/extend/time.rb +++ b/Library/Homebrew/extend/time.rb @@ -5,5 +5,9 @@ require "time" class Time # Backwards compatibility for formulae that used this ActiveSupport extension - alias rfc3339 xmlschema + sig { returns(String) } + def rfc3339 + odeprecated "Time#rfc3339", "Time#xmlschema" + xmlschema + end end diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index c07a6f6292..bf570f6c1e 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -38,9 +38,9 @@ require "tab" require "mktemp" require "find" require "utils/spdx" -require "extend/on_system" +require "on_system" require "api" -require "extend/api_hashable" +require "api_hashable" # A formula provides instructions and metadata for Homebrew to install a piece # of software. Every Homebrew formula is a {Formula}. @@ -2593,11 +2593,8 @@ class Formula if path.exist? && on_system_blocks_exist? formula_contents = path.read - OnSystem::ALL_OS_ARCH_COMBINATIONS.each do |os, arch| - bottle_tag = Utils::Bottles::Tag.new(system: os, arch:) - next unless bottle_tag.valid_combination? - - Homebrew::SimulateSystem.with(os:, arch:) do + OnSystem::VALID_OS_ARCH_TAGS.each do |bottle_tag| + Homebrew::SimulateSystem.with_tag(bottle_tag) do variations_namespace = Formulary.class_s("Variations#{bottle_tag.to_sym.capitalize}") variations_formula_class = Formulary.load_formula(name, path, formula_contents, variations_namespace, flags: self.class.build_flags, ignore_errors: true) diff --git a/Library/Homebrew/formula_auditor.rb b/Library/Homebrew/formula_auditor.rb index b08a3c013c..4aa06f0bf6 100644 --- a/Library/Homebrew/formula_auditor.rb +++ b/Library/Homebrew/formula_auditor.rb @@ -114,7 +114,7 @@ module Homebrew ln -s #{formula.path.to_s.gsub(formula.tap.path, "..")} #{alias_name} EOS else - problem "Formula has other versions so create an alias named #{alias_name}." + problem "Formula has other versions so create an alias named '#{alias_name}'." end end @@ -153,7 +153,7 @@ module Homebrew next if synced_formula == name if (synced_version = Formulary.factory(synced_formula).version) != version - problem "Version of `#{synced_formula}` (#{synced_version}) should match version of `#{name}` (#{version})" + problem "Version of #{synced_formula} (#{synced_version}) should match version of #{name} (#{version})" end end @@ -188,7 +188,7 @@ module Homebrew return if formula.core_formula? return unless Formula.core_names.include?(name) - problem "Formula name conflicts with existing core formula." + problem "Formula name conflicts with an existing formula in homebrew/core." end PERMITTED_LICENSE_MISMATCHES = { @@ -226,7 +226,7 @@ module Homebrew problem <<~EOS Formula #{formula.name} contains incompatible licenses: #{incompatible_licenses}. Formulae in homebrew/core must either use a Debian Free Software Guidelines license - or be released into the public domain. See #{Formatter.url("https://docs.brew.sh/License-Guidelines")} + or be released into the public domain: #{Formatter.url("https://docs.brew.sh/License-Guidelines")} EOS end @@ -327,7 +327,7 @@ module Homebrew end end - problem "Dependency '#{dep}' does not define option #{opt.name.inspect}" + problem "Dependency '#{dep}' does not define option: #{opt.name.inspect}" end problem "Don't use 'git' as a dependency (it's always available)" if @new_formula && dep.name == "git" @@ -448,7 +448,7 @@ module Homebrew if T.must(tap).formula_renames.key?(conflict.name) || T.must(tap).aliases.include?(conflict.name) problem "Formula conflict should be declared using " \ - "canonical name (#{conflicting_formula.name}) instead of #{conflict.name}" + "canonical name (#{conflicting_formula.name}) instead of '#{conflict.name}'" end reverse_conflict_found = T.let(false, T::Boolean) @@ -457,7 +457,7 @@ module Homebrew if T.must(tap).formula_renames.key?(reverse_conflict.name) || T.must(tap).aliases.include?(reverse_conflict.name) problem "Formula #{conflicting_formula.name} conflict should be declared using " \ - "canonical name (#{reverse_conflict_formula.name}) instead of #{reverse_conflict.name}" + "canonical name (#{reverse_conflict_formula.name}) instead of '#{reverse_conflict.name}'" end reverse_conflict_found ||= reverse_conflict_formula == formula @@ -651,7 +651,7 @@ module Homebrew metadata = SharedAudits.github_repo_data(user, repo) return if metadata.nil? - problem "GitHub repo is archived" if metadata["archived"] + problem "GitHub repository is archived" if metadata["archived"] end def audit_gitlab_repository_archived @@ -663,7 +663,7 @@ module Homebrew metadata = SharedAudits.gitlab_repo_data(user, repo) return if metadata.nil? - problem "GitLab repo is archived" if metadata["archived"] + problem "GitLab repository is archived" if metadata["archived"] end def audit_github_repository @@ -712,7 +712,7 @@ module Homebrew end def audit_specs - problem "Head-only (no stable download)" if head_only?(formula) + problem "HEAD-only (no stable download)" if head_only?(formula) %w[Stable HEAD].each do |name| spec_name = name.downcase.to_sym @@ -759,7 +759,7 @@ module Homebrew if formula.head && @versioned_formula && !formula.tap&.audit_exception(:versioned_head_spec_allowlist, formula.name) - problem "Versioned formulae should not have a `HEAD` spec" + problem "Versioned formulae should not have a `head` spec" end stable = formula.stable @@ -771,7 +771,7 @@ module Homebrew stable_version_string = version.to_s if stable_version_string.start_with?("HEAD") - problem "Stable: non-HEAD version name (#{stable_version_string}) should not begin with HEAD" + problem "Stable: non-HEAD version (#{stable_version_string}) should not begin with `HEAD`" end stable_url_version = Version.parse(stable.url) @@ -790,7 +790,7 @@ module Homebrew return if formula.tap&.audit_exception :unstable_allowlist, formula.name, version_prefix return if formula.tap&.audit_exception :unstable_devel_allowlist, formula.name, version_prefix - problem "Stable version URLs should not contain #{matched}" + problem "Stable: version URLs should not contain `#{matched}`" when %r{download\.gnome\.org/sources}, %r{ftp\.gnome\.org/pub/GNOME/sources}i version_prefix = stable.version.major_minor return if formula.tap&.audit_exception :gnome_devel_allowlist, formula.name, version_prefix @@ -800,11 +800,11 @@ module Homebrew return if stable_url_version >= Version.new("40.0") return if stable_url_minor_version.even? - problem "#{stable.version} is a development release" + problem "Stable: version (#{stable.version}) is a development release" when %r{isc.org/isc/bind\d*/}i return if stable_url_minor_version.even? - problem "#{stable.version} is a development release" + problem "Stable: version (#{stable.version}) is a development release" when %r{https?://gitlab\.com/([\w-]+)/([\w-]+)} owner = T.must(Regexp.last_match(1)) @@ -845,7 +845,7 @@ module Homebrew if !newest_committed[:version].nil? && current_version < newest_committed[:version] && current_version_scheme == previous_committed[:version_scheme] - problem "stable version should not decrease (from #{newest_committed[:version]} to #{current_version})" + problem "Stable: version should not decrease (from #{newest_committed[:version]} to #{current_version})" end end @@ -867,14 +867,14 @@ module Homebrew !current_revision.zero? && current_revision == newest_committed[:revision] && current_revision == previous_committed[:revision] - problem "'revision #{current_revision}' should be removed" + problem "`revision #{current_revision}` should be removed" elsif current_version == previous_committed[:version] && !previous_committed[:revision].nil? && current_revision < previous_committed[:revision] - problem "revision should not decrease (from #{previous_committed[:revision]} to #{current_revision})" + problem "`revision` should not decrease (from #{previous_committed[:revision]} to #{current_revision})" elsif newest_committed[:revision] && current_revision > (newest_committed[:revision] + 1) - problem "revisions should only increment by 1" + problem "`revision` should only increment by 1" end end @@ -891,10 +891,10 @@ module Homebrew return if previous_committed[:version_scheme].nil? if current_version_scheme < previous_committed[:version_scheme] - problem "version_scheme should not decrease (from #{previous_committed[:version_scheme]} " \ + problem "`version_scheme` should not decrease (from #{previous_committed[:version_scheme]} " \ "to #{current_version_scheme})" elsif current_version_scheme > (previous_committed[:version_scheme] + 1) - problem "version_schemes should only increment by 1" + problem "`version_scheme` should only increment by 1" end end @@ -935,7 +935,7 @@ module Homebrew bin_names.each do |name| shell_commands.each do |cmd| if text.to_s.match?(/test do.*#{cmd}[(\s]+['"]#{Regexp.escape(name)}[\s'"]/m) - problem %Q(fully scope test #{cmd} calls, e.g. #{cmd} "\#{bin}/#{name}") + problem %Q(Fully scope test `#{cmd}` calls, e.g.: #{cmd} "\#{bin}/#{name}") end end end diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb index 7d7aad186d..56d9094ac2 100644 --- a/Library/Homebrew/formula_installer.rb +++ b/Library/Homebrew/formula_installer.rb @@ -520,6 +520,7 @@ class FormulaInstaller oh1 "Installing #{Formatter.identifier(formula.full_name)} #{options}".strip if show_header? if (tap = formula.tap) && tap.should_report_analytics? + require "utils/analytics" Utils::Analytics.report_package_event(:formula_install, package_name: formula.name, tap_name: tap.name, on_request: installed_on_request?, options:) end @@ -892,9 +893,11 @@ on_request: installed_on_request?, options:) return if quiet? caveats = Caveats.new(formula) - return if caveats.empty? + Homebrew.messages.record_completions_and_elisp(caveats.completions_and_elisp) + return if caveats.caveats.empty? + @show_summary_heading = true ohai "Caveats", caveats.to_s Homebrew.messages.record_caveats(formula.name, caveats) diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb index 2f191fb787..5a48b25d8b 100644 --- a/Library/Homebrew/formulary.rb +++ b/Library/Homebrew/formulary.rb @@ -2,7 +2,7 @@ # frozen_string_literal: true require "digest/sha2" -require "extend/cachable" +require "cachable" require "tab" require "utils" require "utils/bottles" diff --git a/Library/Homebrew/global.rb b/Library/Homebrew/global.rb index ee4f5fa916..ff9d0f79b3 100644 --- a/Library/Homebrew/global.rb +++ b/Library/Homebrew/global.rb @@ -138,7 +138,7 @@ require "extend/kernel" require "os" require "extend/array" -require "extend/cachable" +require "cachable" require "extend/enumerable" require "extend/string" require "extend/pathname" diff --git a/Library/Homebrew/keg.rb b/Library/Homebrew/keg.rb index 40f96d48ba..275cc8fed0 100644 --- a/Library/Homebrew/keg.rb +++ b/Library/Homebrew/keg.rb @@ -4,7 +4,7 @@ require "keg_relocate" require "language/python" require "lock_file" -require "extend/cachable" +require "cachable" # Installation prefix of a formula. class Keg diff --git a/Library/Homebrew/macos_version.rb b/Library/Homebrew/macos_version.rb index 9c1cd7117f..f71a2e6e73 100644 --- a/Library/Homebrew/macos_version.rb +++ b/Library/Homebrew/macos_version.rb @@ -19,6 +19,7 @@ class MacOSVersion < Version # NOTE: When removing symbols here, ensure that they are added # to `DEPRECATED_MACOS_VERSIONS` in `MacOSRequirement`. SYMBOLS = { + tahoe: "26", sequoia: "15", sonoma: "14", ventura: "13", @@ -34,7 +35,9 @@ class MacOSVersion < Version sig { params(macos_version: MacOSVersion).returns(Version) } def self.kernel_major_version(macos_version) version_major = macos_version.major.to_i - if version_major > 10 + if version_major >= 26 + Version.new((version_major - 1).to_s) + elsif version_major > 10 Version.new((version_major + 9).to_s) else version_minor = macos_version.minor.to_i @@ -50,7 +53,7 @@ class MacOSVersion < Version sig { params(version: T.nilable(String)).void } def initialize(version) - raise MacOSVersion::Error, version unless /\A1\d+(?:\.\d+){0,2}\Z/.match?(version) + raise MacOSVersion::Error, version unless /\A\d{2,}(?:\.\d+){0,2}\z/.match?(version) super(T.must(version)) diff --git a/Library/Homebrew/manpages/brew.1.md.erb b/Library/Homebrew/manpages/brew.1.md.erb index d3b0173d8a..13461256a3 100644 --- a/Library/Homebrew/manpages/brew.1.md.erb +++ b/Library/Homebrew/manpages/brew.1.md.erb @@ -133,7 +133,7 @@ If no search term is provided, all locally available formulae are listed. ## CUSTOM EXTERNAL COMMANDS Homebrew, like `git`(1), supports external commands. These are executable -scripts that reside somewhere in the `PATH`, named `brew-` or +scripts that reside somewhere in the `$PATH`, named `brew-` or `brew-``.rb`, which can be invoked like `brew` . This allows you to create your own commands without modifying Homebrew's internals. @@ -184,7 +184,7 @@ files: User-specific environment files take precedence over prefix-specific files and prefix-specific files take precedence over system-wide files (unless -`HOMEBREW_SYSTEM_ENV_TAKES_PRIORITY` is set, see below). +`$HOMEBREW_SYSTEM_ENV_TAKES_PRIORITY` is set, see below). Note that these files do not support shell variable expansion e.g. `$HOME` or command execution e.g. `$(cat file)`. diff --git a/Library/Homebrew/mcp_server.rb b/Library/Homebrew/mcp_server.rb new file mode 100644 index 0000000000..2ce1c89e11 --- /dev/null +++ b/Library/Homebrew/mcp_server.rb @@ -0,0 +1,272 @@ +# typed: strict +# frozen_string_literal: true + +# This is a standalone Ruby script as MCP servers need a faster startup time +# than a normal Homebrew Ruby command allows. +require_relative "standalone" +require "json" +require "stringio" + +module Homebrew + # Provides a Model Context Protocol (MCP) server for Homebrew. + # See https://modelcontextprotocol.io/introduction for more information. + # + # https://modelcontextprotocol.io/docs/tools/inspector is useful for testing. + class McpServer + HOMEBREW_BREW_FILE = T.let(ENV.fetch("HOMEBREW_BREW_FILE").freeze, String) + HOMEBREW_VERSION = T.let(ENV.fetch("HOMEBREW_VERSION").freeze, String) + JSON_RPC_VERSION = T.let("2.0", String) + MCP_PROTOCOL_VERSION = T.let("2025-03-26", String) + ERROR_CODE = T.let(-32601, Integer) + + SERVER_INFO = T.let({ + name: "brew-mcp-server", + version: HOMEBREW_VERSION, + }.freeze, T::Hash[Symbol, String]) + + FORMULA_OR_CASK_PROPERTIES = T.let({ + formula_or_cask: { + type: "string", + description: "Formula or cask name", + }, + }.freeze, T::Hash[Symbol, T.anything]) + + # NOTE: Cursor (as of June 2025) will only query/use a maximum of 40 tools. + TOOLS = T.let({ + search: { + name: "search", + description: "Perform a substring search of cask tokens and formula names for . " \ + "If is flanked by slashes, it is interpreted as a regular expression.", + command: "brew search", + inputSchema: { + type: "object", + properties: { + text_or_regex: { + type: "string", + description: "Text or regex to search for", + }, + }, + }, + required: ["text_or_regex"], + }, + info: { + name: "info", + description: "Display brief statistics for your Homebrew installation. " \ + "If a or is provided, show summary of information about it.", + command: "brew info", + inputSchema: { type: "object", properties: FORMULA_OR_CASK_PROPERTIES }, + }, + install: { + name: "install", + description: "Install a or .", + command: "brew install", + inputSchema: { type: "object", properties: FORMULA_OR_CASK_PROPERTIES }, + required: ["formula_or_cask"], + }, + update: { + name: "update", + description: "Fetch the newest version of Homebrew and all formulae from GitHub using `git` and " \ + "perform any necessary migrations.", + command: "brew update", + inputSchema: { type: "object", properties: {} }, + }, + upgrade: { + name: "upgrade", + description: "Upgrade outdated casks and outdated, unpinned formulae using the same options they were " \ + "originally installed with, plus any appended brew formula options. If or " \ + "are specified, upgrade only the given or kegs (unless they are pinned).", + command: "brew upgrade", + inputSchema: { type: "object", properties: FORMULA_OR_CASK_PROPERTIES }, + }, + uninstall: { + name: "uninstall", + description: "Uninstall a or .", + command: "brew uninstall", + inputSchema: { type: "object", properties: FORMULA_OR_CASK_PROPERTIES }, + required: ["formula_or_cask"], + }, + list: { + name: "list", + description: "List all installed formulae and casks. " \ + "If is provided, summarise the paths within its current keg. " \ + "If is provided, list its artifacts.", + command: "brew list", + inputSchema: { type: "object", properties: FORMULA_OR_CASK_PROPERTIES }, + }, + config: { + name: "config", + description: "Show Homebrew and system configuration info useful for debugging. " \ + "If you file a bug report, you will be required to provide this information.", + command: "brew config", + inputSchema: { type: "object", properties: {} }, + }, + doctor: { + name: "doctor", + description: "Check your system for potential problems. Will exit with a non-zero status " \ + "if any potential problems are found. " \ + "Please note that these warnings are just used to help the Homebrew maintainers " \ + "with debugging if you file an issue. If everything you use Homebrew for " \ + "is working fine: please don't worry or file an issue; just ignore this.", + command: "brew doctor", + inputSchema: { type: "object", properties: {} }, + }, + commands: { + name: "commands", + description: "Show lists of built-in and external commands.", + command: "brew commands", + inputSchema: { type: "object", properties: {} }, + }, + help: { + name: "help", + description: "Outputs the usage instructions for `brew` .", + command: "brew help", + inputSchema: { + type: "object", + properties: { + command: { + type: "string", + description: "Command to get help for", + }, + }, + }, + }, + }.freeze, T::Hash[Symbol, T::Hash[Symbol, T.anything]]) + + sig { params(stdin: T.any(IO, StringIO), stdout: T.any(IO, StringIO), stderr: T.any(IO, StringIO)).void } + def initialize(stdin: $stdin, stdout: $stdout, stderr: $stderr) + @debug_logging = T.let(ARGV.include?("--debug") || ARGV.include?("-d"), T::Boolean) + @ping_switch = T.let(ARGV.include?("--ping"), T::Boolean) + @stdin = T.let(stdin, T.any(IO, StringIO)) + @stdout = T.let(stdout, T.any(IO, StringIO)) + @stderr = T.let(stderr, T.any(IO, StringIO)) + end + + sig { returns(T::Boolean) } + def debug_logging? = @debug_logging + + sig { returns(T::Boolean) } + def ping_switch? = @ping_switch + + sig { void } + def run + @stderr.puts "==> Started Homebrew MCP server..." + + loop do + input = if ping_switch? + { jsonrpc: JSON_RPC_VERSION, id: 1, method: "ping" }.to_json + else + @stdin.gets + end + next if input.nil? || input.strip.empty? + + request = JSON.parse(input) + debug("Request: #{JSON.pretty_generate(request)}") + + response = handle_request(request) + if response.nil? + debug("Response: nil") + next + end + + debug("Response: #{JSON.pretty_generate(response)}") + output = JSON.dump(response).strip + @stdout.puts(output) + @stdout.flush + + break if ping_switch? + end + rescue Interrupt + exit 0 + rescue => e + log("Error: #{e.message}") + exit 1 + end + + sig { params(text: String).void } + def debug(text) + return unless debug_logging? + + log(text) + end + + sig { params(text: String).void } + def log(text) + @stderr.puts(text) + @stderr.flush + end + + sig { params(request: T::Hash[String, T.untyped]).returns(T.nilable(T::Hash[Symbol, T.anything])) } + def handle_request(request) + id = request["id"] + return if id.nil? + + case request["method"] + when "initialize" + respond_result(id, { + protocolVersion: MCP_PROTOCOL_VERSION, + capabilities: { + tools: { listChanged: false }, + prompts: {}, + resources: {}, + logging: {}, + roots: {}, + }, + serverInfo: SERVER_INFO, + }) + when "resources/list" + respond_result(id, { resources: [] }) + when "resources/templates/list" + respond_result(id, { resourceTemplates: [] }) + when "prompts/list" + respond_result(id, { prompts: [] }) + when "ping" + respond_result(id) + when "get_server_info" + respond_result(id, SERVER_INFO) + when "logging/setLevel" + @debug_logging = request["params"]["level"] == "debug" + respond_result(id) + when "notifications/initialized", "notifications/cancelled" + respond_result + when "tools/list" + respond_result(id, { tools: TOOLS.values }) + when "tools/call" + if (tool = TOOLS.fetch(request["params"]["name"].to_sym, nil)) + require "shellwords" + + arguments = request["params"]["arguments"] + argument = arguments.fetch("formula_or_cask", "") + argument = arguments.fetch("text_or_regex", "") if argument.strip.empty? + argument = arguments.fetch("command", "") if argument.strip.empty? + argument = nil if argument.strip.empty? + brew_command = T.cast(tool.fetch(:command), String) + .delete_prefix("brew ") + full_command = [HOMEBREW_BREW_FILE, brew_command, argument].compact + .map { |arg| Shellwords.escape(arg) } + .join(" ") + output = `#{full_command} 2>&1`.strip + respond_result(id, { content: [{ type: "text", text: output }] }) + else + respond_error(id, "Unknown tool") + end + else + respond_error(id, "Method not found") + end + end + + sig { + params(id: T.nilable(Integer), + result: T::Hash[Symbol, T.anything]).returns(T.nilable(T::Hash[Symbol, T.anything])) + } + def respond_result(id = nil, result = {}) + return if id.nil? + + { jsonrpc: JSON_RPC_VERSION, id:, result: } + end + + sig { params(id: T.nilable(Integer), message: String).returns(T::Hash[Symbol, T.anything]) } + def respond_error(id, message) + { jsonrpc: JSON_RPC_VERSION, id:, error: { code: ERROR_CODE, message: } } + end + end +end diff --git a/Library/Homebrew/messages.rb b/Library/Homebrew/messages.rb index cdbf7059e9..830ce46fac 100644 --- a/Library/Homebrew/messages.rb +++ b/Library/Homebrew/messages.rb @@ -16,6 +16,7 @@ class Messages sig { void } def initialize @caveats = T.let([], T::Array[T::Hash[Symbol, Symbol]]) + @completions_and_elisp = T.let(Set.new, T::Set[String]) @package_count = T.let(0, Integer) @install_times = T.let([], T::Array[T::Hash[String, Float]]) end @@ -25,6 +26,11 @@ class Messages @caveats.push(package:, caveats:) end + sig { params(completions_and_elisp: T::Array[String]).void } + def record_completions_and_elisp(completions_and_elisp) + @completions_and_elisp.merge(completions_and_elisp) + end + sig { params(package: String, elapsed_time: Float).void } def package_installed(package, elapsed_time) @package_count += 1 @@ -40,13 +46,14 @@ class Messages sig { params(force: T::Boolean).void } def display_caveats(force: false) return if @package_count.zero? - return if @package_count == 1 && !force - return if @caveats.empty? + return if @caveats.empty? && @completions_and_elisp.empty? - oh1 "Caveats" - @caveats.each do |c| - ohai c[:package], c[:caveats] - end + oh1 "Caveats" unless @completions_and_elisp.empty? + @completions_and_elisp.each { |c| puts c } + return if @package_count == 1 && !force + + oh1 "Caveats" if @completions_and_elisp.empty? + @caveats.each { |c| ohai c[:package], c[:caveats] } end sig { void } diff --git a/Library/Homebrew/extend/on_system.rb b/Library/Homebrew/on_system.rb similarity index 96% rename from Library/Homebrew/extend/on_system.rb rename to Library/Homebrew/on_system.rb index 3d6b97b95f..4e1854ad19 100644 --- a/Library/Homebrew/extend/on_system.rb +++ b/Library/Homebrew/on_system.rb @@ -9,6 +9,13 @@ module OnSystem ALL_OS_OPTIONS = [*MacOSVersion::SYMBOLS.keys, :linux].freeze ALL_OS_ARCH_COMBINATIONS = ALL_OS_OPTIONS.product(ARCH_OPTIONS).freeze + VALID_OS_ARCH_TAGS = ALL_OS_ARCH_COMBINATIONS.filter_map do |os, arch| + tag = Utils::Bottles::Tag.new(system: os, arch:) + next unless tag.valid_combination? + + tag + end.freeze + sig { params(arch: Symbol).returns(T::Boolean) } def self.arch_condition_met?(arch) raise ArgumentError, "Invalid arch condition: #{arch.inspect}" if ARCH_OPTIONS.exclude?(arch) diff --git a/Library/Homebrew/extend/on_system.rbi b/Library/Homebrew/on_system.rbi similarity index 100% rename from Library/Homebrew/extend/on_system.rbi rename to Library/Homebrew/on_system.rbi diff --git a/Library/Homebrew/os/mac/pkgconfig/15/expat.pc b/Library/Homebrew/os/mac/pkgconfig/15/expat.pc index 32ce93ec72..883859e68a 100644 --- a/Library/Homebrew/os/mac/pkgconfig/15/expat.pc +++ b/Library/Homebrew/os/mac/pkgconfig/15/expat.pc @@ -5,7 +5,7 @@ libdir=${exec_prefix}/lib includedir=${prefix}/include Name: expat -Version: 2.6.3 +Version: 2.7.1 Description: expat XML parser URL: https://libexpat.github.io/ Libs: -L${libdir} -lexpat diff --git a/Library/Homebrew/os/mac/pkgconfig/26/bzip2.pc b/Library/Homebrew/os/mac/pkgconfig/26/bzip2.pc new file mode 100644 index 0000000000..aded4844b2 --- /dev/null +++ b/Library/Homebrew/os/mac/pkgconfig/26/bzip2.pc @@ -0,0 +1,12 @@ +homebrew_sdkroot=/Library/Developer/CommandLineTools/SDKs/MacOSX26.sdk +prefix=${homebrew_sdkroot}/usr +exec_prefix=/usr +bindir=${exec_prefix}/bin +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: bzip2 +Description: Lossless, block-sorting data compression +Version: 1.0.8 +Libs: -L${libdir} -lbz2 +Cflags: diff --git a/Library/Homebrew/os/mac/pkgconfig/26/expat.pc b/Library/Homebrew/os/mac/pkgconfig/26/expat.pc new file mode 100644 index 0000000000..8395575305 --- /dev/null +++ b/Library/Homebrew/os/mac/pkgconfig/26/expat.pc @@ -0,0 +1,14 @@ +homebrew_sdkroot=/Library/Developer/CommandLineTools/SDKs/MacOSX26.sdk +prefix=${homebrew_sdkroot}/usr +exec_prefix=/usr +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: expat +Version: 2.7.1 +Description: expat XML parser +URL: https://libexpat.github.io/ +Libs: -L${libdir} -lexpat +Libs.private: +Cflags: +Cflags.private: -DXML_STATIC diff --git a/Library/Homebrew/os/mac/pkgconfig/26/libcurl.pc b/Library/Homebrew/os/mac/pkgconfig/26/libcurl.pc new file mode 100644 index 0000000000..3247df2e81 --- /dev/null +++ b/Library/Homebrew/os/mac/pkgconfig/26/libcurl.pc @@ -0,0 +1,42 @@ +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) Daniel Stenberg, , et al. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at https://curl.se/docs/copyright.html. +# +# You may opt to use, copy, modify, merge, publish, distribute and/or sell +# copies of the Software, and permit persons to whom the Software is +# furnished to do so, under the terms of the COPYING file. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. +# +# SPDX-License-Identifier: curl +# +########################################################################### + +# This should most probably benefit from getting a "Requires:" field added +# dynamically by configure. +# +homebrew_sdkroot=/Library/Developer/CommandLineTools/SDKs/MacOSX26.sdk +prefix=${homebrew_sdkroot}/usr +exec_prefix=/usr +libdir=${exec_prefix}/lib +includedir=${prefix}/include +supported_protocols="DICT FILE FTP FTPS GOPHER GOPHERS HTTP HTTPS IMAP IMAPS IPFS IPNS LDAP LDAPS MQTT POP3 POP3S RTSP SMB SMBS SMTP SMTPS TELNET TFTP" +supported_features="alt-svc AsynchDNS GSS-API HSTS HTTP2 HTTPS-proxy IPv6 Kerberos Largefile libz MultiSSL NTLM SPNEGO SSL threadsafe UnixSockets" + +Name: libcurl +URL: https://curl.se/ +Description: Library to transfer files with ftp, http, etc. +Version: 8.7.1 +Libs: -L${libdir} -lcurl +Libs.private: -lldap -lz +Cflags: diff --git a/Library/Homebrew/os/mac/pkgconfig/26/libedit.pc b/Library/Homebrew/os/mac/pkgconfig/26/libedit.pc new file mode 100644 index 0000000000..a20a0f6a13 --- /dev/null +++ b/Library/Homebrew/os/mac/pkgconfig/26/libedit.pc @@ -0,0 +1,12 @@ +homebrew_sdkroot=/Library/Developer/CommandLineTools/SDKs/MacOSX26.sdk +prefix=${homebrew_sdkroot}/usr +exec_prefix=/usr +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: libedit +Description: command line editor library provides generic line editing, history, and tokenization functions. +Version: 3.0 +Requires: +Libs: -L${libdir} -ledit +Cflags: -I${includedir}/editline diff --git a/Library/Homebrew/os/mac/pkgconfig/26/libexslt.pc b/Library/Homebrew/os/mac/pkgconfig/26/libexslt.pc new file mode 100644 index 0000000000..4da5570157 --- /dev/null +++ b/Library/Homebrew/os/mac/pkgconfig/26/libexslt.pc @@ -0,0 +1,14 @@ +homebrew_sdkroot=/Library/Developer/CommandLineTools/SDKs/MacOSX26.sdk +prefix=${homebrew_sdkroot}/usr +exec_prefix=/usr +libdir=${exec_prefix}/lib +includedir=${prefix}/include + + +Name: libexslt +Version: 0.8.20 +Description: EXSLT Extension library +Requires: libxml-2.0, libxslt +Cflags: +Libs: -L${libdir} -lexslt +Libs.private: diff --git a/Library/Homebrew/os/mac/pkgconfig/26/libffi.pc b/Library/Homebrew/os/mac/pkgconfig/26/libffi.pc new file mode 100644 index 0000000000..2e462cc1eb --- /dev/null +++ b/Library/Homebrew/os/mac/pkgconfig/26/libffi.pc @@ -0,0 +1,12 @@ +homebrew_sdkroot=/Library/Developer/CommandLineTools/SDKs/MacOSX26.sdk +prefix=${homebrew_sdkroot}/usr +exec_prefix=/usr +libdir=${exec_prefix}/lib +toolexeclibdir=${libdir} +includedir=${prefix}/include/ffi + +Name: libffi +Description: Library supporting Foreign Function Interfaces +Version: 3.4-rc1 +Libs: -L${toolexeclibdir} -lffi +Cflags: -I${includedir} diff --git a/Library/Homebrew/os/mac/pkgconfig/26/libxml-2.0.pc b/Library/Homebrew/os/mac/pkgconfig/26/libxml-2.0.pc new file mode 100644 index 0000000000..214be9468b --- /dev/null +++ b/Library/Homebrew/os/mac/pkgconfig/26/libxml-2.0.pc @@ -0,0 +1,14 @@ +homebrew_sdkroot=/Library/Developer/CommandLineTools/SDKs/MacOSX26.sdk +prefix=${homebrew_sdkroot}/usr +exec_prefix=/usr +libdir=${exec_prefix}/lib +includedir=${prefix}/include +modules=1 + +Name: libXML +Version: 2.9.13 +Description: libXML library version2. +Requires: +Libs: -L${libdir} -lxml2 +Libs.private: -lz -lpthread -licucore -lm +Cflags: diff --git a/Library/Homebrew/os/mac/pkgconfig/26/libxslt.pc b/Library/Homebrew/os/mac/pkgconfig/26/libxslt.pc new file mode 100644 index 0000000000..09b03d6fb1 --- /dev/null +++ b/Library/Homebrew/os/mac/pkgconfig/26/libxslt.pc @@ -0,0 +1,14 @@ +homebrew_sdkroot=/Library/Developer/CommandLineTools/SDKs/MacOSX26.sdk +prefix=${homebrew_sdkroot}/usr +exec_prefix=/usr +libdir=${exec_prefix}/lib +includedir=${prefix}/include + + +Name: libxslt +Version: 1.1.35 +Description: XSLT library version 2. +Requires: libxml-2.0 +Cflags: +Libs: -L${libdir} -lxslt +Libs.private: diff --git a/Library/Homebrew/os/mac/pkgconfig/26/ncurses.pc b/Library/Homebrew/os/mac/pkgconfig/26/ncurses.pc new file mode 100644 index 0000000000..05acdc3fbb --- /dev/null +++ b/Library/Homebrew/os/mac/pkgconfig/26/ncurses.pc @@ -0,0 +1,17 @@ +homebrew_sdkroot=/Library/Developer/CommandLineTools/SDKs/MacOSX26.sdk +prefix=${homebrew_sdkroot}/usr +exec_prefix=/usr +libdir=${exec_prefix}/lib +includedir=${prefix}/include +abi_version=5.4 +major_version=6 +version=6.0.20150808 + +Name: ncurses +Description: ncurses 6.0 library +Version: ${version} +URL: http://invisible-island.net/ncurses +Requires.private: +Libs: -L${libdir} -lncurses +Libs.private: +Cflags: -D_DARWIN_C_SOURCE diff --git a/Library/Homebrew/os/mac/pkgconfig/26/ncursesw.pc b/Library/Homebrew/os/mac/pkgconfig/26/ncursesw.pc new file mode 100644 index 0000000000..1456908fa0 --- /dev/null +++ b/Library/Homebrew/os/mac/pkgconfig/26/ncursesw.pc @@ -0,0 +1,17 @@ +homebrew_sdkroot=/Library/Developer/CommandLineTools/SDKs/MacOSX26.sdk +prefix=${homebrew_sdkroot}/usr +exec_prefix=/usr +libdir=${exec_prefix}/lib +includedir=${prefix}/include +abi_version=5.4 +major_version=6 +version=6.0.20150808 + +Name: ncursesw +Description: ncurses 6.0 library +Version: ${version} +URL: http://invisible-island.net/ncurses +Requires.private: +Libs: -L${libdir} -lncurses +Libs.private: +Cflags: -D_DARWIN_C_SOURCE diff --git a/Library/Homebrew/os/mac/pkgconfig/26/sqlite3.pc b/Library/Homebrew/os/mac/pkgconfig/26/sqlite3.pc new file mode 100644 index 0000000000..e7f9019fd5 --- /dev/null +++ b/Library/Homebrew/os/mac/pkgconfig/26/sqlite3.pc @@ -0,0 +1,12 @@ +homebrew_sdkroot=/Library/Developer/CommandLineTools/SDKs/MacOSX26.sdk +prefix=${homebrew_sdkroot}/usr +exec_prefix=/usr +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: SQLite +Description: SQL database engine +Version: 3.48.0 +Libs: -L${libdir} -lsqlite3 +Libs.private: +Cflags: diff --git a/Library/Homebrew/os/mac/pkgconfig/26/uuid.pc b/Library/Homebrew/os/mac/pkgconfig/26/uuid.pc new file mode 100644 index 0000000000..3dc8070ed2 --- /dev/null +++ b/Library/Homebrew/os/mac/pkgconfig/26/uuid.pc @@ -0,0 +1,14 @@ +homebrew_sdkroot=/Library/Developer/CommandLineTools/SDKs/MacOSX26.sdk +prefix=${homebrew_sdkroot}/usr +exec_prefix=/usr +libdir=${exec_prefix}/lib +sharedlibdir=${libdir} +includedir=${prefix}/include/uuid + +Name: uuid +Description: Universally unique id library +Version: 1.0 + +Requires: +Libs: +Cflags: -I${includedir} diff --git a/Library/Homebrew/os/mac/pkgconfig/26/zlib.pc b/Library/Homebrew/os/mac/pkgconfig/26/zlib.pc new file mode 100644 index 0000000000..a86f93bc1b --- /dev/null +++ b/Library/Homebrew/os/mac/pkgconfig/26/zlib.pc @@ -0,0 +1,14 @@ +homebrew_sdkroot=/Library/Developer/CommandLineTools/SDKs/MacOSX26.sdk +prefix=${homebrew_sdkroot}/usr +exec_prefix=/usr +libdir=${exec_prefix}/lib +sharedlibdir=${libdir} +includedir=${prefix}/include + +Name: zlib +Description: zlib compression library +Version: 1.2.12 + +Requires: +Libs: -L${libdir} -L${sharedlibdir} -lz +Cflags: diff --git a/Library/Homebrew/os/mac/xcode.rb b/Library/Homebrew/os/mac/xcode.rb index 5af295fcf6..cec906f25e 100644 --- a/Library/Homebrew/os/mac/xcode.rb +++ b/Library/Homebrew/os/mac/xcode.rb @@ -15,10 +15,10 @@ module OS # This may be a beta version for a beta macOS. sig { params(macos: MacOSVersion).returns(String) } def self.latest_version(macos: MacOS.version) - latest_stable = "15.4" + macos = macos.strip_patch case macos - when "15" then "16.0" - when "14" then latest_stable + when "15" then "16.4" + when "14" then "16.2" when "13" then "15.2" when "12" then "14.2" when "11" then "13.2.1" @@ -28,10 +28,10 @@ module OS when "10.12" then "9.2" when "10.11" then "8.2.1" else - raise "macOS '#{MacOS.version}' is invalid" unless OS::Mac.version.prerelease? + raise "macOS '#{macos}' is invalid" unless macos.prerelease? - # Default to newest known version of Xcode for unreleased macOS versions. - latest_stable + # Assume matching yearly Xcode release + "#{macos}.0" end end @@ -41,7 +41,8 @@ module OS # also in beta). sig { returns(String) } def self.minimum_version - case MacOS.version + macos = MacOS.version + case macos when "15" then "16.0" when "14" then "15.0" when "13" then "14.1" @@ -51,7 +52,9 @@ module OS when "10.14" then "10.2" when "10.13" then "9.0" when "10.12" then "8.0" - else "7.3" + when "10.11" then "7.3" + else + "#{macos}.0" end end @@ -225,10 +228,8 @@ module OS detect_version_from_clang_version end - sig { returns(String) } - def self.detect_version_from_clang_version - version = ::DevelopmentTools.clang_version - + sig { params(version: ::Version).returns(String) } + def self.detect_version_from_clang_version(version = ::DevelopmentTools.clang_version) return "dunno" if version.null? # This logic provides a fake Xcode version based on the @@ -255,8 +256,9 @@ module OS when "13.1.6" then "13.4.1" when "14.0.0" then "14.2" when "14.0.3" then "14.3.1" - when "16.0.0" then "16.0" - else "15.4" + when "15.0.0" then "15.4" + when "16.0.0" then "16.2" + else "26.0" end end @@ -355,8 +357,9 @@ module OS sig { returns(String) } def self.latest_clang_version case MacOS.version - when "15" then "1600.0.20.10" - when "14" then "1500.3.9.4" + when "26" then "1700.3.9.908" + when "15" then "1700.0.13.5" + when "14" then "1600.0.26.6" when "13" then "1500.1.0.2.5" when "12" then "1400.0.29.202" when "11" then "1300.0.29.30" @@ -373,7 +376,8 @@ module OS # that macOS version. sig { returns(String) } def self.minimum_version - case MacOS.version + macos = MacOS.version + case macos when "15" then "16.0.0" when "14" then "15.0.0" when "13" then "14.0.0" @@ -383,7 +387,9 @@ module OS when "10.14" then "10.0.0" when "10.13" then "9.0.0" when "10.12" then "8.0.0" - else "7.3.0" + when "10.11" then "7.3.0" + else + "#{macos}.0.0" end end @@ -410,7 +416,10 @@ module OS sig { returns(T.nilable(String)) } def self.detect_version_from_clang_version - detect_clang_version&.sub(/^(\d+)0(\d)\./, "\\1.\\2.") + clang_version = detect_clang_version + return if clang_version.nil? + + MacOS::Xcode.detect_version_from_clang_version(Version.new(clang_version)) end # Version string (a pretty long one) of the CLT package. diff --git a/Library/Homebrew/extend/io.rb b/Library/Homebrew/readline_nonblock.rb similarity index 60% rename from Library/Homebrew/extend/io.rb rename to Library/Homebrew/readline_nonblock.rb index a6eb7d4b70..7888b46399 100644 --- a/Library/Homebrew/extend/io.rb +++ b/Library/Homebrew/readline_nonblock.rb @@ -1,17 +1,17 @@ # typed: strict # frozen_string_literal: true -class IO - sig { params(sep: String).returns(String) } - def readline_nonblock(sep = $INPUT_RECORD_SEPARATOR) +class ReadlineNonblock + sig { params(io: IO).returns(String) } + def self.read(io) line = +"" buffer = +"" begin loop do - break if buffer == sep + break if buffer == $INPUT_RECORD_SEPARATOR - read_nonblock(1, buffer) + io.read_nonblock(1, buffer) line.concat(buffer) end diff --git a/Library/Homebrew/resource.rb b/Library/Homebrew/resource.rb index 2b37c2ec43..a774f659df 100644 --- a/Library/Homebrew/resource.rb +++ b/Library/Homebrew/resource.rb @@ -4,7 +4,7 @@ require "downloadable" require "mktemp" require "livecheck" -require "extend/on_system" +require "on_system" # Resource is the fundamental representation of an external resource. The # primary formula download, along with other declared resources, are instances diff --git a/Library/Homebrew/resource_auditor.rb b/Library/Homebrew/resource_auditor.rb index 8e8a856d72..77216138e6 100644 --- a/Library/Homebrew/resource_auditor.rb +++ b/Library/Homebrew/resource_auditor.rb @@ -63,7 +63,7 @@ module Homebrew url_strategy = DownloadStrategyDetector.detect(url) if (using == :git || url_strategy == GitDownloadStrategy) && specs[:tag] && !specs[:revision] - problem "Git should specify :revision when a :tag is specified." + problem "Git should specify `revision:` when a `tag:` is specified." end return unless using @@ -71,7 +71,7 @@ module Homebrew if using == :cvs mod = specs[:module] - problem "Redundant :module value in URL" if mod == name + problem "Redundant `module:` value in URL" if mod == name if url.match?(%r{:[^/]+$}) mod = url.split(":").last @@ -79,14 +79,14 @@ module Homebrew if mod == name problem "Redundant CVS module appended to URL" else - problem "Specify CVS module as `:module => \"#{mod}\"` instead of appending it to the URL" + problem "Specify CVS module as `module: \"#{mod}\"` instead of appending it to the URL" end end end return if url_strategy != DownloadStrategyDetector.detect("", using) - problem "Redundant :using value in URL" + problem "Redundant `using:` value in URL" end def audit_checksum @@ -125,7 +125,7 @@ module Homebrew return if name.casecmp(pypi_package_name).zero? - problem "resource name should be `#{pypi_package_name}` to match the PyPI package name" + problem "`resource` name should be '#{pypi_package_name}' to match the PyPI package name" end def audit_urls @@ -166,12 +166,12 @@ module Homebrew remote_exists = Utils::Git.remote_exists?(url) attempts += 1 end - problem "The URL #{url} is not a valid git URL" unless remote_exists + problem "The URL #{url} is not a valid Git URL" unless remote_exists elsif strategy <= SubversionDownloadStrategy next unless DevelopmentTools.subversion_handles_most_https_certificates? next unless Utils::Svn.available? - problem "The URL #{url} is not a valid svn URL" unless Utils::Svn.remote_exists? url + problem "The URL #{url} is not a valid SVN URL" unless Utils::Svn.remote_exists? url end end end @@ -188,7 +188,7 @@ module Homebrew .match(%r{ref: refs/heads/(.*?)\s+HEAD})&.to_a&.second return if branch.blank? || branch == specs[:branch] - problem "Use `branch: \"#{branch}\"` to specify the default branch" + problem "Specify the default branch as `branch: \"#{branch}\"`" end def problem(text) diff --git a/Library/Homebrew/rubocops/cask/no_overrides.rb b/Library/Homebrew/rubocops/cask/no_overrides.rb index 6f313f41ed..1eeb1e1df8 100644 --- a/Library/Homebrew/rubocops/cask/no_overrides.rb +++ b/Library/Homebrew/rubocops/cask/no_overrides.rb @@ -11,14 +11,14 @@ module RuboCop # TODO: Update this list if new stanzas are added to `Cask::DSL` that call `set_unique_stanza`. OVERRIDABLE_METHODS = [ :appcast, :arch, :auto_updates, :conflicts_with, :container, - :desc, :homepage, :sha256, :url, :version + :desc, :homepage, :os, :sha256, :url, :version ].freeze - MESSAGE = "Do not use a top-level `%s` stanza as the default. " \ - "Add it to an `on_{system}` block instead. " \ - "Use `:or_older` or `:or_newer` to specify a range of macOS versions." sig { override.params(cask_block: RuboCop::Cask::AST::CaskBlock).void } def on_cask(cask_block) + message = "Do not use a top-level `%s` stanza as the default. " \ + "Add it to an `on_{system}` block instead. " \ + "Use `:or_older` or `:or_newer` to specify a range of macOS versions." cask_stanzas = cask_block.toplevel_stanzas return if (on_blocks = on_system_methods(cask_stanzas)).none? @@ -31,12 +31,14 @@ module RuboCop # Skip if the stanza outside of a block is not also in an `on_*` block. next unless stanzas_in_blocks.include?(stanza.stanza_name) - add_offense(stanza.source_range, message: format(MESSAGE, stanza: stanza.stanza_name)) + add_offense(stanza.source_range, message: format(message, stanza: stanza.stanza_name)) end end sig { params(on_system: T::Array[RuboCop::Cask::AST::Stanza]).returns(T::Set[Symbol]) } def on_system_stanzas(on_system) + message = "Do not use a `depends_on macos:` stanza inside an `on_{system}` block. " \ + "Add it once to specify the oldest macOS supported by any version in the cask." names = T.let(Set.new, T::Set[Symbol]) method_nodes = on_system.map(&:method_node) method_nodes.select(&:block_type?).each do |node| @@ -51,6 +53,14 @@ module RuboCop end next if RuboCop::Cask::Constants::ON_SYSTEM_METHODS.include?(send_node.method_name) + if send_node.method_name == :depends_on && + send_node.arguments.first.pairs.any? { |a| a.key.value == :macos } && + OnSystemConditionalsHelper::ON_SYSTEM_OPTIONS.map do |m| + :"on_#{m}" + end.include?(T.cast(node, RuboCop::AST::BlockNode).method_name) + add_offense(send_node.source_range, message:) + end + names.add(send_node.method_name) end end diff --git a/Library/Homebrew/rubocops/cask/url.rb b/Library/Homebrew/rubocops/cask/url.rb index a62f5e884a..54ffcd1e84 100644 --- a/Library/Homebrew/rubocops/cask/url.rb +++ b/Library/Homebrew/rubocops/cask/url.rb @@ -41,6 +41,15 @@ module RuboCop return unless hash_node.hash_type? + unless stanza_node.source.match?(/",\n *\w+:/) + add_offense( + stanza_node.source_range, + message: "Keyword URL parameter should be on a new indented line.", + ) do |corrector| + corrector.replace(stanza_node.source_range, stanza_node.source.gsub(/",\s*/, "\",\n ")) + end + end + hash_node.each_pair do |key_node, value_node| next if key_node.source != "verified" next unless value_node.str_type? diff --git a/Library/Homebrew/rubocops/caveats.rb b/Library/Homebrew/rubocops/caveats.rb index 99ae5b826b..8d228e10fa 100644 --- a/Library/Homebrew/rubocops/caveats.rb +++ b/Library/Homebrew/rubocops/caveats.rb @@ -30,7 +30,7 @@ module RuboCop def audit_formula(_formula_nodes) caveats_strings.each do |n| if regex_match_group(n, /\bsetuid\b/i) - problem "Don't recommend `setuid` in the caveats, suggest `sudo` instead." + problem "Instead of recommending `setuid` in the caveats, suggest `sudo`." end problem "Don't use ANSI escape codes in the caveats." if regex_match_group(n, /\e/) diff --git a/Library/Homebrew/rubocops/checksum.rb b/Library/Homebrew/rubocops/checksum.rb index 44d749db0d..e2040ec606 100644 --- a/Library/Homebrew/rubocops/checksum.rb +++ b/Library/Homebrew/rubocops/checksum.rb @@ -28,17 +28,17 @@ module RuboCop return if checksum.nil? if regex_match_group(checksum, /^$/) - problem "sha256 is empty" + problem "`sha256` is empty" return end if string_content(checksum).size != 64 && regex_match_group(checksum, /^\w*$/) - problem "sha256 should be 64 characters" + problem "`sha256` should be 64 characters" end return unless regex_match_group(checksum, /[^a-f0-9]+/i) - add_offense(T.must(@offensive_source_range), message: "sha256 contains invalid characters") + add_offense(T.must(@offensive_source_range), message: "`sha256` contains invalid characters") end end @@ -54,7 +54,7 @@ module RuboCop next if checksum.nil? next unless regex_match_group(checksum, /[A-F]+/) - add_offense(@offensive_source_range, message: "sha256 should be lowercase") do |corrector| + add_offense(@offensive_source_range, message: "`sha256` should be lowercase") do |corrector| correction = T.must(@offensive_node).source.downcase corrector.insert_before(T.must(@offensive_node).source_range, correction) corrector.remove(T.must(@offensive_node).source_range) diff --git a/Library/Homebrew/rubocops/class.rb b/Library/Homebrew/rubocops/class.rb index 2088ef1a59..d2b46d8faa 100644 --- a/Library/Homebrew/rubocops/class.rb +++ b/Library/Homebrew/rubocops/class.rb @@ -23,7 +23,7 @@ module RuboCop parent_class = class_name(parent_class_node) return unless DEPRECATED_CLASSES.include?(parent_class) - problem "#{parent_class} is deprecated, use Formula instead" do |corrector| + problem "`#{parent_class}` is deprecated, use `Formula` instead" do |corrector| corrector.replace(parent_class_node.source_range, "Formula") end end @@ -49,14 +49,14 @@ module RuboCop p1, p2 = params if (match = string_content(p1).match(%r{(/usr/local/(s?bin))})) offending_node(p1) - problem "use \#{#{match[2]}} instead of #{match[1]} in #{node}" do |corrector| + problem "Use `\#{#{match[2]}}` instead of `#{match[1]}` in `#{node}`" do |corrector| corrector.replace(p1.source_range, p1.source.sub(match[1], "\#{#{match[2]}}")) end end if node == :shell_output && node_equals?(p2, 0) offending_node(p2) - problem "Passing 0 to shell_output() is redundant" do |corrector| + problem "Passing 0 to `shell_output` is redundant" do |corrector| corrector.remove(range_with_surrounding_comma(range_with_surrounding_space(range: p2.source_range, side: :left))) end diff --git a/Library/Homebrew/rubocops/components_order.rb b/Library/Homebrew/rubocops/components_order.rb index 14ccb3973e..7b6fc8c8ba 100644 --- a/Library/Homebrew/rubocops/components_order.rb +++ b/Library/Homebrew/rubocops/components_order.rb @@ -39,7 +39,7 @@ module RuboCop if on_method_blocks.length > 1 @offensive_node = on_method_blocks.second - problem "there can only be one `#{on_method}` block in a formula." + problem "There can only be one `#{on_method}` block in a formula." end check_on_system_block_content(component_precedence_list, on_method_blocks.first) @@ -112,7 +112,7 @@ module RuboCop on_system_blocks.each do |on_method, blocks| if blocks.length > 1 - problem "there can only be one `#{on_method}` block in a resource block." + problem "There can only be one `#{on_method}` block in a resource block." next end end diff --git a/Library/Homebrew/rubocops/components_redundancy.rb b/Library/Homebrew/rubocops/components_redundancy.rb index 50557ab187..724f0af7bf 100644 --- a/Library/Homebrew/rubocops/components_redundancy.rb +++ b/Library/Homebrew/rubocops/components_redundancy.rb @@ -32,7 +32,7 @@ module RuboCop url_args = arg.keys.each.map(&:value) if method_called?(body_node, :sha256) && url_args.include?(:tag) && url_args.include?(:revision) - problem "Do not use both sha256 and tag/revision." + problem "Do not use both `sha256` and `tag:`/`revision:`." end end end diff --git a/Library/Homebrew/rubocops/dependency_order.rb b/Library/Homebrew/rubocops/dependency_order.rb index 3f9a343d6d..92ea918d88 100644 --- a/Library/Homebrew/rubocops/dependency_order.rb +++ b/Library/Homebrew/rubocops/dependency_order.rb @@ -108,8 +108,8 @@ module RuboCop offending_node(node_1) - problem "dependency \"#{dependency_name(node_1)}\" (line #{l1}) should be put before dependency " \ - "\"#{dependency_name(node_2)}\" (line #{l2})" do |corrector| + problem "`dependency \"#{dependency_name(node_1)}\"` (line #{l1}) should be put before " \ + "`dependency \"#{dependency_name(node_2)}\"` (line #{l2})" do |corrector| indentation = " " * (start_column(node_2) - line_start_column(node_2)) line_breaks = "\n" corrector.insert_before(node_2.source_range, diff --git a/Library/Homebrew/rubocops/lines.rb b/Library/Homebrew/rubocops/lines.rb index 698aee4fc1..c3b0c578e5 100644 --- a/Library/Homebrew/rubocops/lines.rb +++ b/Library/Homebrew/rubocops/lines.rb @@ -165,41 +165,42 @@ module RuboCop next unless unless_modifier?(method.parent) correct = method.source.gsub("out?", "?") - problem "Use if #{correct} instead of unless #{method.source}" + problem "Use `if #{correct}` instead of `unless #{method.source}`" end find_instance_method_call(body_node, :build, :with?) do |method| next unless unless_modifier?(method.parent) correct = method.source.gsub("?", "out?") - problem "Use if #{correct} instead of unless #{method.source}" + problem "Use `if #{correct}` instead of `unless #{method.source}`" end find_instance_method_call(body_node, :build, :with?) do |method| next unless expression_negated?(method) - problem "Don't negate 'build.with?': use 'build.without?'" + problem "Instead of negating `build.with?`, use `build.without?`" end find_instance_method_call(body_node, :build, :without?) do |method| next unless expression_negated?(method) - problem "Don't negate 'build.without?': use 'build.with?'" + problem "Instead of negating `build.without?`, use `build.with?`" end find_instance_method_call(body_node, :build, :without?) do |method| arg = parameters(method).first next unless (match = regex_match_group(arg, /^-?-?without-(.*)/)) - problem "Don't duplicate 'without': " \ - "Use `build.without? \"#{match[1]}\"` to check for \"--without-#{match[1]}\"" + problem "Instead of duplicating `without`, " \ + "use `build.without? \"#{match[1]}\"` to check for \"--without-#{match[1]}\"" end find_instance_method_call(body_node, :build, :with?) do |method| arg = parameters(method).first next unless (match = regex_match_group(arg, /^-?-?with-(.*)/)) - problem "Don't duplicate 'with': Use `build.with? \"#{match[1]}\"` to check for \"--with-#{match[1]}\"" + problem "Instead of duplicating `with`, " \ + "use `build.with? \"#{match[1]}\"` to check for '--with-#{match[1]}'" end find_instance_method_call(body_node, :build, :include?) do @@ -234,8 +235,8 @@ module RuboCop return if formula_tap != "homebrew-core" find_method_with_args(body_node, :depends_on, "mpich") do - problem "Formulae in homebrew/core should use 'depends_on \"open-mpi\"' " \ - "instead of '#{T.must(@offensive_node).source}'." do |corrector| + problem "Formulae in homebrew/core should use `depends_on \"open-mpi\"` " \ + "instead of `#{T.must(@offensive_node).source}`." do |corrector| corrector.replace(T.must(@offensive_node).source_range, "depends_on \"open-mpi\"") end end @@ -252,15 +253,15 @@ module RuboCop return if (body_node = formula_nodes.body_node).nil? find_method_with_args(body_node, :local_npm_install_args) do - problem "Use 'std_npm_args' instead of '#{T.cast(@offensive_node, - RuboCop::AST::SendNode).method_name}'." do |corrector| + problem "Use `std_npm_args` instead of `#{T.cast(@offensive_node, + RuboCop::AST::SendNode).method_name}`." do |corrector| corrector.replace(T.must(@offensive_node).source_range, "std_npm_args(prefix: false)") end end find_method_with_args(body_node, :std_npm_install_args) do |method| - problem "Use 'std_npm_args' instead of '#{T.cast(@offensive_node, - RuboCop::AST::SendNode).method_name}'." do |corrector| + problem "Use `std_npm_args` instead of `#{T.cast(@offensive_node, + RuboCop::AST::SendNode).method_name}`." do |corrector| if (param = parameters(method).first.source) == "libexec" corrector.replace(T.must(@offensive_node).source_range, "std_npm_args") else @@ -293,8 +294,8 @@ module RuboCop return if formula_tap != "homebrew-core" find_method_with_args(body_node, :depends_on, "quictls") do - problem "Formulae in homebrew/core should use 'depends_on \"openssl@3\"' " \ - "instead of '#{T.must(@offensive_node).source}'." do |corrector| + problem "Formulae in homebrew/core should use `depends_on \"openssl@3\"` " \ + "instead of `#{T.must(@offensive_node).source}`." do |corrector| corrector.replace(T.must(@offensive_node).source_range, "depends_on \"openssl@3\"") end end @@ -311,7 +312,7 @@ module RuboCop return if formula_tap != "homebrew-core" return unless depends_on?("pyoxidizer") - problem "Formulae in homebrew/core should not use '#{T.must(@offensive_node).source}'." + problem "Formulae in homebrew/core should not use `#{T.must(@offensive_node).source}`." end end @@ -505,7 +506,7 @@ module RuboCop end end - # This cop makes sure the `MacOS` module is not used in Linux-facing formula code + # This cop makes sure the `MacOS` module is not used in Linux-facing formula code. class MacOSOnLinux < FormulaCop include OnSystemConditionalsHelper @@ -676,7 +677,7 @@ module RuboCop # FileUtils is included in Formula # encfs modifies a file with this name, so check for some leading characters find_instance_method_call(body_node, "FileUtils", nil) do |method_node| - problem "Don't need 'FileUtils.' before #{method_node.method_name}" + problem "No need for `FileUtils.` before `#{method_node.method_name}`" end # Check for long inreplace block vars @@ -684,45 +685,41 @@ module RuboCop block_arg = node.arguments.children.first next if block_arg.source.size <= 1 - problem "\"inreplace do |s|\" is preferred over \"|#{block_arg.source}|\"." + problem "`inreplace do |s|` is preferred over `|#{block_arg.source}|`." end [:rebuild, :version_scheme].each do |method_name| find_method_with_args(body_node, method_name, 0) do - problem "'#{method_name} 0' should be removed" + problem "`#{method_name} 0` should be removed" end end find_instance_call(body_node, "ARGV") do |_method_node| - problem "Use build instead of ARGV to check options" + problem "Use `build.with?` or `build.without?` instead of `ARGV` to check options" end find_instance_method_call(body_node, :man, :+) do |method| next unless (match = regex_match_group(parameters(method).first, /^man[1-8]$/)) - problem "\"#{method.source}\" should be \"#{match[0]}\"" + problem "`#{method.source}` should be `#{match[0]}`" end # Avoid hard-coding compilers find_every_method_call_by_name(body_node, :system).each do |method| - next if @formula_name == "bazel" # TODO: Remove shim bypass in bazel. - param = parameters(method).first if (match = regex_match_group(param, %r{^(/usr/bin/)?(gcc|clang|cc|c[89]9)(\s|$)})) - problem "Use \"\#{ENV.cc}\" instead of hard-coding \"#{match[2]}\"" + problem "Use `\#{ENV.cc}` instead of hard-coding `#{match[2]}`" elsif (match = regex_match_group(param, %r{^(/usr/bin/)?((g|clang|c)\+\+)(\s|$)})) - problem "Use \"\#{ENV.cxx}\" instead of hard-coding \"#{match[2]}\"" + problem "Use `\#{ENV.cxx}` instead of hard-coding `#{match[2]}`" end end find_instance_method_call(body_node, "ENV", :[]=) do |method| - next if @formula_name == "bazel" # TODO: Remove shim bypass in bazel. - param = parameters(method)[1] if (match = regex_match_group(param, %r{^(/usr/bin/)?(gcc|clang|cc|c[89]9)(\s|$)})) - problem "Use \"\#{ENV.cc}\" instead of hard-coding \"#{match[2]}\"" + problem "Use `\#{ENV.cc}` instead of hard-coding `#{match[2]}`" elsif (match = regex_match_group(param, %r{^(/usr/bin/)?((g|clang|c)\+\+)(\s|$)})) - problem "Use \"\#{ENV.cxx}\" instead of hard-coding \"#{match[2]}\"" + problem "Use `\#{ENV.cxx}` instead of hard-coding `#{match[2]}`" end end @@ -730,18 +727,18 @@ module RuboCop formula_path_strings(body_node, :share) do |p| next unless (match = regex_match_group(p, %r{^(/(man))/?})) - problem "\"\#{share}#{match[1]}\" should be \"\#{#{match[2]}}\"" + problem "`\#{share}#{match[1]}` should be `\#{#{match[2]}}`" end formula_path_strings(body_node, :prefix) do |p| if (match = regex_match_group(p, %r{^(/share/(info|man))$})) - problem ['"#', "{prefix}", match[1], '" should be "#{', match[2], '}"'].join + problem ["`#", "{prefix}", match[1], '` should be `#{', match[2], "}`"].join end if (match = regex_match_group(p, %r{^((/share/man/)(man[1-8]))})) - problem ['"#', "{prefix}", match[1], '" should be "#{', match[3], '}"'].join + problem ["`#", "{prefix}", match[1], '` should be `#{', match[3], "}`"].join end if (match = regex_match_group(p, %r{^(/(bin|include|libexec|lib|sbin|share|Frameworks))}i)) - problem ['"#', "{prefix}", match[1], '" should be "#{', match[2].downcase, '}"'].join + problem ["`#", "{prefix}", match[1], '` should be `#{', match[2].downcase, "}`"].join end end @@ -750,13 +747,13 @@ module RuboCop next if key.nil? || value.nil? next unless (match = regex_match_group(value, /^(lua|perl|python|ruby)(\d*)/)) - problem "#{match[1]} modules should be vendored rather than use deprecated `#{method.source}`" + problem "#{match[1]} modules should be vendored rather than using deprecated `#{method.source}`" end find_every_method_call_by_name(body_node, :system).each do |method| next unless (match = regex_match_group(parameters(method).first, /^(env|export)(\s+)?/)) - problem "Use ENV instead of invoking '#{match[1]}' to modify the environment" + problem "Use `ENV` instead of invoking `#{match[1]}` to modify the environment" end find_every_method_call_by_name(body_node, :depends_on).each do |method| @@ -768,7 +765,7 @@ module RuboCop find_strings(option).each do |dependency| next unless (match = regex_match_group(dependency, /(with(out)?-\w+|c\+\+11)/)) - problem "Dependency #{string_content(dep)} should not use option #{match[0]}" + problem "Dependency '#{string_content(dep)}' should not use option `#{match[0]}`" end end end @@ -776,21 +773,21 @@ module RuboCop find_instance_method_call(body_node, :version, :==) do |method| next unless parameters_passed?(method, ["HEAD"]) - problem "Use 'build.head?' instead of inspecting 'version'" + problem "Use `build.head?` instead of inspecting `version`" end find_instance_method_call(body_node, "ARGV", :include?) do |method| next unless parameters_passed?(method, ["--HEAD"]) - problem "Use \"if build.head?\" instead" + problem "Use `if build.head?` instead" end find_const(body_node, "MACOS_VERSION") do - problem "Use MacOS.version instead of MACOS_VERSION" + problem "Use `MacOS.version` instead of `MACOS_VERSION`" end find_const(body_node, "MACOS_FULL_VERSION") do - problem "Use MacOS.full_version instead of MACOS_FULL_VERSION" + problem "Use `MacOS.full_version` instead of `MACOS_FULL_VERSION`" end conditional_dependencies(body_node) do |node, method, param, dep_node| @@ -799,30 +796,30 @@ module RuboCop if (method == :include? && regex_match_group(param, /^with-#{dep}$/)) || (method == :with? && regex_match_group(param, /^#{dep}$/)) offending_node(dep_node.parent) - problem "Replace #{node.source} with #{dep_node.parent.source} => :optional" + problem "Replace `#{node.source}` with `#{dep_node.parent.source} => :optional`" end elsif node.unless? if (method == :include? && regex_match_group(param, /^without-#{dep}$/)) || (method == :without? && regex_match_group(param, /^#{dep}$/)) offending_node(dep_node.parent) - problem "Replace #{node.source} with #{dep_node.parent.source} => :recommended" + problem "Replace `#{node.source}` with `#{dep_node.parent.source} => :recommended`" end end end find_method_with_args(body_node, :fails_with, :llvm) do - problem "'fails_with :llvm' is now a no-op so should be removed" + problem "`fails_with :llvm` is now a no-op and should be removed" end find_method_with_args(body_node, :needs, :openmp) do - problem "'needs :openmp' should be replaced with 'depends_on \"gcc\"'" + problem "`needs :openmp` should be replaced with `depends_on \"gcc\"`" end find_method_with_args(body_node, :system, /^(otool|install_name_tool|lipo)/) do problem "Use ruby-macho instead of calling #{T.must(@offensive_node).source}" end - problem "Use new-style test definitions (test do)" if find_method_def(body_node, :test) + problem "Use new-style test definitions (`test do`)" if find_method_def(body_node, :test) find_method_with_args(body_node, :skip_clean, :all) do problem "`skip_clean :all` is deprecated; brew no longer strips symbols. " \ @@ -830,7 +827,7 @@ module RuboCop end if find_method_def(processed_source.ast) - problem "Define method #{method_name(@offensive_node)} in the class body, not at the top-level" + problem "Define method `#{method_name(@offensive_node)}` in the class body, not at the top-level" end find_instance_method_call(body_node, :build, :universal?) do @@ -849,7 +846,7 @@ module RuboCop next if tap_style_exception? :runtime_cpu_detection_allowlist problem "Formulae should be verified as having support for runtime hardware detection before " \ - "using ENV.runtime_cpu_detection." + "using `ENV.runtime_cpu_detection`." end find_every_method_call_by_name(body_node, :depends_on).each do |method| @@ -864,7 +861,7 @@ module RuboCop param = parameters(method).first next unless node_equals?(param, "CI") - problem 'Don\'t use ENV["CI"] for Homebrew CI checks.' + problem 'Don\'t use `ENV["CI"]` for Homebrew CI checks.' end find_instance_method_call(body_node, "Dir", :[]) do |method| @@ -874,7 +871,7 @@ module RuboCop next unless path.str_type? next unless (match = regex_match_group(path, /^[^*{},]+$/)) - problem "Dir([\"#{string_content(path)}\"]) is unnecessary; just use \"#{match[0]}\"" + problem "`Dir([\"#{string_content(path)}\"])` is unnecessary; just use `#{match[0]}`" end fileutils_methods = Regexp.new( @@ -946,7 +943,7 @@ module RuboCop end end - # This cop ensures that new formulae depending on removed Requirements are not used + # This cop ensures that new formulae depending on removed Requirements are not used. class Requirements < FormulaCop sig { override.params(_formula_nodes: FormulaNodes).void } def audit_formula(_formula_nodes) @@ -969,16 +966,16 @@ module RuboCop return if formula_tap != "homebrew-core" find_method_with_args(body_node, :depends_on, "rustup") do - problem "Formulae in homebrew/core should use 'depends_on \"rust\"' " \ - "instead of '#{T.must(@offensive_node).source}'." do |corrector| + problem "Formulae in homebrew/core should use `depends_on \"rust\"` " \ + "instead of `#{T.must(@offensive_node).source}`." do |corrector| corrector.replace(T.must(@offensive_node).source_range, "depends_on \"rust\"") end end [:build, [:build, :test], [:test, :build]].each do |type| find_method_with_args(body_node, :depends_on, "rustup" => type) do - problem "Formulae in homebrew/core should use 'depends_on \"rust\" => #{type}' " \ - "instead of '#{T.must(@offensive_node).source}'." do |corrector| + problem "Formulae in homebrew/core should use `depends_on \"rust\" => #{type}` " \ + "instead of `#{T.must(@offensive_node).source}`." do |corrector| corrector.replace(T.must(@offensive_node).source_range, "depends_on \"rust\" => #{type}") end end diff --git a/Library/Homebrew/rubocops/options.rb b/Library/Homebrew/rubocops/options.rb index 8958b94dd8..b92fca4bbe 100644 --- a/Library/Homebrew/rubocops/options.rb +++ b/Library/Homebrew/rubocops/options.rb @@ -30,7 +30,7 @@ module RuboCop if !/with(out)?-/.match?(option) && option != "cxx11" && option != "universal" - problem "Options should begin with with/without. " \ + problem "Options should begin with `with` or `without`. " \ "Migrate '--#{option}' with `deprecated_option`." end diff --git a/Library/Homebrew/rubocops/patches.rb b/Library/Homebrew/rubocops/patches.rb index 4cc7a74066..5fd3a72741 100644 --- a/Library/Homebrew/rubocops/patches.rb +++ b/Library/Homebrew/rubocops/patches.rb @@ -30,14 +30,14 @@ module RuboCop if inline_patches.empty? && patch_end? offending_patch_end_node(node) - add_offense(@offense_source_range, message: "patch is missing 'DATA'") + add_offense(@offense_source_range, message: "Patch is missing `patch :DATA`") end patches_node = find_method_def(body_node, :patches) return if patches_node.nil? legacy_patches = find_strings(patches_node) - problem "Use the patch DSL instead of defining a 'patches' method" + problem "Use the `patch` DSL instead of defining a `patches` method" legacy_patches.each { |p| patch_problems(p) } end @@ -63,7 +63,7 @@ module RuboCop if regex_match_group(patch_url_node, bitbucket_regex) owner, repo, commit = patch_url_node.source.match(bitbucket_regex).captures correct_url = "https://api.bitbucket.org/2.0/repositories/#{owner}/#{repo}/diff/#{commit}" - problem "Bitbucket patches should use the api url: #{correct_url}" do |corrector| + problem "Bitbucket patches should use the API URL: #{correct_url}" do |corrector| corrector.replace(patch_url_node.source_range, %Q("#{correct_url}")) end end @@ -118,7 +118,7 @@ module RuboCop return if !patch_data?(patch) || patch_end? offending_node(patch) - problem "patch is missing '__END__'" + problem "Patch is missing `__END__`" end def_node_search :patch_data?, <<~AST diff --git a/Library/Homebrew/rubocops/shared/desc_helper.rb b/Library/Homebrew/rubocops/shared/desc_helper.rb index 6e458f1378..cfab0c1978 100644 --- a/Library/Homebrew/rubocops/shared/desc_helper.rb +++ b/Library/Homebrew/rubocops/shared/desc_helper.rb @@ -21,7 +21,7 @@ module RuboCop def audit_desc(type, name, desc_call) # Check if a desc is present. if desc_call.nil? - problem "#{type.to_s.capitalize} should have a desc (Description)." + problem "#{type.to_s.capitalize} should have a `desc` (description)." return end @@ -32,7 +32,7 @@ module RuboCop # Check if the desc is empty. desc_length = string_content(desc).length if desc_length.zero? - problem "The desc (description) should not be an empty string." + problem "The `desc` (description) should not be an empty string." return end diff --git a/Library/Homebrew/rubocops/shared/homepage_helper.rb b/Library/Homebrew/rubocops/shared/homepage_helper.rb index f5f53d3544..2ecef2bec9 100644 --- a/Library/Homebrew/rubocops/shared/homepage_helper.rb +++ b/Library/Homebrew/rubocops/shared/homepage_helper.rb @@ -19,10 +19,10 @@ module RuboCop def audit_homepage(type, content, homepage_node, homepage_parameter_node) @offensive_node = T.let(homepage_node, T.nilable(RuboCop::AST::Node)) - problem "#{type.to_s.capitalize} should have a homepage." if content.empty? + problem "#{type.to_s.capitalize} should have a `homepage`." if content.empty? @offensive_node = homepage_parameter_node - problem "The homepage should start with http or https." unless content.match?(%r{^https?://}) + problem "The `homepage` should start with http or https." unless content.match?(%r{^https?://}) case content # Freedesktop is complicated to handle - It has SSL/TLS, but only on certain subdomains. @@ -31,10 +31,9 @@ module RuboCop # "Software" is redirected to https://wiki.freedesktop.org/www/Software/project_name when %r{^http://((?:www|nice|libopenraw|liboil|telepathy|xorg)\.)?freedesktop\.org/(?:wiki/)?} if content.include?("Software") - problem "Freedesktop homepages should be styled " \ - "`https://wiki.freedesktop.org/www/Software/project_name`" + problem "Freedesktop homepages should be styled: https://wiki.freedesktop.org/www/Software/project_name" else - problem "Freedesktop homepages should be styled `https://wiki.freedesktop.org/project_name`" + problem "Freedesktop homepages should be styled: https://wiki.freedesktop.org/project_name" end # Google Code homepages should end in a slash @@ -45,13 +44,13 @@ module RuboCop when %r{^http://([^/]*)\.(sf|sourceforge)\.net(/|$)} fixed = "https://#{Regexp.last_match(1)}.sourceforge.io/" - problem "Sourceforge homepages should be `#{fixed}`" do |corrector| + problem "SourceForge homepages should be: #{fixed}" do |corrector| corrector.replace(homepage_parameter_node.source_range, "\"#{fixed}\"") end when /readthedocs\.org/ fixed = content.sub("readthedocs.org", "readthedocs.io") - problem "Readthedocs homepages should be `#{fixed}`" do |corrector| + problem "Readthedocs homepages should be: #{fixed}" do |corrector| corrector.replace(homepage_parameter_node.source_range, "\"#{fixed}\"") end diff --git a/Library/Homebrew/rubocops/shared/on_system_conditionals_helper.rb b/Library/Homebrew/rubocops/shared/on_system_conditionals_helper.rb index f973dd72b6..beb8a48a05 100644 --- a/Library/Homebrew/rubocops/shared/on_system_conditionals_helper.rb +++ b/Library/Homebrew/rubocops/shared/on_system_conditionals_helper.rb @@ -69,8 +69,8 @@ module RuboCop end offending_node(on_system_node) - problem "Don't use `#{on_system_node.source}` in `#{parent_string}`, " \ - "use `#{if_statement_string}#{if_conditional}` instead." do |corrector| + problem "Instead of using `#{on_system_node.source}` in `#{parent_string}`, " \ + "use `#{if_statement_string}#{if_conditional}`." do |corrector| block_node = offending_node.parent next if block_node.type != :block @@ -108,7 +108,7 @@ module RuboCop next if node_is_allowed?(method_node, allowed_methods:, allowed_blocks:) offending_node(method_node) - problem "Don't use `#{method_node.source}`, use `on_arm` and `on_intel` blocks instead." + problem "Instead of `#{method_node.source}`, use `on_arm` and `on_intel` blocks." end end end @@ -171,7 +171,7 @@ module RuboCop next if node_is_allowed?(method_node, allowed_methods:, allowed_blocks:) offending_node(method_node) - problem "Don't use `#{method_node.source}`, use `on_{macos_version}` blocks instead." + problem "Instead of `#{method_node.source}`, use `on_{macos_version}` blocks." end end end @@ -209,8 +209,7 @@ module RuboCop def if_statement_problem(if_node, if_statement_string, on_system_method_string, else_method: nil, else_node: nil, autocorrect: true) offending_node(if_node) - problem "Don't use `#{if_statement_string}`, " \ - "use `#{on_system_method_string} do` instead." do |corrector| + problem "Instead of `#{if_statement_string}`, use `#{on_system_method_string} do`." do |corrector| next unless autocorrect # TODO: could fix corrector to handle this but punting for now. next if if_node.unless? diff --git a/Library/Homebrew/rubocops/shared/url_helper.rb b/Library/Homebrew/rubocops/shared/url_helper.rb index 0a49816f13..e715ff607d 100644 --- a/Library/Homebrew/rubocops/shared/url_helper.rb +++ b/Library/Homebrew/rubocops/shared/url_helper.rb @@ -38,37 +38,37 @@ module RuboCop # URLs must be ASCII; IDNs must be punycode ascii_pattern = /[^\p{ASCII}]+/ audit_urls(urls, ascii_pattern) do |_, url| - problem "Please use the ASCII (Punycode encoded host, URL-encoded path and query) version of #{url}." + problem "Please use the ASCII (Punycode-encoded host, URL-encoded path and query) version of #{url}." end # GNU URLs; doesn't apply to mirrors gnu_pattern = %r{^(?:https?|ftp)://ftpmirror\.gnu\.org/(.*)} audit_urls(urls, gnu_pattern) do |match, url| - problem "Please use \"https://ftp.gnu.org/gnu/#{match[1]}\" instead of #{url}." + problem "#{url} should be: https://ftp.gnu.org/gnu/#{match[1]}" end # Fossies upstream requests they aren't used as primary URLs # https://github.com/Homebrew/homebrew-core/issues/14486#issuecomment-307753234 fossies_pattern = %r{^https?://fossies\.org/} audit_urls(urls, fossies_pattern) do - problem "Please don't use fossies.org in the url (using as a mirror is fine)" + problem "Please don't use \"fossies.org\" in the `url` (using as a mirror is fine)" end apache_pattern = %r{^https?://(?:[^/]*\.)?apache\.org/(?:dyn/closer\.cgi\?path=/?|dist/)(.*)}i audit_urls(urls, apache_pattern) do |match, url| next if url == livecheck_url - problem "#{url} should be `https://www.apache.org/dyn/closer.lua?path=#{match[1]}`" + problem "#{url} should be: https://www.apache.org/dyn/closer.lua?path=#{match[1]}" end version_control_pattern = %r{^(cvs|bzr|hg|fossil)://} audit_urls(urls, version_control_pattern) do |match, _| - problem "Use of the #{match[1]}:// scheme is deprecated, pass `:using => :#{match[1]}` instead" + problem "Use of the \"#{match[1]}://\" scheme is deprecated, pass `using: :#{match[1]}` instead" end svn_pattern = %r{^svn\+http://} audit_urls(urls, svn_pattern) do |_, _| - problem "Use of the svn+http:// scheme is deprecated, pass `:using => :svn` instead" + problem "Use of the \"svn+http://\" scheme is deprecated, pass `using: :svn` instead" end audit_urls(mirrors, /.*/) do |_, mirror| @@ -117,22 +117,22 @@ module RuboCop apache_mirror_pattern = %r{^https?://(?:[^/]*\.)?apache\.org/dyn/closer\.(?:cgi|lua)\?path=/?(.*)}i audit_urls(mirrors, apache_mirror_pattern) do |match, mirror| - problem "Please use `https://archive.apache.org/dist/#{match[1]}` as a mirror instead of #{mirror}." + problem "#{mirror} should be: https://archive.apache.org/dist/#{match[1]}" end cpan_pattern = %r{^http://search\.mcpan\.org/CPAN/(.*)}i audit_urls(urls, cpan_pattern) do |match, url| - problem "#{url} should be `https://cpan.metacpan.org/#{match[1]}`" + problem "#{url} should be: https://cpan.metacpan.org/#{match[1]}" end gnome_pattern = %r{^(http|ftp)://ftp\.gnome\.org/pub/gnome/(.*)}i audit_urls(urls, gnome_pattern) do |match, url| - problem "#{url} should be `https://download.gnome.org/#{match[2]}`" + problem "#{url} should be: https://download.gnome.org/#{match[2]}" end debian_pattern = %r{^git://anonscm\.debian\.org/users/(.*)}i audit_urls(urls, debian_pattern) do |match, url| - problem "#{url} should be `https://anonscm.debian.org/git/users/#{match[1]}`" + problem "#{url} should be: https://anonscm.debian.org/git/users/#{match[1]}" end # Prefer HTTP/S when possible over FTP protocol due to possible firewalls. @@ -143,7 +143,7 @@ module RuboCop cpan_ftp_pattern = %r{^ftp://ftp\.cpan\.org/pub/CPAN(.*)}i audit_urls(urls, cpan_ftp_pattern) do |match_obj, url| - problem "#{url} should be `http://search.cpan.org/CPAN#{match_obj[1]}`" + problem "#{url} should be: http://search.cpan.org/CPAN#{match_obj[1]}" end # SourceForge url patterns @@ -155,26 +155,26 @@ module RuboCop next if url.include? "/p/" if url =~ /(\?|&)use_mirror=/ - problem "Don't use #{Regexp.last_match(1)}use_mirror in SourceForge urls (url is #{url})." + problem "Don't use \"#{Regexp.last_match(1)}use_mirror\" in SourceForge URLs (`url` is #{url})." end - problem "Don't use /download in SourceForge urls (url is #{url})." if url.end_with?("/download") + problem "Don't use \"/download\" in SourceForge URLs (`url` is #{url})." if url.end_with?("/download") if url.match?(%r{^https?://(sourceforge|sf)\.}) && url != livecheck_url - problem "Use https://downloads.sourceforge.net to get geolocation (url is #{url})." + problem "Use \"https://downloads.sourceforge.net\" to get geolocation (`url` is #{url})." end if url.match?(%r{^https?://prdownloads\.}) - problem "Don't use prdownloads in SourceForge urls (url is #{url})." + problem "Don't use \"prdownloads\" in SourceForge URLs (`url` is #{url})." end if url.match?(%r{^http://\w+\.dl\.}) - problem "Don't use specific dl mirrors in SourceForge urls (url is #{url})." + problem "Don't use specific \"dl\" mirrors in SourceForge URLs (`url` is #{url})." end # sf.net does HTTPS -> HTTP redirects. if url.match?(%r{^https?://downloads?\.sf\.net}) - problem "Use https://downloads.sourceforge.net instead of downloads.sf.net (url is #{url})" + problem "Use \"https://downloads.sourceforge.net\" instead of \"downloads.sf.net\" (`url` is #{url})" end end @@ -236,14 +236,14 @@ module RuboCop audit_urls(urls, archive_gh_pattern) do |_, url| next if url.end_with?(".git") - problem "Use /archive/ URLs for GitHub tarballs (url is #{url})." + problem "Use /archive/ URLs for GitHub tarballs (`url` is #{url})." end archive_refs_gh_pattern = %r{https://.*github.+/archive/(?![a-fA-F0-9]{40})(?!refs/(tags|heads)/)(.*)\.tar\.gz$} audit_urls(urls, archive_refs_gh_pattern) do |match, url| next if url.end_with?(".git") - problem "Use refs/tags/#{match[2]} or refs/heads/#{match[2]} for GitHub references (url is #{url})." + problem %Q(Use "refs/tags/#{match[2]}" or "refs/heads/#{match[2]}" for GitHub references (`url` is #{url}).) end # Don't use GitHub .zip files @@ -253,7 +253,7 @@ module RuboCop next if url.include?("releases/download") next if url.include?("desktop.githubusercontent.com/releases/") - problem "Use GitHub tarballs rather than zipballs (url is #{url})." + problem "Use GitHub tarballs rather than zipballs (`url` is #{url})." end # Don't use GitHub codeload URLs @@ -270,7 +270,7 @@ module RuboCop # Check for Maven Central URLs, prefer HTTPS redirector over specific host maven_pattern = %r{https?://(?:central|repo\d+)\.maven\.org/maven2/(.+)$} audit_urls(urls, maven_pattern) do |match, url| - problem "#{url} should be `https://search.maven.org/remotecontent?filepath=#{match[1]}`" + problem "#{url} should be: https://search.maven.org/remotecontent?filepath=#{match[1]}" end end end diff --git a/Library/Homebrew/rubocops/text.rb b/Library/Homebrew/rubocops/text.rb index 21c15615b8..7b7469b10f 100644 --- a/Library/Homebrew/rubocops/text.rb +++ b/Library/Homebrew/rubocops/text.rb @@ -45,19 +45,19 @@ module RuboCop # processed_source.ast is passed instead of body_node because `require` would be outside body_node find_method_with_args(processed_source.ast, :require, "language/go") do - problem "require \"language/go\" is no longer necessary or correct" + problem '`require "language/go"` is no longer necessary or correct' end find_instance_method_call(body_node, "Formula", :factory) do - problem "\"Formula.factory(name)\" is deprecated in favor of \"Formula[name]\"" + problem "`Formula.factory(name)` is deprecated in favour of `Formula[name]`" end find_method_with_args(body_node, :revision, 0) do - problem "\"revision 0\" is unnecessary" + problem "`revision 0` is unnecessary" end find_method_with_args(body_node, :system, "xcodebuild") do - problem %q(use "xcodebuild *args" instead of "system 'xcodebuild', *args") + problem "Use `xcodebuild *args` instead of `system 'xcodebuild', *args`" end if !depends_on?(:xcode) && method_called_ever?(body_node, :xcodebuild) @@ -72,7 +72,7 @@ module RuboCop find_method_with_args(method_node, :system, "cargo", "build") do |m| next if parameters_passed?(m, [/--lib/]) - problem "use \"cargo\", \"install\", *std_cargo_args" + problem 'Use `"cargo", "install", *std_cargo_args`' end end @@ -80,7 +80,7 @@ module RuboCop next if parameters_passed?(d, [/vendor-only/]) next if @formula_name == "goose" # needed in 2.3.0 - problem "use \"dep\", \"ensure\", \"-vendor-only\"" + problem 'Use `"dep", "ensure", "-vendor-only"`' end find_every_method_call_by_name(body_node, :system).each do |m| diff --git a/Library/Homebrew/rubocops/urls.rb b/Library/Homebrew/rubocops/urls.rb index a37ba8705e..cbd9bcb393 100644 --- a/Library/Homebrew/rubocops/urls.rb +++ b/Library/Homebrew/rubocops/urls.rb @@ -54,13 +54,13 @@ module RuboCop # Check pypi URLs pypi_pattern = %r{^https?://pypi\.python\.org/} audit_urls(urls, pypi_pattern) do |_, url| - problem "use the `Source` url found on PyPI downloads page (`#{get_pypi_url(url)}`)" + problem "Use the \"Source\" URL found on the PyPI downloads page (#{get_pypi_url(url)})" end # Require long files.pythonhosted.org URLs pythonhosted_pattern = %r{^https?://files\.pythonhosted\.org/packages/source/} audit_urls(urls, pythonhosted_pattern) do |_, url| - problem "use the `Source` url found on PyPI downloads page (`#{get_pypi_url(url)}`)" + problem "Use the \"Source\" URL found on the PyPI downloads page (#{get_pypi_url(url)})" end end @@ -84,7 +84,7 @@ module RuboCop next if url_has_revision?(parameters(url).last) offending_node(url) - problem "Formulae in homebrew/core should specify a revision for git URLs" + problem "Formulae in homebrew/core should specify a revision for Git URLs" end end @@ -107,7 +107,7 @@ module RuboCop next if url_has_tag?(parameters(url).last) offending_node(url) - problem "Formulae in homebrew/core should specify a tag for git URLs" + problem "Formulae in homebrew/core should specify a tag for Git URLs" end end diff --git a/Library/Homebrew/rubocops/uses_from_macos.rb b/Library/Homebrew/rubocops/uses_from_macos.rb index 621f3bc3ed..8ebbc96483 100644 --- a/Library/Homebrew/rubocops/uses_from_macos.rb +++ b/Library/Homebrew/rubocops/uses_from_macos.rb @@ -66,7 +66,7 @@ module RuboCop return if PROVIDED_BY_MACOS_FORMULAE.include? @formula_name problem "Formulae that are `keg_only :provided_by_macos` should be " \ - "added to the `PROVIDED_BY_MACOS_FORMULAE` list (in the Homebrew/brew repo)" + "added to the `PROVIDED_BY_MACOS_FORMULAE` list (in the Homebrew/brew repository)" end end end @@ -116,7 +116,7 @@ module RuboCop next if ALLOWED_USES_FROM_MACOS_DEPS.include? dep_name next if ProvidedByMacos::PROVIDED_BY_MACOS_FORMULAE.include? dep_name - problem "`uses_from_macos` should only be used for macOS dependencies, not #{dep_name}." + problem "`uses_from_macos` should only be used for macOS dependencies, not '#{dep_name}'." end end end diff --git a/Library/Homebrew/rubocops/version.rb b/Library/Homebrew/rubocops/version.rb index 82863ab3a1..4492e57d9e 100644 --- a/Library/Homebrew/rubocops/version.rb +++ b/Library/Homebrew/rubocops/version.rb @@ -15,13 +15,13 @@ module RuboCop version = string_content(parameters(version_node).first) - problem "version is set to an empty string" if version.empty? + problem "Version is set to an empty string" if version.empty? - problem "version #{version} should not have a leading 'v'" if version.start_with?("v") + problem "Version #{version} should not have a leading 'v'" if version.start_with?("v") return unless version.match?(/_\d+$/) - problem "version #{version} should not end with an underline and a number" + problem "Version #{version} should not end with an underline and a number" end end end diff --git a/Library/Homebrew/sbom.rb b/Library/Homebrew/sbom.rb index 8873cdf751..4df1d7e815 100644 --- a/Library/Homebrew/sbom.rb +++ b/Library/Homebrew/sbom.rb @@ -4,7 +4,7 @@ require "cxxstdlib" require "json" require "development_tools" -require "extend/cachable" +require "cachable" require "utils/curl" # Rather than calling `new` directly, use one of the class methods like {SBOM.create}. diff --git a/Library/Homebrew/service.rb b/Library/Homebrew/service.rb index 2ae807da14..b52c1bb083 100644 --- a/Library/Homebrew/service.rb +++ b/Library/Homebrew/service.rb @@ -2,7 +2,7 @@ # frozen_string_literal: true require "ipaddr" -require "extend/on_system" +require "on_system" require "utils/service" module Homebrew diff --git a/Library/Homebrew/simulate_system.rb b/Library/Homebrew/simulate_system.rb index e1b80b8415..e40d891581 100644 --- a/Library/Homebrew/simulate_system.rb +++ b/Library/Homebrew/simulate_system.rb @@ -2,6 +2,7 @@ # frozen_string_literal: true require "macos_version" +require "utils/bottles" module Homebrew # Helper module for simulating different system configurations. @@ -33,6 +34,18 @@ module Homebrew end end + sig { + type_parameters(:U).params( + tag: Utils::Bottles::Tag, + block: T.proc.returns(T.type_parameter(:U)), + ).returns(T.type_parameter(:U)) + } + def with_tag(tag, &block) + raise ArgumentError, "Invalid tag: #{tag}" unless tag.valid_combination? + + with(os: tag.system, arch: tag.arch, &block) + end + sig { params(new_os: Symbol).void } def os=(new_os) os_options = [:macos, :linux, *MacOSVersion::SYMBOLS.keys] @@ -72,6 +85,14 @@ module Homebrew def current_os os || :generic end + + sig { returns(Utils::Bottles::Tag) } + def current_tag + Utils::Bottles::Tag.new( + system: current_os, + arch: current_arch, + ) + end end end end diff --git a/Library/Homebrew/software_spec.rb b/Library/Homebrew/software_spec.rb index 7463429257..a6172182cb 100644 --- a/Library/Homebrew/software_spec.rb +++ b/Library/Homebrew/software_spec.rb @@ -12,7 +12,7 @@ require "utils/bottles" require "patch" require "compilers" require "macos_version" -require "extend/on_system" +require "on_system" class SoftwareSpec include Downloadable diff --git a/Library/Homebrew/sorbet/rbi/dsl/caveats.rbi b/Library/Homebrew/sorbet/rbi/dsl/caveats.rbi index dbe807aa31..e544438a19 100644 --- a/Library/Homebrew/sorbet/rbi/dsl/caveats.rbi +++ b/Library/Homebrew/sorbet/rbi/dsl/caveats.rbi @@ -6,9 +6,6 @@ class Caveats - sig { params(args: T.untyped, block: T.untyped).returns(T::Boolean) } - def empty?(*args, &block); end - sig { params(args: T.untyped, block: T.untyped).returns(String) } def to_s(*args, &block); end end diff --git a/Library/Homebrew/sorbet/rbi/dsl/homebrew/cmd/mcp_server_cmd.rbi b/Library/Homebrew/sorbet/rbi/dsl/homebrew/cmd/mcp_server_cmd.rbi new file mode 100644 index 0000000000..c9fc49bef8 --- /dev/null +++ b/Library/Homebrew/sorbet/rbi/dsl/homebrew/cmd/mcp_server_cmd.rbi @@ -0,0 +1,16 @@ +# typed: true + +# DO NOT EDIT MANUALLY +# This is an autogenerated file for dynamic methods in `Homebrew::Cmd::McpServerCmd`. +# Please instead update this file by running `bin/tapioca dsl Homebrew::Cmd::McpServerCmd`. + + +class Homebrew::Cmd::McpServerCmd + sig { returns(Homebrew::Cmd::McpServerCmd::Args) } + def args; end +end + +class Homebrew::Cmd::McpServerCmd::Args < Homebrew::CLI::Args + sig { returns(T::Boolean) } + def ping?; end +end diff --git a/Library/Homebrew/sorbet/rbi/dsl/homebrew/dev_cmd/tests.rbi b/Library/Homebrew/sorbet/rbi/dsl/homebrew/dev_cmd/tests.rbi index 863665ee93..32c70a843f 100644 --- a/Library/Homebrew/sorbet/rbi/dsl/homebrew/dev_cmd/tests.rbi +++ b/Library/Homebrew/sorbet/rbi/dsl/homebrew/dev_cmd/tests.rbi @@ -23,6 +23,9 @@ class Homebrew::DevCmd::Tests::Args < Homebrew::CLI::Args sig { returns(T::Boolean) } def generic?; end + sig { returns(T::Boolean) } + def no_parallel?; end + sig { returns(T::Boolean) } def online?; end diff --git a/Library/Homebrew/sorbet/rbi/dsl/rubo_cop/cask/ast/stanza.rbi b/Library/Homebrew/sorbet/rbi/dsl/rubo_cop/cask/ast/stanza.rbi index a8c6e4f8af..b07393aca9 100644 --- a/Library/Homebrew/sorbet/rbi/dsl/rubo_cop/cask/ast/stanza.rbi +++ b/Library/Homebrew/sorbet/rbi/dsl/rubo_cop/cask/ast/stanza.rbi @@ -129,6 +129,9 @@ class RuboCop::Cask::AST::Stanza sig { params(args: T.untyped, block: T.untyped).returns(T::Boolean) } def on_system_block?(*args, &block); end + sig { returns(T::Boolean) } + def on_tahoe?; end + sig { returns(T::Boolean) } def on_ventura?; end diff --git a/Library/Homebrew/system_command.rb b/Library/Homebrew/system_command.rb index 737eea4322..b70e2d7583 100644 --- a/Library/Homebrew/system_command.rb +++ b/Library/Homebrew/system_command.rb @@ -6,7 +6,7 @@ require "shellwords" require "uri" require "context" -require "extend/io" +require "readline_nonblock" require "utils/timer" # Class for running sub-processes and capturing their output and exit status. @@ -361,7 +361,7 @@ class SystemCommand readable_sources.each do |source| loop do - line = source.readline_nonblock || "" + line = ReadlineNonblock.read(source) yield(sources.fetch(source), line) end rescue EOFError diff --git a/Library/Homebrew/tab.rb b/Library/Homebrew/tab.rb index 70f7118234..dc57bb4d20 100644 --- a/Library/Homebrew/tab.rb +++ b/Library/Homebrew/tab.rb @@ -5,7 +5,7 @@ require "cxxstdlib" require "options" require "json" require "development_tools" -require "extend/cachable" +require "cachable" # Rather than calling `new` directly, use one of the class methods like {Tab.create}. class AbstractTab diff --git a/Library/Homebrew/tap.rb b/Library/Homebrew/tap.rb index bf83e7ee29..545d91cd76 100644 --- a/Library/Homebrew/tap.rb +++ b/Library/Homebrew/tap.rb @@ -1079,15 +1079,12 @@ class Tap # All locally installed and core taps. Core taps might not be installed locally when using the API. sig { returns(T::Array[Tap]) } def self.all - cache[:all] ||= begin - core_taps = [ - CoreTap.instance, - # The conditional is valid here because we only want the cask tap on macOS. - (CoreCaskTap.instance if OS.mac?), # rubocop:disable Homebrew/MoveToExtendOS - ].compact + cache[:all] ||= installed | core_taps + end - installed | core_taps - end + sig { returns(T::Array[Tap]) } + def self.core_taps + [CoreTap.instance].freeze end # Enumerate all available {Tap}s. @@ -1517,3 +1514,5 @@ class TapConfig Homebrew::Settings.delete key, repo: tap.path end end + +require "extend/os/tap" diff --git a/Library/Homebrew/test/api/cask_spec.rb b/Library/Homebrew/test/api/cask_spec.rb index 932897dbe8..372027293f 100644 --- a/Library/Homebrew/test/api/cask_spec.rb +++ b/Library/Homebrew/test/api/cask_spec.rb @@ -54,6 +54,7 @@ RSpec.describe Homebrew::API::Cask do end before do + allow(Homebrew::API).to receive(:fetch_json_api_file).and_return([[], true]) allow_any_instance_of(Homebrew::API::Download).to receive(:fetch) allow_any_instance_of(Homebrew::API::Download).to receive(:symlink_location).and_return( TEST_FIXTURE_DIR/"cask/Casks/everything.rb", diff --git a/Library/Homebrew/test/api_spec.rb b/Library/Homebrew/test/api_spec.rb index 9186fc625c..dbf590f73d 100644 --- a/Library/Homebrew/test/api_spec.rb +++ b/Library/Homebrew/test/api_spec.rb @@ -90,4 +90,84 @@ RSpec.describe Homebrew::API do end end end + + describe "::merge_variations" do + let(:arm64_sequoia_tag) { Utils::Bottles::Tag.new(system: :sequoia, arch: :arm) } + let(:sonoma_tag) { Utils::Bottles::Tag.new(system: :sonoma, arch: :intel) } + let(:x86_64_linux_tag) { Utils::Bottles::Tag.new(system: :linux, arch: :intel) } + + let(:json) do + { + "name" => "foo", + "foo" => "bar", + "baz" => ["test1", "test2"], + "variations" => { + "arm64_sequoia" => { "foo" => "new" }, + :sonoma => { "baz" => ["new1", "new2", "new3"] }, + }, + } + end + + let(:arm64_sequoia_result) do + { + "name" => "foo", + "foo" => "new", + "baz" => ["test1", "test2"], + } + end + + let(:sonoma_result) do + { + "name" => "foo", + "foo" => "bar", + "baz" => ["new1", "new2", "new3"], + } + end + + it "returns the original JSON if no variations are found" do + result = described_class.merge_variations(arm64_sequoia_result, bottle_tag: arm64_sequoia_tag) + expect(result).to eq arm64_sequoia_result + end + + it "returns the original JSON if no variations are found for the current system" do + result = described_class.merge_variations(arm64_sequoia_result) + expect(result).to eq arm64_sequoia_result + end + + it "returns the original JSON without the variations if no matching variation is found" do + result = described_class.merge_variations(json, bottle_tag: x86_64_linux_tag) + expect(result).to eq json.except("variations") + end + + it "returns the original JSON without the variations if no matching variation is found for the current system" do + Homebrew::SimulateSystem.with(os: :linux, arch: :intel) do + result = described_class.merge_variations(json) + expect(result).to eq json.except("variations") + end + end + + it "returns the JSON with the matching variation applied from a string key" do + result = described_class.merge_variations(json, bottle_tag: arm64_sequoia_tag) + expect(result).to eq arm64_sequoia_result + end + + it "returns the JSON with the matching variation applied from a string key for the current system" do + Homebrew::SimulateSystem.with(os: :sequoia, arch: :arm) do + result = described_class.merge_variations(json) + expect(result).to eq arm64_sequoia_result + end + end + + it "returns the JSON with the matching variation applied from a symbol key" do + result = described_class.merge_variations(json, bottle_tag: sonoma_tag) + expect(result).to eq sonoma_result + end + + it "returns the JSON with the matching variation applied from a symbol key for the current system" do + Homebrew::SimulateSystem.with(os: :sonoma, arch: :intel) do + result = described_class.merge_variations(json) + expect(result).to eq sonoma_result + end + end + end end diff --git a/Library/Homebrew/test/bundle/commands/check_spec.rb b/Library/Homebrew/test/bundle/commands/check_spec.rb index 2e62f9383c..8448d7ee1b 100644 --- a/Library/Homebrew/test/bundle/commands/check_spec.rb +++ b/Library/Homebrew/test/bundle/commands/check_spec.rb @@ -12,7 +12,7 @@ require "bundle/mac_app_store_installer" require "bundle/dsl" require "bundle/skipper" -RSpec.describe Homebrew::Bundle::Commands::Check do +RSpec.describe Homebrew::Bundle::Commands::Check, :no_api do let(:do_check) do described_class.run(no_upgrade:, verbose:) end diff --git a/Library/Homebrew/test/bundle/commands/cleanup_spec.rb b/Library/Homebrew/test/bundle/commands/cleanup_spec.rb index e85f78ddc7..1793985919 100644 --- a/Library/Homebrew/test/bundle/commands/cleanup_spec.rb +++ b/Library/Homebrew/test/bundle/commands/cleanup_spec.rb @@ -4,7 +4,7 @@ require "bundle" require "bundle/commands/cleanup" RSpec.describe Homebrew::Bundle::Commands::Cleanup do - describe "read Brewfile and current installation" do + describe "read Brewfile and current installation", :no_api do before do described_class.reset! diff --git a/Library/Homebrew/test/bundle/commands/exec_spec.rb b/Library/Homebrew/test/bundle/commands/exec_spec.rb index 101ab72f05..c11b989b46 100644 --- a/Library/Homebrew/test/bundle/commands/exec_spec.rb +++ b/Library/Homebrew/test/bundle/commands/exec_spec.rb @@ -12,7 +12,7 @@ RSpec.describe Homebrew::Bundle::Commands::Exec do end end - context "when a Brewfile is found" do + context "when a Brewfile is found", :no_api do let(:brewfile_contents) { "brew 'openssl'" } before do diff --git a/Library/Homebrew/test/bundle/commands/install_spec.rb b/Library/Homebrew/test/bundle/commands/install_spec.rb index f32e3f28e3..9e855914bd 100644 --- a/Library/Homebrew/test/bundle/commands/install_spec.rb +++ b/Library/Homebrew/test/bundle/commands/install_spec.rb @@ -16,7 +16,7 @@ RSpec.describe Homebrew::Bundle::Commands::Install do end end - context "when a Brewfile is found" do + context "when a Brewfile is found", :no_api do let(:brewfile_contents) do <<~EOS tap 'phinze/cask' diff --git a/Library/Homebrew/test/cask/cask_loader/from_api_loader_spec.rb b/Library/Homebrew/test/cask/cask_loader/from_api_loader_spec.rb index f066a098a9..3362c519b6 100644 --- a/Library/Homebrew/test/cask/cask_loader/from_api_loader_spec.rb +++ b/Library/Homebrew/test/cask/cask_loader/from_api_loader_spec.rb @@ -31,10 +31,6 @@ RSpec.describe Cask::CaskLoader::FromAPILoader, :cask do end context "when using the API" do - before do - ENV.delete("HOMEBREW_NO_INSTALL_FROM_API") - end - it "returns a loader for valid token" do expect(described_class.try_new(api_token)) .to be_a(described_class) diff --git a/Library/Homebrew/test/cask/cask_loader_spec.rb b/Library/Homebrew/test/cask/cask_loader_spec.rb index 4c18828c9e..e2671408fa 100644 --- a/Library/Homebrew/test/cask/cask_loader_spec.rb +++ b/Library/Homebrew/test/cask/cask_loader_spec.rb @@ -45,10 +45,6 @@ RSpec.describe Cask::CaskLoader, :cask do end context "when using the API" do - before do - ENV.delete("HOMEBREW_NO_INSTALL_FROM_API") - end - it "warns when using the short token" do expect do expect(described_class.for("version-newest")).to be_a Cask::CaskLoader::FromAPILoader diff --git a/Library/Homebrew/test/cask/cask_spec.rb b/Library/Homebrew/test/cask/cask_spec.rb index 2dd30c87cc..e08e8f90e4 100644 --- a/Library/Homebrew/test/cask/cask_spec.rb +++ b/Library/Homebrew/test/cask/cask_spec.rb @@ -46,13 +46,13 @@ RSpec.describe Cask::Cask, :cask do expect(c.token).to eq("caffeine") end - it "returns an instance of the Cask from a URL", :needs_utils_curl, :no_api do + it "returns an instance of the Cask from a URL", :needs_utils_curl do c = Cask::CaskLoader.load("file://#{tap_path}/Casks/local-caffeine.rb") expect(c).to be_a(described_class) expect(c.token).to eq("local-caffeine") end - it "raises an error when failing to download a Cask from a URL", :needs_utils_curl, :no_api do + it "raises an error when failing to download a Cask from a URL", :needs_utils_curl do expect do Cask::CaskLoader.load("file://#{tap_path}/Casks/notacask.rb") end.to raise_error(Cask::CaskUnavailableError) @@ -324,6 +324,9 @@ RSpec.describe Cask::Cask, :cask do let(:expected_versions_variations) do <<~JSON { + "tahoe": { + "url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine/darwin/1.2.3/intel.zip" + }, "sequoia": { "url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine/darwin/1.2.3/intel.zip" }, @@ -377,6 +380,10 @@ RSpec.describe Cask::Cask, :cask do let(:expected_sha256_variations) do <<~JSON { + "tahoe": { + "url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine-intel.zip", + "sha256": "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b" + }, "sequoia": { "url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine-intel.zip", "sha256": "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b" @@ -423,6 +430,10 @@ RSpec.describe Cask::Cask, :cask do let(:expected_sha256_variations_os) do <<~JSON { + "tahoe": { + "url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine-intel-darwin.zip", + "sha256": "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b" + }, "sequoia": { "url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine-intel-darwin.zip", "sha256": "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b" diff --git a/Library/Homebrew/test/cask_dependent_spec.rb b/Library/Homebrew/test/cask_dependent_spec.rb index 48e09d16fe..38e9da163f 100644 --- a/Library/Homebrew/test/cask_dependent_spec.rb +++ b/Library/Homebrew/test/cask_dependent_spec.rb @@ -30,7 +30,7 @@ RSpec.describe CaskDependent, :needs_macos do end end - describe "#recursive_dependencies", :integration_test do + describe "#recursive_dependencies", :integration_test, :no_api do it "is all the dependencies of the cask" do setup_test_formula "foo" setup_test_formula "bar" diff --git a/Library/Homebrew/test/caveats_spec.rb b/Library/Homebrew/test/caveats_spec.rb index 7871177928..089c80c527 100644 --- a/Library/Homebrew/test/caveats_spec.rb +++ b/Library/Homebrew/test/caveats_spec.rb @@ -242,7 +242,7 @@ RSpec.describe Caveats do url "foo-1.0" end end - let(:caveats) { described_class.new(f).caveats } + let(:caveats) { described_class.new(f) } let(:path) { f.prefix.resolved_path } let(:bash_completion_dir) { path/"etc/bash_completion.d" } @@ -261,25 +261,25 @@ RSpec.describe Caveats do it "includes where Bash completions have been installed to" do bash_completion_dir.mkpath FileUtils.touch bash_completion_dir/f.name - expect(caveats).to include(HOMEBREW_PREFIX/"etc/bash_completion.d") + expect(caveats.completions_and_elisp.join).to include(HOMEBREW_PREFIX/"etc/bash_completion.d") end it "includes where fish completions have been installed to" do fish_vendor_completions.mkpath FileUtils.touch fish_vendor_completions/f.name - expect(caveats).to include(HOMEBREW_PREFIX/"share/fish/vendor_completions.d") + expect(caveats.completions_and_elisp.join).to include(HOMEBREW_PREFIX/"share/fish/vendor_completions.d") end it "includes where zsh completions have been installed to" do zsh_site_functions.mkpath FileUtils.touch zsh_site_functions/f.name - expect(caveats).to include(HOMEBREW_PREFIX/"share/zsh/site-functions") + expect(caveats.completions_and_elisp.join).to include(HOMEBREW_PREFIX/"share/zsh/site-functions") end it "includes where pwsh completions have been installed to" do pwsh_completion_dir.mkpath FileUtils.touch pwsh_completion_dir/f.name - expect(caveats).to include(HOMEBREW_PREFIX/"share/pwsh/completions") + expect(caveats.completions_and_elisp.join).to include(HOMEBREW_PREFIX/"share/pwsh/completions") end end end diff --git a/Library/Homebrew/test/cmd/casks_spec.rb b/Library/Homebrew/test/cmd/casks_spec.rb new file mode 100644 index 0000000000..d70b5daf34 --- /dev/null +++ b/Library/Homebrew/test/cmd/casks_spec.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +RSpec.describe "brew casks", type: :system do + it "prints all installed Casks", :integration_test do + expect { brew_sh "casks" } + .to be_a_success + .and not_to_output.to_stderr + end +end diff --git a/Library/Homebrew/test/cmd/deps_spec.rb b/Library/Homebrew/test/cmd/deps_spec.rb index 80edb94337..f00566b29b 100644 --- a/Library/Homebrew/test/cmd/deps_spec.rb +++ b/Library/Homebrew/test/cmd/deps_spec.rb @@ -8,7 +8,7 @@ RSpec.describe Homebrew::Cmd::Deps do it_behaves_like "parseable arguments" - it "outputs all of a Formula's dependencies and their dependencies on separate lines", :integration_test do + it "outputs all of a Formula's dependencies and their dependencies on separate lines", :integration_test, :no_api do # Included in output setup_test_formula "bar" setup_test_formula "foo" @@ -37,6 +37,6 @@ RSpec.describe Homebrew::Cmd::Deps do expect { brew "deps", "baz", "--include-test", "--missing", "--skip-recommended" } .to be_a_success .and output("bar\nfoo\ntest\n").to_stdout - .and not_to_output.to_stderr + .and output(/not the actual runtime dependencies/).to_stderr end end diff --git a/Library/Homebrew/test/cmd/desc_spec.rb b/Library/Homebrew/test/cmd/desc_spec.rb index 4313e56ac3..4c699e62f5 100644 --- a/Library/Homebrew/test/cmd/desc_spec.rb +++ b/Library/Homebrew/test/cmd/desc_spec.rb @@ -15,7 +15,7 @@ RSpec.describe Homebrew::Cmd::Desc do .and be_a_success end - it "errors when searching without --eval-all", :integration_test do + it "errors when searching without --eval-all", :integration_test, :no_api do setup_test_formula "testball" expect { brew "desc", "--search", "testball" } @@ -23,7 +23,7 @@ RSpec.describe Homebrew::Cmd::Desc do .and be_a_failure end - it "successfully searches with --search --eval-all", :integration_test do + it "successfully searches with --search --eval-all", :integration_test, :no_api do setup_test_formula "testball" expect { brew "desc", "--search", "--eval-all", "ball" } @@ -34,7 +34,6 @@ RSpec.describe Homebrew::Cmd::Desc do it "successfully searches without --eval-all, with API", :integration_test, :needs_network do setup_test_formula "testball" - expect { brew "desc", "--search", "testball", "HOMEBREW_NO_INSTALL_FROM_API" => nil } - .to be_a_success + expect { brew "desc", "--search", "testball" }.to be_a_success end end diff --git a/Library/Homebrew/test/cmd/formulae_spec.rb b/Library/Homebrew/test/cmd/formulae_spec.rb new file mode 100644 index 0000000000..714238aefa --- /dev/null +++ b/Library/Homebrew/test/cmd/formulae_spec.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +RSpec.describe "brew formulae", type: :system do + it "prints all installed Formulae", :integration_test do + expect { brew_sh "formulae" } + .to be_a_success + .and not_to_output.to_stderr + end +end diff --git a/Library/Homebrew/test/cmd/leaves_spec.rb b/Library/Homebrew/test/cmd/leaves_spec.rb index 9e00a21ca1..089a032f11 100644 --- a/Library/Homebrew/test/cmd/leaves_spec.rb +++ b/Library/Homebrew/test/cmd/leaves_spec.rb @@ -31,7 +31,7 @@ RSpec.describe Homebrew::Cmd::Leaves do end end - context "when there are installed Formulae", :integration_test do + context "when there are installed Formulae", :integration_test, :no_api do it "prints all installed Formulae that are not dependencies of another installed Formula" do setup_test_formula "foo" setup_test_formula "bar" diff --git a/Library/Homebrew/test/cmd/list_spec.rb b/Library/Homebrew/test/cmd/list_spec.rb index 97a6f1466a..62ff3c8004 100644 --- a/Library/Homebrew/test/cmd/list_spec.rb +++ b/Library/Homebrew/test/cmd/list_spec.rb @@ -8,7 +8,7 @@ RSpec.describe Homebrew::Cmd::List do it_behaves_like "parseable arguments" - it "prints all installed Formulae", :integration_test do + it "prints all installed formulae", :integration_test do formulae.each do |f| (HOMEBREW_CELLAR/f/"1.0/somedir").mkpath end @@ -19,5 +19,9 @@ RSpec.describe Homebrew::Cmd::List do .and be_a_success end - # TODO: add a test for the shell fast-path (`brew_sh`) + it "prints all installed formulae and casks", :integration_test do + expect { brew_sh "list" } + .to be_a_success + .and not_to_output.to_stderr + end end diff --git a/Library/Homebrew/test/cmd/mcp-server_spec.rb b/Library/Homebrew/test/cmd/mcp-server_spec.rb new file mode 100644 index 0000000000..9a4ef1116f --- /dev/null +++ b/Library/Homebrew/test/cmd/mcp-server_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +RSpec.describe "brew mcp-server", type: :system do + it "starts the MCP server", :integration_test do + # This is the easiest way to handle a newline here. + # rubocop:disable Style/StringConcatenation + expect { brew_sh "mcp-server", "--ping" } + .to output("==> Started Homebrew MCP server...\n").to_stderr + .and output('{"jsonrpc":"2.0","id":1,"result":{}}' + "\n").to_stdout + .and be_a_success + # rubocop:enable Style/StringConcatenation + end +end diff --git a/Library/Homebrew/test/cmd/migrate_spec.rb b/Library/Homebrew/test/cmd/migrate_spec.rb index 0e592a3f03..913bfef608 100644 --- a/Library/Homebrew/test/cmd/migrate_spec.rb +++ b/Library/Homebrew/test/cmd/migrate_spec.rb @@ -6,7 +6,7 @@ require "cmd/shared_examples/args_parse" RSpec.describe Homebrew::Cmd::Migrate do it_behaves_like "parseable arguments" - it "migrates a renamed Formula", :integration_test do + it "migrates a renamed Formula", :integration_test, :no_api do setup_test_formula "testball1" setup_test_formula "testball2" install_and_rename_coretap_formula "testball1", "testball2" diff --git a/Library/Homebrew/test/cmd/missing_spec.rb b/Library/Homebrew/test/cmd/missing_spec.rb index d1cbb37d8b..3cb7353747 100644 --- a/Library/Homebrew/test/cmd/missing_spec.rb +++ b/Library/Homebrew/test/cmd/missing_spec.rb @@ -6,7 +6,7 @@ require "cmd/shared_examples/args_parse" RSpec.describe Homebrew::Cmd::Missing do it_behaves_like "parseable arguments" - it "prints missing dependencies", :integration_test do + it "prints missing dependencies", :integration_test, :no_api do setup_test_formula "foo" setup_test_formula "bar" diff --git a/Library/Homebrew/test/cmd/search_spec.rb b/Library/Homebrew/test/cmd/search_spec.rb index 78adf8855c..6efb80fe83 100644 --- a/Library/Homebrew/test/cmd/search_spec.rb +++ b/Library/Homebrew/test/cmd/search_spec.rb @@ -6,7 +6,7 @@ require "cmd/shared_examples/args_parse" RSpec.describe Homebrew::Cmd::SearchCmd do it_behaves_like "parseable arguments" - it "finds formula in search", :integration_test do + it "finds formula in search", :integration_test, :no_api do setup_test_formula "testball" expect { brew "search", "testball" } diff --git a/Library/Homebrew/test/cmd/setup-ruby_spec.rb b/Library/Homebrew/test/cmd/setup-ruby_spec.rb new file mode 100644 index 0000000000..7bff28754e --- /dev/null +++ b/Library/Homebrew/test/cmd/setup-ruby_spec.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +RSpec.describe "brew setup-ruby", type: :system do + it "installs and configures Homebrew's Ruby", :integration_test do + expect { brew_sh "setup-ruby" } + .to output("").to_stdout + .and not_to_output.to_stderr + .and be_a_success + end +end diff --git a/Library/Homebrew/test/cmd/shellenv_spec.rb b/Library/Homebrew/test/cmd/shellenv_spec.rb new file mode 100644 index 0000000000..2a241b2270 --- /dev/null +++ b/Library/Homebrew/test/cmd/shellenv_spec.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +RSpec.describe "brew shellenv", type: :system do + it "prints export statements", :integration_test do + expect { brew_sh "shellenv" } + .to output(/.*/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end +end diff --git a/Library/Homebrew/test/cmd/tap-info_spec.rb b/Library/Homebrew/test/cmd/tap-info_spec.rb index ada71038cd..78e96760da 100644 --- a/Library/Homebrew/test/cmd/tap-info_spec.rb +++ b/Library/Homebrew/test/cmd/tap-info_spec.rb @@ -16,7 +16,7 @@ RSpec.describe Homebrew::Cmd::TapInfo do end it "display brief statistics for all installed taps", :integration_test, :needs_network do - expect { brew "tap-info", "HOMEBREW_NO_INSTALL_FROM_API" => nil } + expect { brew "tap-info" } .to output(/\d+ taps?, \d+ private/).to_stdout .and not_to_output.to_stderr .and be_a_success diff --git a/Library/Homebrew/test/cmd/untap_spec.rb b/Library/Homebrew/test/cmd/untap_spec.rb index fb1d3a77b0..8100afc00e 100644 --- a/Library/Homebrew/test/cmd/untap_spec.rb +++ b/Library/Homebrew/test/cmd/untap_spec.rb @@ -18,7 +18,7 @@ RSpec.describe Homebrew::Cmd::Untap do end describe "#installed_formulae_for", :integration_test do - shared_examples "finds installed formulae in tap" do + shared_examples "finds installed formulae in tap", :no_api do def load_formula(name:, with_formula_file: false, mock_install: false) formula = if with_formula_file path = setup_test_formula(name, tap:) @@ -84,7 +84,7 @@ RSpec.describe Homebrew::Cmd::Untap do end describe "#installed_casks_for", :cask do - shared_examples "finds installed casks in tap" do + shared_examples "finds installed casks in tap", :no_api do def load_cask(token:, with_cask_file: false, mock_install: false) cask_loader = Cask::CaskLoader::FromContentLoader.new(<<~RUBY, tap:) cask '#{token}' do diff --git a/Library/Homebrew/test/cmd/uses_spec.rb b/Library/Homebrew/test/cmd/uses_spec.rb index 9cea6ade8c..85a38abbfc 100644 --- a/Library/Homebrew/test/cmd/uses_spec.rb +++ b/Library/Homebrew/test/cmd/uses_spec.rb @@ -10,7 +10,7 @@ RSpec.describe Homebrew::Cmd::Uses do it_behaves_like "parseable arguments" - it "prints the Formulae a given Formula is used by", :integration_test do + it "prints the Formulae a given Formula is used by", :integration_test, :no_api do # Included in output setup_test_formula "bar" setup_test_formula "optional", <<~RUBY @@ -46,7 +46,7 @@ RSpec.describe Homebrew::Cmd::Uses do .and be_a_success end - it "handles unavailable formula", :integration_test do + it "handles unavailable formula", :integration_test, :no_api do setup_test_formula "foo" setup_test_formula "bar" setup_test_formula "optional", <<~RUBY diff --git a/Library/Homebrew/test/compiler_selector_spec.rb b/Library/Homebrew/test/compiler_selector_spec.rb index a4fe2a9956..91e3f5358f 100644 --- a/Library/Homebrew/test/compiler_selector_spec.rb +++ b/Library/Homebrew/test/compiler_selector_spec.rb @@ -23,7 +23,7 @@ RSpec.describe CompilerSelector do end end - describe "#compiler" do + describe "#compiler", :no_api do it "defaults to cc" do expect(selector.compiler).to eq(cc) end diff --git a/Library/Homebrew/test/diagnostic_checks_spec.rb b/Library/Homebrew/test/diagnostic_checks_spec.rb index 3e1d9c0563..6249670651 100644 --- a/Library/Homebrew/test/diagnostic_checks_spec.rb +++ b/Library/Homebrew/test/diagnostic_checks_spec.rb @@ -117,7 +117,6 @@ RSpec.describe Homebrew::Diagnostic::Checks do specify "#check_for_unnecessary_core_tap" do ENV.delete("HOMEBREW_DEVELOPER") - ENV.delete("HOMEBREW_NO_INSTALL_FROM_API") expect_any_instance_of(CoreTap).to receive(:installed?).and_return(true) @@ -126,7 +125,6 @@ RSpec.describe Homebrew::Diagnostic::Checks do specify "#check_for_unnecessary_cask_tap" do ENV.delete("HOMEBREW_DEVELOPER") - ENV.delete("HOMEBREW_NO_INSTALL_FROM_API") expect_any_instance_of(CoreCaskTap).to receive(:installed?).and_return(true) diff --git a/Library/Homebrew/test/exceptions_spec.rb b/Library/Homebrew/test/exceptions_spec.rb index 27d03c3239..58bdd2fce8 100644 --- a/Library/Homebrew/test/exceptions_spec.rb +++ b/Library/Homebrew/test/exceptions_spec.rb @@ -71,7 +71,7 @@ RSpec.describe "Exception" do end context "without a dependent" do - it(:to_s) { expect(error.to_s).to eq('No available formula with the name "foo".') } + it(:to_s) { expect(error.to_s).to match(/^No available formula with the name "foo"\./) } end context "with a dependent" do @@ -80,7 +80,7 @@ RSpec.describe "Exception" do end it(:to_s) do - expect(error.to_s).to eq('No available formula with the name "foo" (dependency of foobar).') + expect(error.to_s).to match(/^No available formula with the name "foo" \(dependency of foobar\)\./) end end end diff --git a/Library/Homebrew/test/formula_auditor_spec.rb b/Library/Homebrew/test/formula_auditor_spec.rb index 8b363aebd2..3d842a1e5b 100644 --- a/Library/Homebrew/test/formula_auditor_spec.rb +++ b/Library/Homebrew/test/formula_auditor_spec.rb @@ -519,7 +519,7 @@ RSpec.describe Homebrew::FormulaAuditor do fa.audit_specs expect(fa.problems.first[:message]) - .to match("resource name should be `FooSomething` to match the PyPI package name") + .to match("`resource` name should be 'FooSomething' to match the PyPI package name") end it "reports a problem if the resource name does not match the python wheel name" do @@ -538,7 +538,7 @@ RSpec.describe Homebrew::FormulaAuditor do fa.audit_specs expect(fa.problems.first[:message]) - .to match("resource name should be `FooSomething` to match the PyPI package name") + .to match("`resource` name should be 'FooSomething' to match the PyPI package name") end end @@ -788,7 +788,7 @@ RSpec.describe Homebrew::FormulaAuditor do RUBY fa.audit_specs - expect(fa.problems.first[:message]).to match "Versioned formulae should not have a `HEAD` spec" + expect(fa.problems.first[:message]).to match "Versioned formulae should not have a `head` spec" end it "allows versioned formulae on the allowlist to have a `HEAD` spec" do @@ -911,7 +911,7 @@ RSpec.describe Homebrew::FormulaAuditor do context "when uncommitted should not decrease" do before { formula_gsub "foo-1.0.tar.gz", "foo-0.9.tar.gz" } - it { is_expected.to match("stable version should not decrease (from 1.0 to 0.9)") } + it { is_expected.to match("Stable: version should not decrease (from 1.0 to 0.9)") } end context "when committed can decrease" do @@ -991,31 +991,31 @@ RSpec.describe Homebrew::FormulaAuditor do describe "with the same version, should not decrease" do before { formula_gsub_origin_commit "revision 2", "revision 1" } - it { is_expected.to match("revision should not decrease (from 2 to 1)") } + it { is_expected.to match("`revision` should not decrease (from 2 to 1)") } end describe "should not be removed with the same version" do before { formula_gsub_origin_commit "revision 2" } - it { is_expected.to match("revision should not decrease (from 2 to 0)") } + it { is_expected.to match("`revision` should not decrease (from 2 to 0)") } end describe "should not decrease with the same, uncommitted version" do before { formula_gsub "revision 2", "revision 1" } - it { is_expected.to match("revision should not decrease (from 2 to 1)") } + it { is_expected.to match("`revision` should not decrease (from 2 to 1)") } end describe "should be removed with a newer version" do before { formula_gsub_origin_commit "foo-1.0.tar.gz", "foo-1.1.tar.gz" } - it { is_expected.to match("'revision 2' should be removed") } + it { is_expected.to match("`revision 2` should be removed") } end describe "should be removed with a newer local version" do before { formula_gsub "foo-1.0.tar.gz", "foo-1.1.tar.gz" } - it { is_expected.to match("'revision 2' should be removed") } + it { is_expected.to match("`revision 2` should be removed") } end describe "should not warn on an newer version revision removal" do @@ -1044,7 +1044,7 @@ RSpec.describe Homebrew::FormulaAuditor do formula_gsub "revision 2", "revision 4" end - it { is_expected.to match("revisions should only increment by 1") } + it { is_expected.to match("`revision` should only increment by 1") } end describe "should not warn on past increment by more than 1" do @@ -1094,7 +1094,7 @@ RSpec.describe Homebrew::FormulaAuditor do describe "should not decrease with the same version" do before { formula_gsub_origin_commit "version_scheme 1" } - it { is_expected.to match("version_scheme should not decrease (from 1 to 0)") } + it { is_expected.to match("`version_scheme` should not decrease (from 1 to 0)") } end describe "should not decrease with a new version" do @@ -1104,7 +1104,7 @@ RSpec.describe Homebrew::FormulaAuditor do formula_gsub_origin_commit "version_scheme 1", "" end - it { is_expected.to match("version_scheme should not decrease (from 1 to 0)") } + it { is_expected.to match("`version_scheme` should not decrease (from 1 to 0)") } end describe "should only increment by 1" do @@ -1115,7 +1115,7 @@ RSpec.describe Homebrew::FormulaAuditor do formula_gsub_origin_commit "# no version_scheme", "version_scheme 3" end - it { is_expected.to match("version_schemes should only increment by 1") } + it { is_expected.to match("`version_scheme` should only increment by 1") } end end end @@ -1261,7 +1261,7 @@ RSpec.describe Homebrew::FormulaAuditor do allow(File).to receive(:open).and_return("") end - specify "it warns when conflicting with non-existing formula" do + specify "it warns when conflicting with non-existing formula", :no_api do foo = formula("foo") do url "https://brew.sh/bar-1.0.tgz" @@ -1275,7 +1275,7 @@ RSpec.describe Homebrew::FormulaAuditor do .to match("Can't find conflicting formula \"bar\"") end - specify "it warns when conflicting with itself" do + specify "it warns when conflicting with itself", :no_api do foo = formula("foo") do url "https://brew.sh/bar-1.0.tgz" @@ -1290,7 +1290,7 @@ RSpec.describe Homebrew::FormulaAuditor do .to match("Formula should not conflict with itself") end - specify "it warns when another formula does not have a symmetric conflict" do + specify "it warns when another formula does not have a symmetric conflict", :no_api do stub_formula_loader formula("gcc") { url "gcc-1.0" } stub_formula_loader formula("glibc") { url "glibc-1.0" } diff --git a/Library/Homebrew/test/formula_spec.rb b/Library/Homebrew/test/formula_spec.rb index 045b27b3a0..ada1618966 100644 --- a/Library/Homebrew/test/formula_spec.rb +++ b/Library/Homebrew/test/formula_spec.rb @@ -1046,7 +1046,13 @@ RSpec.describe Formula do before do # Use a more limited os list to shorten the variations hash os_list = [:monterey, :big_sur, :catalina, :mojave, :linux] - stub_const("OnSystem::ALL_OS_ARCH_COMBINATIONS", os_list.product(OnSystem::ARCH_OPTIONS)) + valid_tags = os_list.product(OnSystem::ARCH_OPTIONS).filter_map do |os, arch| + tag = Utils::Bottles::Tag.new(system: os, arch:) + next unless tag.valid_combination? + + tag + end + stub_const("OnSystem::VALID_OS_ARCH_TAGS", valid_tags) # For consistency, always run on Monterey and ARM allow(MacOS).to receive(:version).and_return(MacOSVersion.new("12")) diff --git a/Library/Homebrew/test/formulary_spec.rb b/Library/Homebrew/test/formulary_spec.rb index 3e344cad5c..64897d7c30 100644 --- a/Library/Homebrew/test/formulary_spec.rb +++ b/Library/Homebrew/test/formulary_spec.rb @@ -55,7 +55,7 @@ RSpec.describe Formulary do end describe "::factory" do - context "without the API" do + context "without the API", :no_api do before do formula_path.dirname.mkpath formula_path.write formula_content @@ -129,7 +129,7 @@ RSpec.describe Formulary do end.to raise_error(FormulaUnavailableError) end - it "returns a Formula when given a URL", :needs_utils_curl, :no_api do + it "returns a Formula when given a URL", :needs_utils_curl do formula = described_class.factory("file://#{formula_path}") expect(formula).to be_a(Formula) end @@ -398,8 +398,6 @@ RSpec.describe Formulary do end before do - ENV.delete("HOMEBREW_NO_INSTALL_FROM_API") - # avoid unnecessary network calls allow(Homebrew::API::Formula).to receive_messages(all_aliases: {}, all_renames: {}) allow(CoreTap.instance).to receive(:tap_migrations).and_return({}) @@ -645,16 +643,12 @@ RSpec.describe Formulary do end context "when given a tapped name" do - it "returns a `FromTapLoader`" do + it "returns a `FromTapLoader`", :no_api do expect(described_class.loader_for("homebrew/core/gcc")).to be_a Formulary::FromTapLoader end end - context "when not using the API" do - before do - ENV["HOMEBREW_NO_INSTALL_FROM_API"] = "1" - end - + context "when not using the API", :no_api do context "when a formula is migrated" do let(:token) { "foo" } diff --git a/Library/Homebrew/test/github_runner_matrix_spec.rb b/Library/Homebrew/test/github_runner_matrix_spec.rb index 2920ca6698..7379e0d7d9 100644 --- a/Library/Homebrew/test/github_runner_matrix_spec.rb +++ b/Library/Homebrew/test/github_runner_matrix_spec.rb @@ -3,16 +3,17 @@ require "github_runner_matrix" require "test/support/fixtures/testball" -RSpec.describe GitHubRunnerMatrix do +RSpec.describe GitHubRunnerMatrix, :no_api do before do allow(ENV).to receive(:fetch).with("HOMEBREW_LINUX_RUNNER").and_return("ubuntu-latest") allow(ENV).to receive(:fetch).with("HOMEBREW_MACOS_LONG_TIMEOUT", "false").and_return("false") allow(ENV).to receive(:fetch).with("HOMEBREW_MACOS_BUILD_ON_GITHUB_RUNNER", "false").and_return("false") allow(ENV).to receive(:fetch).with("GITHUB_RUN_ID").and_return("12345") - allow(ENV).to receive(:fetch).with("HOMEBREW_NO_INSTALL_FROM_API", nil).and_call_original allow(ENV).to receive(:fetch).with("HOMEBREW_EVAL_ALL", nil).and_call_original allow(ENV).to receive(:fetch).with("HOMEBREW_SIMULATE_MACOS_ON_LINUX", nil).and_call_original allow(ENV).to receive(:fetch).with("HOMEBREW_FORBID_PACKAGES_FROM_PATHS", nil).and_call_original + allow(ENV).to receive(:fetch).with("HOMEBREW_DEVELOPER", nil).and_call_original + allow(ENV).to receive(:fetch).with("HOMEBREW_NO_INSTALL_FROM_API", nil).and_call_original end let(:newest_supported_macos) do diff --git a/Library/Homebrew/test/mcp_server_spec.rb b/Library/Homebrew/test/mcp_server_spec.rb new file mode 100644 index 0000000000..98f31469cf --- /dev/null +++ b/Library/Homebrew/test/mcp_server_spec.rb @@ -0,0 +1,249 @@ +# frozen_string_literal: true + +require "mcp_server" +require "stringio" +require "timeout" + +RSpec.describe Homebrew::McpServer do + let(:stdin) { StringIO.new } + let(:stdout) { StringIO.new } + let(:stderr) { StringIO.new } + let(:server) { described_class.new(stdin:, stdout:, stderr:) } + let(:jsonrpc) { Homebrew::McpServer::JSON_RPC_VERSION } + let(:id) { Random.rand(1000) } + let(:code) { Homebrew::McpServer::ERROR_CODE } + + describe "#initialize" do + it "sets debug_logging to false by default" do + expect(server.debug_logging?).to be(false) + end + + it "sets debug_logging to true if --debug is in ARGV" do + stub_const("ARGV", ["--debug"]) + expect(server.debug_logging?).to be(true) + end + + it "sets debug_logging to true if -d is in ARGV" do + stub_const("ARGV", ["-d"]) + expect(server.debug_logging?).to be(true) + end + end + + describe "#debug and #log" do + it "logs debug output when debug_logging is true" do + stub_const("ARGV", ["--debug"]) + server.debug("foo") + expect(stderr.string).to include("foo") + end + + it "does not log debug output when debug_logging is false" do + server.debug("foo") + expect(stderr.string).to eq("") + end + + it "logs to stderr" do + server.log("bar") + expect(stderr.string).to include("bar") + end + end + + describe "#handle_request" do + it "responds to initialize method" do + request = { "id" => id, "method" => "initialize" } + result = server.handle_request(request) + expect(result).to eq({ + jsonrpc:, + id:, + result: { + protocolVersion: Homebrew::McpServer::MCP_PROTOCOL_VERSION, + capabilities: { + tools: { listChanged: false }, + prompts: {}, + resources: {}, + logging: {}, + roots: {}, + }, + serverInfo: Homebrew::McpServer::SERVER_INFO, + }, + }) + end + + it "responds to resources/list" do + request = { "id" => id, "method" => "resources/list" } + result = server.handle_request(request) + expect(result).to eq({ jsonrpc:, id:, result: { resources: [] } }) + end + + it "responds to resources/templates/list" do + request = { "id" => id, "method" => "resources/templates/list" } + result = server.handle_request(request) + expect(result).to eq({ jsonrpc:, id:, result: { resourceTemplates: [] } }) + end + + it "responds to prompts/list" do + request = { "id" => id, "method" => "prompts/list" } + result = server.handle_request(request) + expect(result).to eq({ jsonrpc:, id:, result: { prompts: [] } }) + end + + it "responds to ping" do + request = { "id" => id, "method" => "ping" } + result = server.handle_request(request) + expect(result).to eq({ jsonrpc:, id:, result: {} }) + end + + it "responds to get_server_info" do + request = { "id" => id, "method" => "get_server_info" } + result = server.handle_request(request) + expect(result).to eq({ jsonrpc:, id:, result: Homebrew::McpServer::SERVER_INFO }) + end + + it "responds to logging/setLevel with debug" do + request = { "id" => id, "method" => "logging/setLevel", "params" => { "level" => "debug" } } + result = server.handle_request(request) + expect(server.debug_logging?).to be(true) + expect(result).to eq({ jsonrpc:, id:, result: {} }) + end + + it "responds to logging/setLevel with non-debug" do + request = { "id" => id, "method" => "logging/setLevel", "params" => { "level" => "info" } } + result = server.handle_request(request) + expect(server.debug_logging?).to be(false) + expect(result).to eq({ jsonrpc:, id:, result: {} }) + end + + it "responds to notifications/initialized" do + request = { "id" => id, "method" => "notifications/initialized" } + expect(server.handle_request(request)).to be_nil + end + + it "responds to notifications/cancelled" do + request = { "id" => id, "method" => "notifications/cancelled" } + expect(server.handle_request(request)).to be_nil + end + + it "responds to tools/list" do + request = { "id" => id, "method" => "tools/list" } + result = server.handle_request(request) + expect(result[:result][:tools]).to match_array(Homebrew::McpServer::TOOLS.values) + end + + Homebrew::McpServer::TOOLS.each do |tool_name, tool_definition| + it "responds to tools/call for #{tool_name}" do + allow(server).to receive(:`).and_return("output for #{tool_name}") + arguments = {} + Array(tool_definition[:required]).each do |required_key| + arguments[required_key] = "dummy" + end + request = { + "id" => id, + "method" => "tools/call", + "params" => { + "name" => tool_name.to_s, + "arguments" => arguments, + }, + } + result = server.handle_request(request) + expect(result).to eq({ + jsonrpc: jsonrpc, + id: id, + result: { content: [{ type: "text", text: "output for #{tool_name}" }] }, + }) + end + end + + it "responds to tools/call for unknown tool" do + request = { "id" => id, "method" => "tools/call", "params" => { "name" => "not_a_tool", "arguments" => {} } } + result = server.handle_request(request) + expect(result).to eq({ jsonrpc:, id:, error: { message: "Unknown tool", code: } }) + end + + it "responds with error for unknown method" do + request = { "id" => id, "method" => "not_a_method" } + result = server.handle_request(request) + expect(result).to eq({ jsonrpc:, id:, error: { message: "Method not found", code: } }) + end + + it "returns nil if id is nil" do + request = { "method" => "initialize" } + expect(server.handle_request(request)).to be_nil + end + end + + describe "#respond_result" do + it "returns nil if id is nil" do + expect(server.send(:respond_result, nil, {})).to be_nil + end + + it "returns a result hash if id is present" do + result = server.respond_result(id, { foo: "bar" }) + expect(result).to eq({ jsonrpc:, id:, result: { foo: "bar" } }) + end + end + + describe "#respond_error" do + it "returns an error hash" do + result = server.respond_error(id, "fail") + expect(result).to eq({ jsonrpc:, id:, error: { message: "fail", code: } }) + end + end + + describe "#run" do + let(:sleep_time) { 0.001 } + + it "runs the loop and exits cleanly on interrupt" do + stub_const("ARGV", ["--debug"]) + stdin.puts({ id:, method: "ping" }.to_json) + stdin.rewind + server_thread = Thread.new do + server.run + rescue SystemExit + # expected, do nothing + end + + response_hash_string = "Response: {" + sleep(sleep_time) + server_thread.raise(Interrupt) + server_thread.join + + expect(stderr.string).to include(response_hash_string) + end + + it "runs the loop and logs 'Response: nil' when handle_request returns nil" do + stub_const("ARGV", ["--debug"]) + stdin.puts({ id:, method: "notifications/initialized" }.to_json) + stdin.rewind + server_thread = Thread.new do + server.run + rescue SystemExit + # expected, do nothing + end + + response_nil_string = "Response: nil" + sleep(sleep_time) + server_thread.raise(Interrupt) + server_thread.join + + expect(stderr.string).to include(response_nil_string) + end + + it "exits on Interrupt" do + allow(stdin).to receive(:gets).and_raise(Interrupt) + expect do + server.run + rescue + SystemExit + end.to raise_error(SystemExit) + end + + it "exits on error" do + allow(stdin).to receive(:gets).and_raise(StandardError, "fail") + expect do + server.run + rescue + SystemExit + end.to raise_error(SystemExit) + expect(stderr.string).to match(/Error: fail/) + end + end +end diff --git a/Library/Homebrew/test/rubocops/cask/no_overrides_spec.rb b/Library/Homebrew/test/rubocops/cask/no_overrides_spec.rb index 3b68c05a32..ba7de8e7b4 100644 --- a/Library/Homebrew/test/rubocops/cask/no_overrides_spec.rb +++ b/Library/Homebrew/test/rubocops/cask/no_overrides_spec.rb @@ -173,4 +173,43 @@ RSpec.describe RuboCop::Cop::Cask::NoOverrides, :config do end CASK end + + it "accepts when there is a top-level `depends_on macos:` stanza" do + expect_no_offenses <<~CASK + cask 'foo' do + version '1.2.3' + url 'https://brew.sh/foo.pkg' + + depends_on macos: ">= :sequoia" + + name 'Foo' + end + CASK + end + + it "reports an offense when `on_*` blocks contain a `depends_on macos:` stanza" do + expect_offense <<~CASK + cask 'foo' do + version '1.2.3' + + on_sequoia :or_newer do + sha256 "aaa" + url "https://brew.sh/foo-mac.dmg" + + depends_on macos: ">= :sequoia" + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not use a `depends_on macos:` stanza inside an `on_{system}` block. Add it once to specify the oldest macOS supported by any version in the cask. + end + + on_arm do + sha256 "bbb" + url "https://brew.sh/foo-arm.dmg" + + depends_on macos: ">= :sequoia" + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not use a `depends_on macos:` stanza inside an `on_{system}` block. Add it once to specify the oldest macOS supported by any version in the cask. + end + + name 'Foo' + end + CASK + end end diff --git a/Library/Homebrew/test/rubocops/cask/on_system_conditionals_spec.rb b/Library/Homebrew/test/rubocops/cask/on_system_conditionals_spec.rb index 7777d226af..fbbc8fc645 100644 --- a/Library/Homebrew/test/rubocops/cask/on_system_conditionals_spec.rb +++ b/Library/Homebrew/test/rubocops/cask/on_system_conditionals_spec.rb @@ -19,7 +19,7 @@ RSpec.describe RuboCop::Cop::Cask::OnSystemConditionals, :config do cask 'foo' do postflight do on_intel do - ^^^^^^^^ Don't use `on_intel` in `postflight do`, use `if Hardware::CPU.intel?` instead. + ^^^^^^^^ Instead of using `on_intel` in `postflight do`, use `if Hardware::CPU.intel?`. foobar end end @@ -43,7 +43,7 @@ RSpec.describe RuboCop::Cop::Cask::OnSystemConditionals, :config do cask 'foo' do postflight do on_monterey do - ^^^^^^^^^^^ Don't use `on_monterey` in `postflight do`, use `if MacOS.version == :monterey` instead. + ^^^^^^^^^^^ Instead of using `on_monterey` in `postflight do`, use `if MacOS.version == :monterey`. foobar end end @@ -67,7 +67,7 @@ RSpec.describe RuboCop::Cop::Cask::OnSystemConditionals, :config do cask 'foo' do postflight do on_monterey :or_older do - ^^^^^^^^^^^^^^^^^^^^^ Don't use `on_monterey :or_older` in `postflight do`, use `if MacOS.version <= :monterey` instead. + ^^^^^^^^^^^^^^^^^^^^^ Instead of using `on_monterey :or_older` in `postflight do`, use `if MacOS.version <= :monterey`. foobar end end @@ -171,7 +171,7 @@ RSpec.describe RuboCop::Cop::Cask::OnSystemConditionals, :config do expect_offense <<~CASK cask 'foo' do if Hardware::CPU.arm? && other_condition - ^^^^^^^^^^^^^^^^^^ Don't use `Hardware::CPU.arm?`, use `on_arm` and `on_intel` blocks instead. + ^^^^^^^^^^^^^^^^^^ Instead of `Hardware::CPU.arm?`, use `on_arm` and `on_intel` blocks. sha256 "67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94" else sha256 "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b" @@ -184,7 +184,7 @@ RSpec.describe RuboCop::Cop::Cask::OnSystemConditionals, :config do expect_offense <<~CASK cask 'foo' do if Hardware::CPU.intel? && other_condition - ^^^^^^^^^^^^^^^^^^^^ Don't use `Hardware::CPU.intel?`, use `on_arm` and `on_intel` blocks instead. + ^^^^^^^^^^^^^^^^^^^^ Instead of `Hardware::CPU.intel?`, use `on_arm` and `on_intel` blocks. sha256 "67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94" else sha256 "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b" @@ -200,7 +200,7 @@ RSpec.describe RuboCop::Cop::Cask::OnSystemConditionals, :config do sha256 "67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94" url "https://example.com/foo-#{version}-#{Hardware::CPU.arch}.zip" - ^^^^^^^^^^^^^^^^^^ Don't use `Hardware::CPU.arch`, use `on_arm` and `on_intel` blocks instead. + ^^^^^^^^^^^^^^^^^^ Instead of `Hardware::CPU.arch`, use `on_arm` and `on_intel` blocks. end CASK end @@ -211,7 +211,7 @@ RSpec.describe RuboCop::Cop::Cask::OnSystemConditionals, :config do expect_offense <<~CASK cask 'foo' do if MacOS.version == :catalina - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't use `if MacOS.version == :catalina`, use `on_catalina do` instead. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Instead of `if MacOS.version == :catalina`, use `on_catalina do`. version "1.0.0" else version "2.0.0" @@ -224,7 +224,7 @@ RSpec.describe RuboCop::Cop::Cask::OnSystemConditionals, :config do expect_offense <<~CASK cask 'foo' do if MacOS.version <= :catalina - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't use `if MacOS.version <= :catalina`, use `on_catalina :or_older do` instead. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Instead of `if MacOS.version <= :catalina`, use `on_catalina :or_older do`. version "1.0.0" else version "2.0.0" @@ -237,7 +237,7 @@ RSpec.describe RuboCop::Cop::Cask::OnSystemConditionals, :config do expect_offense <<~CASK cask 'foo' do if MacOS.version >= :catalina - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't use `if MacOS.version >= :catalina`, use `on_catalina :or_newer do` instead. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Instead of `if MacOS.version >= :catalina`, use `on_catalina :or_newer do`. version "1.0.0" else version "2.0.0" diff --git a/Library/Homebrew/test/rubocops/caveats_spec.rb b/Library/Homebrew/test/rubocops/caveats_spec.rb index 93a80060be..6b262fd278 100644 --- a/Library/Homebrew/test/rubocops/caveats_spec.rb +++ b/Library/Homebrew/test/rubocops/caveats_spec.rb @@ -13,7 +13,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Caveats do url "https://brew.sh/foo-1.0.tgz" def caveats "setuid" - ^^^^^^^^ FormulaAudit/Caveats: Don't recommend `setuid` in the caveats, suggest `sudo` instead. + ^^^^^^^^ FormulaAudit/Caveats: Instead of recommending `setuid` in the caveats, suggest `sudo`. end end RUBY diff --git a/Library/Homebrew/test/rubocops/checksum/checksum_case_spec.rb b/Library/Homebrew/test/rubocops/checksum/checksum_case_spec.rb index c05e29827d..612a0b5383 100644 --- a/Library/Homebrew/test/rubocops/checksum/checksum_case_spec.rb +++ b/Library/Homebrew/test/rubocops/checksum/checksum_case_spec.rb @@ -13,12 +13,12 @@ RSpec.describe RuboCop::Cop::FormulaAudit::ChecksumCase do stable do url "https://github.com/foo-lang/foo-compiler/archive/0.18.0.tar.gz" sha256 "5cf6e1ae0A645b426c0a7cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea0e9a" - ^ FormulaAudit/ChecksumCase: sha256 should be lowercase + ^ FormulaAudit/ChecksumCase: `sha256` should be lowercase resource "foo-package" do url "https://github.com/foo-lang/foo-package/archive/0.18.0.tar.gz" sha256 "5cf6e1Ae0a645b426b047aa4cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea9" - ^ FormulaAudit/ChecksumCase: sha256 should be lowercase + ^ FormulaAudit/ChecksumCase: `sha256` should be lowercase end end end @@ -32,7 +32,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::ChecksumCase do resource "foo-outside" do url "https://github.com/foo-lang/foo-outside/archive/0.18.0.tar.gz" sha256 "A4cc7cd3f7d1605ffa1ac5755cf6e1ae0a645b426b047a6a39a8b2268ddc7ea9" - ^ FormulaAudit/ChecksumCase: sha256 should be lowercase + ^ FormulaAudit/ChecksumCase: `sha256` should be lowercase end stable do url "https://github.com/foo-lang/foo-compiler/archive/0.18.0.tar.gz" diff --git a/Library/Homebrew/test/rubocops/checksum/checksum_spec.rb b/Library/Homebrew/test/rubocops/checksum/checksum_spec.rb index a50b7122a7..b82593f96b 100644 --- a/Library/Homebrew/test/rubocops/checksum/checksum_spec.rb +++ b/Library/Homebrew/test/rubocops/checksum/checksum_spec.rb @@ -13,12 +13,12 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Checksum do stable do url "https://github.com/foo-lang/foo-compiler/archive/0.18.0.tar.gz" sha256 "" - ^^ FormulaAudit/Checksum: sha256 is empty + ^^ FormulaAudit/Checksum: `sha256` is empty resource "foo-package" do url "https://github.com/foo-lang/foo-package/archive/0.18.0.tar.gz" sha256 "" - ^^ FormulaAudit/Checksum: sha256 is empty + ^^ FormulaAudit/Checksum: `sha256` is empty end end end @@ -32,12 +32,12 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Checksum do stable do url "https://github.com/foo-lang/foo-compiler/archive/0.18.0.tar.gz" sha256 "5cf6e1ae0a645b426c0474cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea0e9ad" - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Checksum: sha256 should be 64 characters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Checksum: `sha256` should be 64 characters resource "foo-package" do url "https://github.com/foo-lang/foo-package/archive/0.18.0.tar.gz" sha256 "5cf6e1ae0a645b426c047aaa4cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea0e9" - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Checksum: sha256 should be 64 characters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Checksum: `sha256` should be 64 characters end end end @@ -51,12 +51,12 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Checksum do stable do url "https://github.com/foo-lang/foo-compiler/archive/0.18.0.tar.gz" sha256 "5cf6e1ae0a645b426c0k7cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea0e9a" - ^ FormulaAudit/Checksum: sha256 contains invalid characters + ^ FormulaAudit/Checksum: `sha256` contains invalid characters resource "foo-package" do url "https://github.com/foo-lang/foo-package/archive/0.18.0.tar.gz" sha256 "5cf6e1ae0a645b426x047aa4cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea9" - ^ FormulaAudit/Checksum: sha256 contains invalid characters + ^ FormulaAudit/Checksum: `sha256` contains invalid characters end end end @@ -70,7 +70,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Checksum do bottle do sha256 catalina: "5cf6e1ae0a645b426c0474cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea0e9ad" - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Checksum: sha256 should be 64 characters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Checksum: `sha256` should be 64 characters end end RUBY @@ -83,7 +83,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Checksum do bottle do sha256 cellar: :any, catalina: "5cf6e1ae0a645b426c0474cc7cd3f7d1605ffa1ac5756a39a8b2268ddc7ea0e9ad" - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Checksum: sha256 should be 64 characters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Checksum: `sha256` should be 64 characters end end RUBY diff --git a/Library/Homebrew/test/rubocops/class/class_name_spec.rb b/Library/Homebrew/test/rubocops/class/class_name_spec.rb index 78050236a1..49fbc0812f 100644 --- a/Library/Homebrew/test/rubocops/class/class_name_spec.rb +++ b/Library/Homebrew/test/rubocops/class/class_name_spec.rb @@ -14,7 +14,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::ClassName do it "reports and corrects an offense when using ScriptFileFormula" do expect_offense(<<~RUBY) class Foo < ScriptFileFormula - ^^^^^^^^^^^^^^^^^ FormulaAudit/ClassName: ScriptFileFormula is deprecated, use Formula instead + ^^^^^^^^^^^^^^^^^ FormulaAudit/ClassName: `ScriptFileFormula` is deprecated, use `Formula` instead url 'https://brew.sh/foo-1.0.tgz' end RUBY @@ -24,7 +24,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::ClassName do it "reports and corrects an offense when using GithubGistFormula" do expect_offense(<<~RUBY) class Foo < GithubGistFormula - ^^^^^^^^^^^^^^^^^ FormulaAudit/ClassName: GithubGistFormula is deprecated, use Formula instead + ^^^^^^^^^^^^^^^^^ FormulaAudit/ClassName: `GithubGistFormula` is deprecated, use `Formula` instead url 'https://brew.sh/foo-1.0.tgz' end RUBY @@ -34,7 +34,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::ClassName do it "reports and corrects an offense when using AmazonWebServicesFormula" do expect_offense(<<~RUBY) class Foo < AmazonWebServicesFormula - ^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/ClassName: AmazonWebServicesFormula is deprecated, use Formula instead + ^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/ClassName: `AmazonWebServicesFormula` is deprecated, use `Formula` instead url 'https://brew.sh/foo-1.0.tgz' end RUBY diff --git a/Library/Homebrew/test/rubocops/class/test_spec.rb b/Library/Homebrew/test/rubocops/class/test_spec.rb index cabeddb71e..deb36fc66f 100644 --- a/Library/Homebrew/test/rubocops/class/test_spec.rb +++ b/Library/Homebrew/test/rubocops/class/test_spec.rb @@ -6,46 +6,46 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Test do subject(:cop) { described_class.new } it "reports and corrects an offense when /usr/local/bin is found in test calls" do - expect_offense(<<~RUBY) + expect_offense(<<~'RUBY') class Foo < Formula url 'https://brew.sh/foo-1.0.tgz' test do system "/usr/local/bin/test" - ^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Test: use \#{bin} instead of /usr/local/bin in system + ^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Test: Use `#{bin}` instead of `/usr/local/bin` in `system` end end RUBY - expect_correction(<<~RUBY) + expect_correction(<<~'RUBY') class Foo < Formula url 'https://brew.sh/foo-1.0.tgz' test do - system "\#{bin}/test" + system "#{bin}/test" end end RUBY end it "reports and corrects an offense when passing 0 as the second parameter to shell_output" do - expect_offense(<<~RUBY) + expect_offense(<<~'RUBY') class Foo < Formula url 'https://brew.sh/foo-1.0.tgz' test do - shell_output("\#{bin}/test", 0) - ^ FormulaAudit/Test: Passing 0 to shell_output() is redundant + shell_output("#{bin}/test", 0) + ^ FormulaAudit/Test: Passing 0 to `shell_output` is redundant end end RUBY - expect_correction(<<~RUBY) + expect_correction(<<~'RUBY') class Foo < Formula url 'https://brew.sh/foo-1.0.tgz' test do - shell_output("\#{bin}/test") + shell_output("#{bin}/test") end end RUBY diff --git a/Library/Homebrew/test/rubocops/components_order_spec.rb b/Library/Homebrew/test/rubocops/components_order_spec.rb index 8fce98e573..a52843b836 100644 --- a/Library/Homebrew/test/rubocops/components_order_spec.rb +++ b/Library/Homebrew/test/rubocops/components_order_spec.rb @@ -511,7 +511,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::ComponentsOrder do end on_macos do - ^^^^^^^^^^^ FormulaAudit/ComponentsOrder: there can only be one `on_macos` block in a formula. + ^^^^^^^^^^^ FormulaAudit/ComponentsOrder: There can only be one `on_macos` block in a formula. depends_on "foo" end end @@ -527,7 +527,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::ComponentsOrder do end on_linux do - ^^^^^^^^^^^ FormulaAudit/ComponentsOrder: there can only be one `on_linux` block in a formula. + ^^^^^^^^^^^ FormulaAudit/ComponentsOrder: There can only be one `on_linux` block in a formula. depends_on "foo" end end @@ -543,7 +543,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::ComponentsOrder do end on_intel do - ^^^^^^^^^^^ FormulaAudit/ComponentsOrder: there can only be one `on_intel` block in a formula. + ^^^^^^^^^^^ FormulaAudit/ComponentsOrder: There can only be one `on_intel` block in a formula. depends_on "foo" end end @@ -559,7 +559,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::ComponentsOrder do end on_arm do - ^^^^^^^^^ FormulaAudit/ComponentsOrder: there can only be one `on_arm` block in a formula. + ^^^^^^^^^ FormulaAudit/ComponentsOrder: There can only be one `on_arm` block in a formula. depends_on "foo" end end @@ -575,7 +575,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::ComponentsOrder do end on_monterey do - ^^^^^^^^^^^^^^ FormulaAudit/ComponentsOrder: there can only be one `on_monterey` block in a formula. + ^^^^^^^^^^^^^^ FormulaAudit/ComponentsOrder: There can only be one `on_monterey` block in a formula. depends_on "foo" end end @@ -591,7 +591,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::ComponentsOrder do end on_monterey :or_older do - ^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/ComponentsOrder: there can only be one `on_monterey` block in a formula. + ^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/ComponentsOrder: There can only be one `on_monterey` block in a formula. depends_on "foo" end end @@ -881,7 +881,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::ComponentsOrder do url "https://brew.sh/foo-1.0.tgz" resource do - ^^^^^^^^^^^ FormulaAudit/ComponentsOrder: there can only be one `on_macos` block in a resource block. + ^^^^^^^^^^^ FormulaAudit/ComponentsOrder: There can only be one `on_macos` block in a resource block. on_macos do url "https://brew.sh/resource1.tar.gz" sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35" @@ -902,7 +902,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::ComponentsOrder do url "https://brew.sh/foo-1.0.tgz" resource do - ^^^^^^^^^^^ FormulaAudit/ComponentsOrder: there can only be one `on_linux` block in a resource block. + ^^^^^^^^^^^ FormulaAudit/ComponentsOrder: There can only be one `on_linux` block in a resource block. on_linux do url "https://brew.sh/resource1.tar.gz" sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35" @@ -923,7 +923,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::ComponentsOrder do url "https://brew.sh/foo-1.0.tgz" resource do - ^^^^^^^^^^^ FormulaAudit/ComponentsOrder: there can only be one `on_intel` block in a resource block. + ^^^^^^^^^^^ FormulaAudit/ComponentsOrder: There can only be one `on_intel` block in a resource block. on_intel do url "https://brew.sh/resource1.tar.gz" sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35" @@ -944,7 +944,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::ComponentsOrder do url "https://brew.sh/foo-1.0.tgz" resource do - ^^^^^^^^^^^ FormulaAudit/ComponentsOrder: there can only be one `on_arm` block in a resource block. + ^^^^^^^^^^^ FormulaAudit/ComponentsOrder: There can only be one `on_arm` block in a resource block. on_arm do url "https://brew.sh/resource1.tar.gz" sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35" @@ -965,7 +965,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::ComponentsOrder do url "https://brew.sh/foo-1.0.tgz" resource do - ^^^^^^^^^^^ FormulaAudit/ComponentsOrder: there can only be one `on_monterey` block in a resource block. + ^^^^^^^^^^^ FormulaAudit/ComponentsOrder: There can only be one `on_monterey` block in a resource block. on_monterey do url "https://brew.sh/resource1.tar.gz" sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35" diff --git a/Library/Homebrew/test/rubocops/dependency_order_spec.rb b/Library/Homebrew/test/rubocops/dependency_order_spec.rb index bbcfe253e4..80a465a938 100644 --- a/Library/Homebrew/test/rubocops/dependency_order_spec.rb +++ b/Library/Homebrew/test/rubocops/dependency_order_spec.rb @@ -13,7 +13,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::DependencyOrder do url "https://brew.sh/foo-1.0.tgz" uses_from_macos "apple" if build.with? "foo" uses_from_macos "foo" => :optional - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: dependency "foo" (line 5) should be put before dependency "apple" (line 4) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: `dependency "foo"` (line 5) should be put before `dependency "apple"` (line 4) end RUBY @@ -34,7 +34,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::DependencyOrder do url "https://brew.sh/foo-1.0.tgz" uses_from_macos "foo" uses_from_macos "bar" - ^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: dependency "bar" (line 5) should be put before dependency "foo" (line 4) + ^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: `dependency "bar"` (line 5) should be put before `dependency "foo"` (line 4) end RUBY @@ -55,7 +55,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::DependencyOrder do url "https://brew.sh/foo-1.0.tgz" uses_from_macos FooRequirement uses_from_macos "bar" - ^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: dependency "bar" (line 5) should be put before dependency "FooRequirement" (line 4) + ^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: `dependency "bar"` (line 5) should be put before `dependency "FooRequirement"` (line 4) end RUBY @@ -77,13 +77,13 @@ RSpec.describe RuboCop::Cop::FormulaAudit::DependencyOrder do head do uses_from_macos "apple" if build.with? "foo" uses_from_macos "bar" - ^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: dependency "bar" (line 6) should be put before dependency "apple" (line 5) + ^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: `dependency "bar"` (line 6) should be put before `dependency "apple"` (line 5) uses_from_macos "foo" => :optional - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: dependency "foo" (line 7) should be put before dependency "apple" (line 5) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: `dependency "foo"` (line 7) should be put before `dependency "apple"` (line 5) end uses_from_macos "apple" if build.with? "foo" uses_from_macos "foo" => :optional - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: dependency "foo" (line 10) should be put before dependency "apple" (line 9) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: `dependency "foo"` (line 10) should be put before `dependency "apple"` (line 9) end RUBY @@ -122,9 +122,9 @@ RSpec.describe RuboCop::Cop::FormulaAudit::DependencyOrder do on_arm do uses_from_macos "apple" if build.with? "foo" uses_from_macos "bar" - ^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: dependency "bar" (line 6) should be put before dependency "apple" (line 5) + ^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: `dependency "bar"` (line 6) should be put before `dependency "apple"` (line 5) uses_from_macos "foo" => :optional - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: dependency "foo" (line 7) should be put before dependency "apple" (line 5) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: `dependency "foo"` (line 7) should be put before `dependency "apple"` (line 5) end end RUBY @@ -151,7 +151,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::DependencyOrder do url "https://brew.sh/foo-1.0.tgz" depends_on "apple" if build.with? "foo" depends_on "foo" => :optional - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: dependency "foo" (line 5) should be put before dependency "apple" (line 4) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: `dependency "foo"` (line 5) should be put before `dependency "apple"` (line 4) end RUBY @@ -172,7 +172,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::DependencyOrder do url "https://brew.sh/foo-1.0.tgz" depends_on "foo" depends_on "bar" - ^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: dependency "bar" (line 5) should be put before dependency "foo" (line 4) + ^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: `dependency "bar"` (line 5) should be put before `dependency "foo"` (line 4) end RUBY @@ -193,7 +193,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::DependencyOrder do url "https://brew.sh/foo-1.0.tgz" depends_on FooRequirement depends_on "bar" - ^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: dependency "bar" (line 5) should be put before dependency "FooRequirement" (line 4) + ^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: `dependency "bar"` (line 5) should be put before `dependency "FooRequirement"` (line 4) end RUBY @@ -215,13 +215,13 @@ RSpec.describe RuboCop::Cop::FormulaAudit::DependencyOrder do head do depends_on "apple" if build.with? "foo" depends_on "bar" - ^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: dependency "bar" (line 6) should be put before dependency "apple" (line 5) + ^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: `dependency "bar"` (line 6) should be put before `dependency "apple"` (line 5) depends_on "foo" => :optional - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: dependency "foo" (line 7) should be put before dependency "apple" (line 5) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: `dependency "foo"` (line 7) should be put before `dependency "apple"` (line 5) end depends_on "apple" if build.with? "foo" depends_on "foo" => :optional - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: dependency "foo" (line 10) should be put before dependency "apple" (line 9) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: `dependency "foo"` (line 10) should be put before `dependency "apple"` (line 9) end RUBY @@ -260,9 +260,9 @@ RSpec.describe RuboCop::Cop::FormulaAudit::DependencyOrder do on_linux do depends_on "apple" if build.with? "foo" depends_on "bar" - ^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: dependency "bar" (line 6) should be put before dependency "apple" (line 5) + ^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: `dependency "bar"` (line 6) should be put before `dependency "apple"` (line 5) depends_on "foo" => :optional - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: dependency "foo" (line 7) should be put before dependency "apple" (line 5) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/DependencyOrder: `dependency "foo"` (line 7) should be put before `dependency "apple"` (line 5) end end RUBY diff --git a/Library/Homebrew/test/rubocops/desc_spec.rb b/Library/Homebrew/test/rubocops/desc_spec.rb index 29ecf06de7..173e07033d 100644 --- a/Library/Homebrew/test/rubocops/desc_spec.rb +++ b/Library/Homebrew/test/rubocops/desc_spec.rb @@ -9,7 +9,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Desc do it "reports an offense when there is no `desc`" do expect_offense(<<~RUBY) class Foo < Formula - ^^^^^^^^^^^^^^^^^^^ FormulaAudit/Desc: Formula should have a desc (Description). + ^^^^^^^^^^^^^^^^^^^ FormulaAudit/Desc: Formula should have a `desc` (description). url 'https://brew.sh/foo-1.0.tgz' end RUBY @@ -20,7 +20,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Desc do class Foo < Formula url 'https://brew.sh/foo-1.0.tgz' desc '' - ^^^^^^^ FormulaAudit/Desc: The desc (description) should not be an empty string. + ^^^^^^^ FormulaAudit/Desc: The `desc` (description) should not be an empty string. end RUBY end diff --git a/Library/Homebrew/test/rubocops/homepage_spec.rb b/Library/Homebrew/test/rubocops/homepage_spec.rb index 6b845603c4..3857ee4bc8 100644 --- a/Library/Homebrew/test/rubocops/homepage_spec.rb +++ b/Library/Homebrew/test/rubocops/homepage_spec.rb @@ -19,7 +19,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Homepage do expect_offense(<<~RUBY) class Foo < Formula homepage "ftp://brew.sh/foo" - ^^^^^^^^^^^^^^^^^^^ FormulaAudit/Homepage: The homepage should start with http or https. + ^^^^^^^^^^^^^^^^^^^ FormulaAudit/Homepage: The `homepage` should start with http or https. url "https://brew.sh/foo-1.0.tgz" end RUBY @@ -29,7 +29,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Homepage do expect_offense(<<~RUBY) class Foo < Formula homepage "http://www.freedesktop.org/wiki/bar" - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Homepage: Freedesktop homepages should be styled `https://wiki.freedesktop.org/project_name` + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Homepage: Freedesktop homepages should be styled: https://wiki.freedesktop.org/project_name url "https://brew.sh/foo-1.0.tgz" end RUBY @@ -39,7 +39,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Homepage do expect_offense(<<~RUBY) class Foo < Formula homepage "http://www.freedesktop.org/wiki/Software/baz" - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Homepage: Freedesktop homepages should be styled `https://wiki.freedesktop.org/www/Software/project_name` + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Homepage: Freedesktop homepages should be styled: https://wiki.freedesktop.org/www/Software/project_name url "https://brew.sh/foo-1.0.tgz" end RUBY @@ -79,7 +79,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Homepage do RUBY end - describe "for Sourceforge" do + describe "for SourceForge" do correct_formula = <<~RUBY class Foo < Formula homepage "https://foo.sourceforge.io/" @@ -91,7 +91,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Homepage do expect_offense(<<~RUBY) class Foo < Formula homepage "http://foo.sourceforge.net/" - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Homepage: Sourceforge homepages should be `https://foo.sourceforge.io/` + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Homepage: SourceForge homepages should be: https://foo.sourceforge.io/ url "https://brew.sh/foo-1.0.tgz" end RUBY @@ -103,7 +103,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Homepage do expect_offense(<<~RUBY) class Foo < Formula homepage "http://foo.sourceforge.net" - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Homepage: Sourceforge homepages should be `https://foo.sourceforge.io/` + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Homepage: SourceForge homepages should be: https://foo.sourceforge.io/ url "https://brew.sh/foo-1.0.tgz" end RUBY @@ -115,7 +115,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Homepage do expect_offense(<<~RUBY) class Foo < Formula homepage "http://foo.sf.net/" - ^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Homepage: Sourceforge homepages should be `https://foo.sourceforge.io/` + ^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Homepage: SourceForge homepages should be: https://foo.sourceforge.io/ url "https://brew.sh/foo-1.0.tgz" end RUBY @@ -128,7 +128,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Homepage do expect_offense(<<~RUBY) class Foo < Formula homepage "https://foo.readthedocs.org" - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Homepage: Readthedocs homepages should be `https://foo.readthedocs.io` + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Homepage: Readthedocs homepages should be: https://foo.readthedocs.io url "https://brew.sh/foo-1.0.tgz" end RUBY diff --git a/Library/Homebrew/test/rubocops/lines/quictls_check_spec.rb b/Library/Homebrew/test/rubocops/lines/quictls_check_spec.rb index 3ee173448d..81150a2dee 100644 --- a/Library/Homebrew/test/rubocops/lines/quictls_check_spec.rb +++ b/Library/Homebrew/test/rubocops/lines/quictls_check_spec.rb @@ -13,7 +13,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::QuicTLSCheck do url 'https://brew.sh/foo-1.0.tgz' depends_on "quictls" - ^^^^^^^^^^^^^^^^^^^^ FormulaAudit/QuicTLSCheck: Formulae in homebrew/core should use 'depends_on "openssl@3"' instead of 'depends_on "quictls"'. + ^^^^^^^^^^^^^^^^^^^^ FormulaAudit/QuicTLSCheck: Formulae in homebrew/core should use `depends_on "openssl@3"` instead of `depends_on "quictls"`. end RUBY end diff --git a/Library/Homebrew/test/rubocops/options_spec.rb b/Library/Homebrew/test/rubocops/options_spec.rb index 5c1d2d376e..604fd98db7 100644 --- a/Library/Homebrew/test/rubocops/options_spec.rb +++ b/Library/Homebrew/test/rubocops/options_spec.rb @@ -32,7 +32,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Options do url 'https://brew.sh/foo-1.0.tgz' option :cxx11 option "examples", "with-examples" - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Options: Options should begin with with/without. Migrate '--examples' with `deprecated_option`. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Options: Options should begin with `with` or `without`. Migrate '--examples' with `deprecated_option`. end RUBY end diff --git a/Library/Homebrew/test/rubocops/patches_spec.rb b/Library/Homebrew/test/rubocops/patches_spec.rb index 9f568fd453..00c60d1c2b 100644 --- a/Library/Homebrew/test/rubocops/patches_spec.rb +++ b/Library/Homebrew/test/rubocops/patches_spec.rb @@ -24,7 +24,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Patches do homepage "ftp://brew.sh/foo" url "https://brew.sh/foo-1.0.tgz" def patches - ^^^^^^^^^^^ FormulaAudit/Patches: Use the patch DSL instead of defining a 'patches' method + ^^^^^^^^^^^ FormulaAudit/Patches: Use the `patch` DSL instead of defining a `patches` method DATA end end @@ -83,7 +83,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Patches do commit = "b354c009a60bcd6d7fc04014e200a1ee9c45c167" fixed_url = "https://api.bitbucket.org/2.0/repositories/multicoreware/x265_git/diff/#{commit}" expect_offense_hash(message: <<~EOS.chomp, severity: :convention, line: 5, column: 4, source:) - FormulaAudit/Patches: Bitbucket patches should use the api url: #{fixed_url} + FormulaAudit/Patches: Bitbucket patches should use the API URL: #{fixed_url} EOS end expected_offense.zip([inspect_source(source).last]).each do |expected, actual| @@ -112,7 +112,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Patches do expected_offenses = [ { - message: "FormulaAudit/Patches: Use the patch DSL instead of defining a 'patches' method", + message: "FormulaAudit/Patches: Use the `patch` DSL instead of defining a `patches` method", severity: :convention, line: 4, column: 2, @@ -166,7 +166,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Patches do class Foo < Formula url 'https://brew.sh/foo-1.0.tgz' patch :DATA - ^^^^^^^^^^^ FormulaAudit/Patches: patch is missing '__END__' + ^^^^^^^^^^^ FormulaAudit/Patches: Patch is missing `__END__` end RUBY end @@ -177,7 +177,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Patches do url 'https://brew.sh/foo-1.0.tgz' end __END__ - ^^^^^^^ FormulaAudit/Patches: patch is missing 'DATA' + ^^^^^^^ FormulaAudit/Patches: Patch is missing `patch :DATA` patch content here RUBY end diff --git a/Library/Homebrew/test/rubocops/provided_by_macos_spec.rb b/Library/Homebrew/test/rubocops/provided_by_macos_spec.rb index 0fa2145e8c..f43d070b46 100644 --- a/Library/Homebrew/test/rubocops/provided_by_macos_spec.rb +++ b/Library/Homebrew/test/rubocops/provided_by_macos_spec.rb @@ -12,7 +12,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::ProvidedByMacos do homepage "https://brew.sh" keg_only :provided_by_macos - ^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/ProvidedByMacos: Formulae that are `keg_only :provided_by_macos` should be added to the `PROVIDED_BY_MACOS_FORMULAE` list (in the Homebrew/brew repo) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/ProvidedByMacos: Formulae that are `keg_only :provided_by_macos` should be added to the `PROVIDED_BY_MACOS_FORMULAE` list (in the Homebrew/brew repository) end RUBY end diff --git a/Library/Homebrew/test/rubocops/shell_commands_spec.rb b/Library/Homebrew/test/rubocops/shell_commands_spec.rb index bcd8601ea9..6d0e1734ff 100644 --- a/Library/Homebrew/test/rubocops/shell_commands_spec.rb +++ b/Library/Homebrew/test/rubocops/shell_commands_spec.rb @@ -26,19 +26,19 @@ RSpec.describe RuboCop::Cop::Homebrew::ShellCommands do end it "reports and corrects an offense when `system` arguments involving interpolation should be separated" do - expect_offense(<<~RUBY) + expect_offense(<<~'RUBY') class Foo < Formula def install - system "\#{bin}/foo bar" - ^^^^^^^^^^^^^^^^ Homebrew/ShellCommands: Separate `system` commands into `"\#{bin}/foo", "bar"` + system "#{bin}/foo bar" + ^^^^^^^^^^^^^^^^ Homebrew/ShellCommands: Separate `system` commands into `"#{bin}/foo", "bar"` end end RUBY - expect_correction(<<~RUBY) + expect_correction(<<~'RUBY') class Foo < Formula def install - system "\#{bin}/foo", "bar" + system "#{bin}/foo", "bar" end end RUBY @@ -151,19 +151,19 @@ RSpec.describe RuboCop::Cop::Homebrew::ShellCommands do end it "reports and corrects an offense when `Utils.popen_read` arguments with interpolation are unseparated" do - expect_offense(<<~RUBY) + expect_offense(<<~'RUBY') class Foo < Formula def install - Utils.popen_read("\#{bin}/foo bar") - ^^^^^^^^^^^^^^^^ Homebrew/ShellCommands: Separate `Utils.popen_read` commands into `"\#{bin}/foo", "bar"` + Utils.popen_read("#{bin}/foo bar") + ^^^^^^^^^^^^^^^^ Homebrew/ShellCommands: Separate `Utils.popen_read` commands into `"#{bin}/foo", "bar"` end end RUBY - expect_correction(<<~RUBY) + expect_correction(<<~'RUBY') class Foo < Formula def install - Utils.popen_read("\#{bin}/foo", "bar") + Utils.popen_read("#{bin}/foo", "bar") end end RUBY diff --git a/Library/Homebrew/test/rubocops/text/miscellaneous_spec.rb b/Library/Homebrew/test/rubocops/text/miscellaneous_spec.rb index baa6a32e6d..f3f15fecd3 100644 --- a/Library/Homebrew/test/rubocops/text/miscellaneous_spec.rb +++ b/Library/Homebrew/test/rubocops/text/miscellaneous_spec.rb @@ -12,7 +12,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Miscellaneous do desc "foo" url 'https://brew.sh/foo-1.0.tgz' FileUtils.mv "hello" - ^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: Don't need 'FileUtils.' before mv + ^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: No need for `FileUtils.` before `mv` end RUBY end @@ -23,7 +23,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Miscellaneous do desc "foo" url 'https://brew.sh/foo-1.0.tgz' inreplace "foo" do |longvar| - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: "inreplace do |s|" is preferred over "|longvar|". + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: `inreplace do |s|` is preferred over `|longvar|`. somerandomCall(longvar) end end @@ -37,7 +37,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Miscellaneous do url 'https://brew.sh/foo-1.0.tgz' bottle do rebuild 0 - ^^^^^^^^^ FormulaAudit/Miscellaneous: 'rebuild 0' should be removed + ^^^^^^^^^ FormulaAudit/Miscellaneous: `rebuild 0` should be removed sha256 "fe0679b932dd43a87fd415b609a7fbac7a069d117642ae8ebaac46ae1fb9f0b3" => :sierra end end @@ -53,7 +53,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Miscellaneous do sha256 "fe0679b932dd43a87fd415b609a7fbac7a069d117642ae8ebaac46ae1fb9f0b3" => :sierra end fails_with :llvm do - ^^^^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: 'fails_with :llvm' is now a no-op so should be removed + ^^^^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: `fails_with :llvm` is now a no-op and should be removed build 2335 cause "foo" end @@ -68,7 +68,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Miscellaneous do url 'https://brew.sh/foo-1.0.tgz' def test - ^^^^^^^^ FormulaAudit/Miscellaneous: Use new-style test definitions (test do) + ^^^^^^^^ FormulaAudit/Miscellaneous: Use new-style test definitions (`test do`) assert_equals "1", "1" end end @@ -165,7 +165,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Miscellaneous do url 'https://brew.sh/foo-1.0.tgz' rm_rf Dir["src/{llvm,test,librustdoc,etc/snapshot.pyc}"] rm_rf Dir["src/snapshot.pyc"] - ^^^^^^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: Dir(["src/snapshot.pyc"]) is unnecessary; just use "src/snapshot.pyc" + ^^^^^^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: `Dir(["src/snapshot.pyc"])` is unnecessary; just use `src/snapshot.pyc` end RUBY end @@ -184,7 +184,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Miscellaneous do it "reports an offense when top-level functions are defined outside of a class body" do expect_offense(<<~RUBY) def test - ^^^^^^^^ FormulaAudit/Miscellaneous: Define method test in the class body, not at the top-level + ^^^^^^^^ FormulaAudit/Miscellaneous: Define method `test` in the class body, not at the top-level nil end class Foo < Formula @@ -201,7 +201,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Miscellaneous do url 'https://brew.sh/foo-1.0.tgz' def install man1.install man+"man8" => "faad.1" - ^^^^^^ FormulaAudit/Miscellaneous: "man+"man8"" should be "man8" + ^^^^^^ FormulaAudit/Miscellaneous: `man+"man8"` should be `man8` end end RUBY @@ -214,7 +214,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Miscellaneous do url 'https://brew.sh/foo-1.0.tgz' def install system "/usr/bin/gcc", "foo" - ^^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: Use "#{ENV.cc}" instead of hard-coding "gcc" + ^^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: Use `#{ENV.cc}` instead of hard-coding `gcc` end end RUBY @@ -227,7 +227,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Miscellaneous do url 'https://brew.sh/foo-1.0.tgz' def install system "/usr/bin/g++", "-o", "foo", "foo.cc" - ^^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: Use "#{ENV.cxx}" instead of hard-coding "g++" + ^^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: Use `#{ENV.cxx}` instead of hard-coding `g++` end end RUBY @@ -240,20 +240,20 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Miscellaneous do url 'https://brew.sh/foo-1.0.tgz' def install ENV["COMPILER_PATH"] = "/usr/bin/c++" - ^^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: Use "#{ENV.cxx}" instead of hard-coding "c++" + ^^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: Use `#{ENV.cxx}` instead of hard-coding `c++` end end RUBY end it "reports an offense when a hard-coded `gcc` is set as COMPILER_PATH" do - expect_offense(<<~RUBY) + expect_offense(<<~'RUBY') class Foo < Formula desc "foo" url 'https://brew.sh/foo-1.0.tgz' def install ENV["COMPILER_PATH"] = "/usr/bin/gcc" - ^^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: Use "\#{ENV.cc}" instead of hard-coding "gcc" + ^^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: Use `#{ENV.cc}` instead of hard-coding `gcc` end end RUBY @@ -266,7 +266,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Miscellaneous do url 'https://brew.sh/foo-1.0.tgz' def install mv "#{share}/man", share - ^^^^ FormulaAudit/Miscellaneous: "#{share}/man" should be "#{man}" + ^^^^ FormulaAudit/Miscellaneous: `#{share}/man` should be `#{man}` end end RUBY @@ -279,7 +279,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Miscellaneous do url 'https://brew.sh/foo-1.0.tgz' def install mv "#{prefix}/libexec", share - ^^^^^^^^ FormulaAudit/Miscellaneous: "#{prefix}/libexec" should be "#{libexec}" + ^^^^^^^^ FormulaAudit/Miscellaneous: `#{prefix}/libexec` should be `#{libexec}` end end RUBY @@ -292,7 +292,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Miscellaneous do url 'https://brew.sh/foo-1.0.tgz' def install system "./configure", "--INFODIR=#{prefix}/share/info" - ^^^^^^^^^^^ FormulaAudit/Miscellaneous: "#{prefix}/share/info" should be "#{info}" + ^^^^^^^^^^^ FormulaAudit/Miscellaneous: `#{prefix}/share/info` should be `#{info}` end end RUBY @@ -305,7 +305,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Miscellaneous do url 'https://brew.sh/foo-1.0.tgz' def install system "./configure", "--MANDIR=#{prefix}/share/man/man8" - ^^^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: "#{prefix}/share/man/man8" should be "#{man8}" + ^^^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: `#{prefix}/share/man/man8` should be `#{man8}` end end RUBY @@ -317,7 +317,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Miscellaneous do desc "foo" url 'https://brew.sh/foo-1.0.tgz' depends_on "lpeg" => :lua51 - ^^^^^^ FormulaAudit/Miscellaneous: lua modules should be vendored rather than use deprecated `depends_on "lpeg" => :lua51` + ^^^^^^ FormulaAudit/Miscellaneous: lua modules should be vendored rather than using deprecated `depends_on "lpeg" => :lua51` end RUBY end @@ -328,7 +328,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Miscellaneous do desc "foo" url 'https://brew.sh/foo-1.0.tgz' system "export", "var=value" - ^^^^^^^^ FormulaAudit/Miscellaneous: Use ENV instead of invoking 'export' to modify the environment + ^^^^^^^^ FormulaAudit/Miscellaneous: Use `ENV` instead of invoking `export` to modify the environment end RUBY end @@ -339,7 +339,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Miscellaneous do desc "foo" url 'https://brew.sh/foo-1.0.tgz' depends_on "foo" => "with-bar" - ^^^^^^^^^^ FormulaAudit/Miscellaneous: Dependency foo should not use option with-bar + ^^^^^^^^^^ FormulaAudit/Miscellaneous: Dependency 'foo' should not use option `with-bar` end RUBY end @@ -351,9 +351,9 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Miscellaneous do url 'https://brew.sh/foo-1.0.tgz' depends_on "httpd" => [:build, :test] depends_on "foo" => [:optional, "with-bar"] - ^^^^^^^^^^ FormulaAudit/Miscellaneous: Dependency foo should not use option with-bar + ^^^^^^^^^^ FormulaAudit/Miscellaneous: Dependency 'foo' should not use option `with-bar` depends_on "icu4c" => [:optional, "c++11"] - ^^^^^^^ FormulaAudit/Miscellaneous: Dependency icu4c should not use option c++11 + ^^^^^^^ FormulaAudit/Miscellaneous: Dependency 'icu4c' should not use option `c++11` end RUBY end @@ -364,7 +364,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Miscellaneous do desc "foo" url 'https://brew.sh/foo-1.0.tgz' if version == "HEAD" - ^^^^^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: Use 'build.head?' instead of inspecting 'version' + ^^^^^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: Use `build.head?` instead of inspecting `version` foo() end end @@ -378,8 +378,8 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Miscellaneous do url 'https://brew.sh/foo-1.0.tgz' test do head = ARGV.include? "--HEAD" - ^^^^ FormulaAudit/Miscellaneous: Use build instead of ARGV to check options - ^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: Use "if build.head?" instead + ^^^^ FormulaAudit/Miscellaneous: Use `build.with?` or `build.without?` instead of `ARGV` to check options + ^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: Use `if build.head?` instead end end RUBY @@ -391,7 +391,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Miscellaneous do desc "foo" url 'https://brew.sh/foo-1.0.tgz' needs :openmp - ^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: 'needs :openmp' should be replaced with 'depends_on "gcc"' + ^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: `needs :openmp` should be replaced with `depends_on "gcc"` end RUBY end @@ -403,7 +403,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Miscellaneous do url 'https://brew.sh/foo-1.0.tgz' test do version = MACOS_VERSION - ^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: Use MacOS.version instead of MACOS_VERSION + ^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: Use `MacOS.version` instead of `MACOS_VERSION` end end RUBY @@ -415,7 +415,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Miscellaneous do desc "foo" url 'https://brew.sh/foo-1.0.tgz' depends_on "foo" if build.with? "foo" - ^^^^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: Replace depends_on "foo" if build.with? "foo" with depends_on "foo" => :optional + ^^^^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: Replace `depends_on "foo" if build.with? "foo"` with `depends_on "foo" => :optional` end RUBY end @@ -426,7 +426,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Miscellaneous do desc "foo" url 'https://brew.sh/foo-1.0.tgz' depends_on :foo unless build.without? "foo" - ^^^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: Replace depends_on :foo unless build.without? "foo" with depends_on :foo => :recommended + ^^^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: Replace `depends_on :foo unless build.without? "foo"` with `depends_on :foo => :recommended` end RUBY end @@ -437,7 +437,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Miscellaneous do desc "foo" url 'https://brew.sh/foo-1.0.tgz' depends_on :foo unless build.include? "without-foo" - ^^^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: Replace depends_on :foo unless build.include? "without-foo" with depends_on :foo => :recommended + ^^^^^^^^^^^^^^^ FormulaAudit/Miscellaneous: Replace `depends_on :foo unless build.include? "without-foo"` with `depends_on :foo => :recommended` end RUBY end diff --git a/Library/Homebrew/test/rubocops/text/mpi_check_spec.rb b/Library/Homebrew/test/rubocops/text/mpi_check_spec.rb index 986f689c75..0ccedc8c52 100644 --- a/Library/Homebrew/test/rubocops/text/mpi_check_spec.rb +++ b/Library/Homebrew/test/rubocops/text/mpi_check_spec.rb @@ -12,7 +12,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::MpiCheck do desc "foo" url 'https://brew.sh/foo-1.0.tgz' depends_on "mpich" - ^^^^^^^^^^^^^^^^^^ FormulaAudit/MpiCheck: Formulae in homebrew/core should use 'depends_on "open-mpi"' instead of 'depends_on "mpich"'. + ^^^^^^^^^^^^^^^^^^ FormulaAudit/MpiCheck: Formulae in homebrew/core should use `depends_on "open-mpi"` instead of `depends_on "mpich"`. end RUBY diff --git a/Library/Homebrew/test/rubocops/text/on_system_conditionals_spec.rb b/Library/Homebrew/test/rubocops/text/on_system_conditionals_spec.rb index 9757208197..aec211e200 100644 --- a/Library/Homebrew/test/rubocops/text/on_system_conditionals_spec.rb +++ b/Library/Homebrew/test/rubocops/text/on_system_conditionals_spec.rb @@ -11,7 +11,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::OnSystemConditionals do class Foo < Formula desc "foo" if OS.linux? - ^^^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Don't use `if OS.linux?`, use `on_linux do` instead. + ^^^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Instead of `if OS.linux?`, use `on_linux do`. url 'https://brew.sh/linux-1.0.tgz' else url 'https://brew.sh/linux-1.0.tgz' @@ -37,7 +37,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::OnSystemConditionals do class Foo < Formula desc "foo" if OS.mac? - ^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Don't use `if OS.mac?`, use `on_macos do` instead. + ^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Instead of `if OS.mac?`, use `on_macos do`. url 'https://brew.sh/mac-1.0.tgz' else url 'https://brew.sh/linux-1.0.tgz' @@ -66,7 +66,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::OnSystemConditionals do def install on_macos do - ^^^^^^^^ FormulaAudit/OnSystemConditionals: Don't use `on_macos` in `def install`, use `if OS.mac?` instead. + ^^^^^^^^ FormulaAudit/OnSystemConditionals: Instead of using `on_macos` in `def install`, use `if OS.mac?`. true end end @@ -95,7 +95,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::OnSystemConditionals do def install on_linux do - ^^^^^^^^ FormulaAudit/OnSystemConditionals: Don't use `on_linux` in `def install`, use `if OS.linux?` instead. + ^^^^^^^^ FormulaAudit/OnSystemConditionals: Instead of using `on_linux` in `def install`, use `if OS.linux?`. true end end @@ -124,7 +124,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::OnSystemConditionals do test do on_macos do - ^^^^^^^^ FormulaAudit/OnSystemConditionals: Don't use `on_macos` in `test do`, use `if OS.mac?` instead. + ^^^^^^^^ FormulaAudit/OnSystemConditionals: Instead of using `on_macos` in `test do`, use `if OS.mac?`. true end end @@ -152,7 +152,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::OnSystemConditionals do class Foo < Formula desc "foo" if Hardware::CPU.arm? - ^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Don't use `if Hardware::CPU.arm?`, use `on_arm do` instead. + ^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Instead of `if Hardware::CPU.arm?`, use `on_arm do`. url 'https://brew.sh/linux-1.0.tgz' else url 'https://brew.sh/linux-1.0.tgz' @@ -178,7 +178,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::OnSystemConditionals do class Foo < Formula desc "foo" if Hardware::CPU.intel? - ^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Don't use `if Hardware::CPU.intel?`, use `on_intel do` instead. + ^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Instead of `if Hardware::CPU.intel?`, use `on_intel do`. url 'https://brew.sh/mac-1.0.tgz' else url 'https://brew.sh/linux-1.0.tgz' @@ -207,7 +207,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::OnSystemConditionals do def install on_intel do - ^^^^^^^^ FormulaAudit/OnSystemConditionals: Don't use `on_intel` in `def install`, use `if Hardware::CPU.intel?` instead. + ^^^^^^^^ FormulaAudit/OnSystemConditionals: Instead of using `on_intel` in `def install`, use `if Hardware::CPU.intel?`. true end end @@ -236,7 +236,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::OnSystemConditionals do def install on_arm do - ^^^^^^ FormulaAudit/OnSystemConditionals: Don't use `on_arm` in `def install`, use `if Hardware::CPU.arm?` instead. + ^^^^^^ FormulaAudit/OnSystemConditionals: Instead of using `on_arm` in `def install`, use `if Hardware::CPU.arm?`. true end end @@ -265,7 +265,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::OnSystemConditionals do test do on_intel do - ^^^^^^^^ FormulaAudit/OnSystemConditionals: Don't use `on_intel` in `test do`, use `if Hardware::CPU.intel?` instead. + ^^^^^^^^ FormulaAudit/OnSystemConditionals: Instead of using `on_intel` in `test do`, use `if Hardware::CPU.intel?`. true end end @@ -293,7 +293,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::OnSystemConditionals do class Foo < Formula desc "foo" if MacOS.version == :monterey - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Don't use `if MacOS.version == :monterey`, use `on_monterey do` instead. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Instead of `if MacOS.version == :monterey`, use `on_monterey do`. url 'https://brew.sh/linux-1.0.tgz' end end @@ -314,7 +314,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::OnSystemConditionals do class Foo < Formula desc "foo" if MacOS.version <= :monterey - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Don't use `if MacOS.version <= :monterey`, use `on_system :linux, macos: :monterey_or_older do` instead. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Instead of `if MacOS.version <= :monterey`, use `on_system :linux, macos: :monterey_or_older do`. url 'https://brew.sh/mac-1.0.tgz' end end @@ -335,7 +335,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::OnSystemConditionals do class Foo < Formula desc "foo" if MacOS.version < :monterey - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Don't use `if MacOS.version < :monterey`, use `on_system do` instead. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Instead of `if MacOS.version < :monterey`, use `on_system do`. url 'https://brew.sh/mac-1.0.tgz' end end @@ -347,7 +347,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::OnSystemConditionals do class Foo < Formula desc "foo" if MacOS.version >= :monterey - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Don't use `if MacOS.version >= :monterey`, use `on_monterey :or_newer do` instead. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Instead of `if MacOS.version >= :monterey`, use `on_monterey :or_newer do`. url 'https://brew.sh/mac-1.0.tgz' else url 'https://brew.sh/linux-1.0.tgz' @@ -361,7 +361,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::OnSystemConditionals do class Foo < Formula desc "foo" if MacOS.version > :monterey - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Don't use `if MacOS.version > :monterey`, use `on_monterey do` instead. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Instead of `if MacOS.version > :monterey`, use `on_monterey do`. url 'https://brew.sh/mac-1.0.tgz' end end @@ -376,7 +376,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::OnSystemConditionals do def install on_monterey do - ^^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Don't use `on_monterey` in `def install`, use `if MacOS.version == :monterey` instead. + ^^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Instead of using `on_monterey` in `def install`, use `if MacOS.version == :monterey`. true end end @@ -405,7 +405,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::OnSystemConditionals do def install on_monterey :or_older do - ^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Don't use `on_monterey :or_older` in `def install`, use `if MacOS.version <= :monterey` instead. + ^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Instead of using `on_monterey :or_older` in `def install`, use `if MacOS.version <= :monterey`. true end end @@ -434,7 +434,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::OnSystemConditionals do def install on_monterey :or_newer do - ^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Don't use `on_monterey :or_newer` in `def install`, use `if MacOS.version >= :monterey` instead. + ^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Instead of using `on_monterey :or_newer` in `def install`, use `if MacOS.version >= :monterey`. true end end @@ -463,7 +463,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::OnSystemConditionals do def install on_system :linux, macos: :monterey_or_newer do - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Don't use `on_system :linux, macos: :monterey_or_newer` in `def install`, use `if OS.linux? || MacOS.version >= :monterey` instead. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Instead of using `on_system :linux, macos: :monterey_or_newer` in `def install`, use `if OS.linux? || MacOS.version >= :monterey`. true end end @@ -492,7 +492,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::OnSystemConditionals do test do on_monterey do - ^^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Don't use `on_monterey` in `test do`, use `if MacOS.version == :monterey` instead. + ^^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Instead of using `on_monterey` in `test do`, use `if MacOS.version == :monterey`. true end end @@ -521,7 +521,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::OnSystemConditionals do test do on_system :linux, macos: :monterey do - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Don't use `on_system :linux, macos: :monterey` in `test do`, use `if OS.linux? || MacOS.version == :monterey` instead. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/OnSystemConditionals: Instead of using `on_system :linux, macos: :monterey` in `test do`, use `if OS.linux? || MacOS.version == :monterey`. true end end diff --git a/Library/Homebrew/test/rubocops/text/option_declarations_spec.rb b/Library/Homebrew/test/rubocops/text/option_declarations_spec.rb index b14e6daafd..34f4b668a7 100644 --- a/Library/Homebrew/test/rubocops/text/option_declarations_spec.rb +++ b/Library/Homebrew/test/rubocops/text/option_declarations_spec.rb @@ -57,7 +57,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::OptionDeclarations do url 'https://brew.sh/foo-1.0.tgz' def post_install return unless build.without? "bar" - ^^^^^^^^^^^^^^^^^^^^ FormulaAudit/OptionDeclarations: Use if build.with? "bar" instead of unless build.without? "bar" + ^^^^^^^^^^^^^^^^^^^^ FormulaAudit/OptionDeclarations: Use `if build.with? "bar"` instead of `unless build.without? "bar"` end end RUBY @@ -70,7 +70,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::OptionDeclarations do url 'https://brew.sh/foo-1.0.tgz' def post_install return unless build.with? "bar" - ^^^^^^^^^^^^^^^^^ FormulaAudit/OptionDeclarations: Use if build.without? "bar" instead of unless build.with? "bar" + ^^^^^^^^^^^^^^^^^ FormulaAudit/OptionDeclarations: Use `if build.without? "bar"` instead of `unless build.with? "bar"` end end RUBY @@ -83,7 +83,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::OptionDeclarations do url 'https://brew.sh/foo-1.0.tgz' def post_install return if !build.with? "bar" - ^^^^^^^^^^^^^^^^^^ FormulaAudit/OptionDeclarations: Don't negate 'build.with?': use 'build.without?' + ^^^^^^^^^^^^^^^^^^ FormulaAudit/OptionDeclarations: Instead of negating `build.with?`, use `build.without?` end end RUBY @@ -96,7 +96,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::OptionDeclarations do url 'https://brew.sh/foo-1.0.tgz' def post_install return if !build.without? "bar" - ^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/OptionDeclarations: Don't negate 'build.without?': use 'build.with?' + ^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/OptionDeclarations: Instead of negating `build.without?`, use `build.with?` end end RUBY @@ -109,7 +109,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::OptionDeclarations do url 'https://brew.sh/foo-1.0.tgz' def post_install return if build.without? "--without-bar" - ^^^^^^^^^^^^^^^ FormulaAudit/OptionDeclarations: Don't duplicate 'without': Use `build.without? "bar"` to check for "--without-bar" + ^^^^^^^^^^^^^^^ FormulaAudit/OptionDeclarations: Instead of duplicating `without`, use `build.without? "bar"` to check for "--without-bar" end end RUBY @@ -122,7 +122,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::OptionDeclarations do url 'https://brew.sh/foo-1.0.tgz' def post_install return if build.with? "--with-bar" - ^^^^^^^^^^^^ FormulaAudit/OptionDeclarations: Don't duplicate 'with': Use `build.with? "bar"` to check for "--with-bar" + ^^^^^^^^^^^^ FormulaAudit/OptionDeclarations: Instead of duplicating `with`, use `build.with? "bar"` to check for '--with-bar' end end RUBY diff --git a/Library/Homebrew/test/rubocops/text/shell_variables_spec.rb b/Library/Homebrew/test/rubocops/text/shell_variables_spec.rb index ddf39dc3cc..aa7c7b9100 100644 --- a/Library/Homebrew/test/rubocops/text/shell_variables_spec.rb +++ b/Library/Homebrew/test/rubocops/text/shell_variables_spec.rb @@ -64,19 +64,19 @@ RSpec.describe RuboCop::Cop::FormulaAudit::ShellVariables do end it "reports and corrects unexpanded shell variables while preserving string interpolation" do - expect_offense(<<~RUBY) + expect_offense(<<~'RUBY') class Foo < Formula def install - Utils.popen "SHELL=bash \#{bin}/foo" - ^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/ShellVariables: Use `Utils.popen({ "SHELL" => "bash" }, "\#{bin}/foo")` instead of `Utils.popen "SHELL=bash \#{bin}/foo"` + Utils.popen "SHELL=bash #{bin}/foo" + ^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/ShellVariables: Use `Utils.popen({ "SHELL" => "bash" }, "#{bin}/foo")` instead of `Utils.popen "SHELL=bash #{bin}/foo"` end end RUBY - expect_correction(<<~RUBY) + expect_correction(<<~'RUBY') class Foo < Formula def install - Utils.popen({ "SHELL" => "bash" }, "\#{bin}/foo") + Utils.popen({ "SHELL" => "bash" }, "#{bin}/foo") end end RUBY diff --git a/Library/Homebrew/test/rubocops/text/std_npm_args_spec.rb b/Library/Homebrew/test/rubocops/text/std_npm_args_spec.rb index c0bb9e97ed..2c5ea62337 100644 --- a/Library/Homebrew/test/rubocops/text/std_npm_args_spec.rb +++ b/Library/Homebrew/test/rubocops/text/std_npm_args_spec.rb @@ -22,7 +22,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::StdNpmArgs do class Foo < Formula def install system "npm", "install", *Language::Node.local_npm_install_args, "--production" - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/StdNpmArgs: Use 'std_npm_args' instead of 'local_npm_install_args'. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/StdNpmArgs: Use `std_npm_args` instead of `local_npm_install_args`. end end RUBY @@ -41,7 +41,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::StdNpmArgs do class Foo < Formula def install system "npm", "install", *Language::Node.std_npm_install_args(libexec), "--production" - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/StdNpmArgs: Use 'std_npm_args' instead of 'std_npm_install_args'. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/StdNpmArgs: Use `std_npm_args` instead of `std_npm_install_args`. end end RUBY @@ -60,7 +60,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::StdNpmArgs do class Foo < Formula def install system "npm", "install", *Language::Node.std_npm_install_args(buildpath), "--production" - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/StdNpmArgs: Use 'std_npm_args' instead of 'std_npm_install_args'. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/StdNpmArgs: Use `std_npm_args` instead of `std_npm_install_args`. end end RUBY diff --git a/Library/Homebrew/test/rubocops/text/strict_spec.rb b/Library/Homebrew/test/rubocops/text/strict_spec.rb index dde8271967..b57143c46b 100644 --- a/Library/Homebrew/test/rubocops/text/strict_spec.rb +++ b/Library/Homebrew/test/rubocops/text/strict_spec.rb @@ -29,29 +29,29 @@ RSpec.describe RuboCop::Cop::FormulaAuditStrict::Text do end it %Q(reports an offense if "\#{share}/" is present) do - expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb") + expect_offense(<<~'RUBY', "/homebrew-core/Formula/foo.rb") class Foo < Formula def install - ohai "\#{share}/foo" - ^^^^^^^^^^^^^^ FormulaAuditStrict/Text: Use `\#{pkgshare}` instead of `\#{share}/foo` + ohai "#{share}/foo" + ^^^^^^^^^^^^^^ FormulaAuditStrict/Text: Use `#{pkgshare}` instead of `#{share}/foo` end end RUBY - expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb") + expect_offense(<<~'RUBY', "/homebrew-core/Formula/foo.rb") class Foo < Formula def install - ohai "\#{share}/foo/bar" - ^^^^^^^^^^^^^^^^^^ FormulaAuditStrict/Text: Use `\#{pkgshare}` instead of `\#{share}/foo` + ohai "#{share}/foo/bar" + ^^^^^^^^^^^^^^^^^^ FormulaAuditStrict/Text: Use `#{pkgshare}` instead of `#{share}/foo` end end RUBY - expect_offense(<<~RUBY, "/homebrew-core/Formula/foolibc++.rb") + expect_offense(<<~'RUBY', "/homebrew-core/Formula/foolibc++.rb") class Foolibcxx < Formula def install - ohai "\#{share}/foolibc++" - ^^^^^^^^^^^^^^^^^^^^ FormulaAuditStrict/Text: Use `\#{pkgshare}` instead of `\#{share}/foolibc++` + ohai "#{share}/foolibc++" + ^^^^^^^^^^^^^^^^^^^^ FormulaAuditStrict/Text: Use `#{pkgshare}` instead of `#{share}/foolibc++` end end RUBY @@ -87,10 +87,10 @@ RSpec.describe RuboCop::Cop::FormulaAuditStrict::Text do end it %Q(reports no offenses if "\#{share}/" doesn't match formula name) do - expect_no_offenses(<<~RUBY, "/homebrew-core/Formula/foo.rb") + expect_no_offenses(<<~'RUBY', "/homebrew-core/Formula/foo.rb") class Foo < Formula def install - ohai "\#{share}/foo-bar" + ohai "#{share}/foo-bar" end end RUBY @@ -123,10 +123,10 @@ RSpec.describe RuboCop::Cop::FormulaAuditStrict::Text do end it %Q(reports no offenses if formula name appears after "\#{share}/") do - expect_no_offenses(<<~RUBY, "/homebrew-core/Formula/foo.rb") + expect_no_offenses(<<~'RUBY', "/homebrew-core/Formula/foo.rb") class Foo < Formula def install - ohai "\#{share}/bar/foo" + ohai "#{share}/bar/foo" end end RUBY @@ -134,13 +134,13 @@ RSpec.describe RuboCop::Cop::FormulaAuditStrict::Text do context "for interpolated bin paths" do it 'reports an offense & autocorrects if "\#{bin}/" or other dashed binaries too are present' do - expect_offense(<<~RUBY, "/homebrew-core/Formula/foo.rb") + expect_offense(<<~'RUBY', "/homebrew-core/Formula/foo.rb") class Foo < Formula test do - system "\#{bin}/foo", "-v" - ^^^^^^^^^^^^ FormulaAuditStrict/Text: Use `bin/"foo"` instead of `"\#{bin}/foo"` - system "\#{bin}/foo-bar", "-v" - ^^^^^^^^^^^^^^^^ FormulaAuditStrict/Text: Use `bin/"foo-bar"` instead of `"\#{bin}/foo-bar"` + system "#{bin}/foo", "-v" + ^^^^^^^^^^^^ FormulaAuditStrict/Text: Use `bin/"foo"` instead of `"#{bin}/foo"` + system "#{bin}/foo-bar", "-v" + ^^^^^^^^^^^^^^^^ FormulaAuditStrict/Text: Use `bin/"foo-bar"` instead of `"#{bin}/foo-bar"` end end RUBY @@ -156,12 +156,12 @@ RSpec.describe RuboCop::Cop::FormulaAuditStrict::Text do end it 'does not report an offense if \#{bin}/foo and then a space and more text' do - expect_no_offenses(<<~RUBY, "/homebrew-core/Formula/foo.rb") + expect_no_offenses(<<~'RUBY', "/homebrew-core/Formula/foo.rb") class Foo < Formula test do - shell_output("\#{bin}/foo --version") - assert_match "help", shell_output("\#{bin}/foo-something --help 2>&1") - assert_match "OK", shell_output("\#{bin}/foo-something_else --check 2>&1") + shell_output("#{bin}/foo --version") + assert_match "help", shell_output("#{bin}/foo-something --help 2>&1") + assert_match "OK", shell_output("#{bin}/foo-something_else --check 2>&1") end end RUBY @@ -169,11 +169,11 @@ RSpec.describe RuboCop::Cop::FormulaAuditStrict::Text do end it 'does not report an offense if "\#{bin}/foo" is in a word array' do - expect_no_offenses(<<~RUBY, "/homebrew-core/Formula/foo.rb") + expect_no_offenses(<<~'RUBY', "/homebrew-core/Formula/foo.rb") class Foo < Formula test do cmd = %W[ - \#{bin}/foo + #{bin}/foo version ] assert_match version.to_s, shell_output(cmd) diff --git a/Library/Homebrew/test/rubocops/text_spec.rb b/Library/Homebrew/test/rubocops/text_spec.rb index df7dc19b4b..f45b917da5 100644 --- a/Library/Homebrew/test/rubocops/text_spec.rb +++ b/Library/Homebrew/test/rubocops/text_spec.rb @@ -30,7 +30,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Text do url "https://brew.sh/foo-1.0.tgz" homepage "https://brew.sh" revision 0 - ^^^^^^^^^^ FormulaAudit/Text: "revision 0" is unnecessary + ^^^^^^^^^^ FormulaAudit/Text: `revision 0` is unnecessary end RUBY end @@ -103,7 +103,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Text do def install system "xcodebuild", "foo", "bar" - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Text: use "xcodebuild *args" instead of "system 'xcodebuild', *args" + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Text: Use `xcodebuild *args` instead of `system 'xcodebuild', *args` end end RUBY @@ -117,7 +117,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Text do def install system "xcodebuild", "foo", "bar" - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Text: use "xcodebuild *args" instead of "system 'xcodebuild', *args" + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Text: Use `xcodebuild *args` instead of `system 'xcodebuild', *args` end def plist @@ -140,7 +140,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Text do it 'reports an offense if `require "language/go"` is present' do expect_offense(<<~RUBY) require "language/go" - ^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Text: require "language/go" is no longer necessary or correct + ^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Text: `require "language/go"` is no longer necessary or correct class Foo < Formula url "https://brew.sh/foo-1.0.tgz" @@ -162,7 +162,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Text do def install Formula.factory(name) - ^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Text: "Formula.factory(name)" is deprecated in favor of "Formula[name]" + ^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Text: `Formula.factory(name)` is deprecated in favour of `Formula[name]` end end RUBY @@ -176,7 +176,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Text do def install system "dep", "ensure" - ^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Text: use "dep", "ensure", "-vendor-only" + ^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Text: Use `"dep", "ensure", "-vendor-only"` end end RUBY @@ -190,7 +190,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Text do def install system "cargo", "build" - ^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Text: use "cargo", "install", *std_cargo_args + ^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/Text: Use `"cargo", "install", *std_cargo_args` end end RUBY @@ -221,10 +221,10 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Text do end it "reports an offense if paths are concatenated in string interpolation" do - expect_offense(<<~RUBY) + expect_offense(<<~'RUBY') class Foo < Formula def install - ohai "foo \#{bar + "baz"}" + ohai "foo #{bar + "baz"}" ^^^^^^^^^^^^^^ FormulaAudit/Text: Do not concatenate paths in string interpolation end end diff --git a/Library/Homebrew/test/rubocops/urls/git_spec.rb b/Library/Homebrew/test/rubocops/urls/git_spec.rb index c95deae3e2..329b3b8d86 100644 --- a/Library/Homebrew/test/rubocops/urls/git_spec.rb +++ b/Library/Homebrew/test/rubocops/urls/git_spec.rb @@ -55,7 +55,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::GitUrls do class Foo < Formula desc "foo" url "https://github.com/foo/bar.git", - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/GitUrls: Formulae in homebrew/core should specify a revision for git URLs + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/GitUrls: Formulae in homebrew/core should specify a revision for Git URLs tag: "v1.0.0" end RUBY @@ -66,7 +66,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::GitUrls do class Foo < Formula desc "foo" url "https://github.com/foo/bar.git", - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/GitUrls: Formulae in homebrew/core should specify a revision for git URLs + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/GitUrls: Formulae in homebrew/core should specify a revision for Git URLs shallow: false, tag: "v1.0.0" end diff --git a/Library/Homebrew/test/rubocops/urls/git_strict_spec.rb b/Library/Homebrew/test/rubocops/urls/git_strict_spec.rb index 1e511173d1..5015133cda 100644 --- a/Library/Homebrew/test/rubocops/urls/git_strict_spec.rb +++ b/Library/Homebrew/test/rubocops/urls/git_strict_spec.rb @@ -46,7 +46,7 @@ RSpec.describe RuboCop::Cop::FormulaAuditStrict::GitUrls do class Foo < Formula desc "foo" url "https://github.com/foo/bar.git", - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAuditStrict/GitUrls: Formulae in homebrew/core should specify a tag for git URLs + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAuditStrict/GitUrls: Formulae in homebrew/core should specify a tag for Git URLs revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" end RUBY @@ -57,7 +57,7 @@ RSpec.describe RuboCop::Cop::FormulaAuditStrict::GitUrls do class Foo < Formula desc "foo" url "https://github.com/foo/bar.git", - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAuditStrict/GitUrls: Formulae in homebrew/core should specify a tag for git URLs + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAuditStrict/GitUrls: Formulae in homebrew/core should specify a tag for Git URLs revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", shallow: false end diff --git a/Library/Homebrew/test/rubocops/urls/pypi_spec.rb b/Library/Homebrew/test/rubocops/urls/pypi_spec.rb index f4d1186ead..a7f35253f9 100644 --- a/Library/Homebrew/test/rubocops/urls/pypi_spec.rb +++ b/Library/Homebrew/test/rubocops/urls/pypi_spec.rb @@ -11,7 +11,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::PyPiUrls do class Foo < Formula desc "foo" url "https://pypi.python.org/packages/source/foo/foo-0.1.tar.gz" - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/PyPiUrls: use the `Source` url found on PyPI downloads page (`https://pypi.org/project/foo/#files`) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/PyPiUrls: Use the "Source" URL found on the PyPI downloads page (https://pypi.org/project/foo/#files) end RUBY end @@ -21,7 +21,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::PyPiUrls do class Foo < Formula desc "foo" url "https://files.pythonhosted.org/packages/source/f/foo/foo-0.1.tar.gz" - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/PyPiUrls: use the `Source` url found on PyPI downloads page (`https://pypi.org/project/foo/#files`) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/PyPiUrls: Use the "Source" URL found on the PyPI downloads page (https://pypi.org/project/foo/#files) end RUBY end diff --git a/Library/Homebrew/test/rubocops/urls_spec.rb b/Library/Homebrew/test/rubocops/urls_spec.rb index fab6d84ada..393d52a6b4 100644 --- a/Library/Homebrew/test/rubocops/urls_spec.rb +++ b/Library/Homebrew/test/rubocops/urls_spec.rb @@ -8,11 +8,12 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Urls do let(:offense_list) do [{ "url" => "https://ftpmirror.gnu.org/lightning/lightning-2.1.0.tar.gz", - "msg" => 'Please use "https://ftp.gnu.org/gnu/lightning/lightning-2.1.0.tar.gz" instead of https://ftpmirror.gnu.org/lightning/lightning-2.1.0.tar.gz.', + "msg" => "https://ftpmirror.gnu.org/lightning/lightning-2.1.0.tar.gz should be: " \ + "https://ftp.gnu.org/gnu/lightning/lightning-2.1.0.tar.gz", "col" => 2, }, { "url" => "https://fossies.org/linux/privat/monit-5.23.0.tar.gz", - "msg" => "Please don't use fossies.org in the url (using as a mirror is fine)", + "msg" => "Please don't use \"fossies.org\" in the `url` (using as a mirror is fine)", "col" => 2, }, { "url" => "http://tools.ietf.org/tools/rfcmarkup/rfcmarkup-1.119.tgz", @@ -20,23 +21,23 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Urls do "col" => 2, }, { "url" => "https://apache.org/dyn/closer.cgi?path=/apr/apr-1.7.0.tar.bz2", - "msg" => "https://apache.org/dyn/closer.cgi?path=/apr/apr-1.7.0.tar.bz2 should be " \ - "`https://www.apache.org/dyn/closer.lua?path=apr/apr-1.7.0.tar.bz2`", + "msg" => "https://apache.org/dyn/closer.cgi?path=/apr/apr-1.7.0.tar.bz2 should be: " \ + "https://www.apache.org/dyn/closer.lua?path=apr/apr-1.7.0.tar.bz2", "col" => 2, }, { "url" => "http://search.mcpan.org/CPAN/authors/id/Z/ZE/ZEFRAM/Perl4-CoreLibs-0.003.tar.gz", - "msg" => "http://search.mcpan.org/CPAN/authors/id/Z/ZE/ZEFRAM/Perl4-CoreLibs-0.003.tar.gz should be " \ - "`https://cpan.metacpan.org/authors/id/Z/ZE/ZEFRAM/Perl4-CoreLibs-0.003.tar.gz`", + "msg" => "http://search.mcpan.org/CPAN/authors/id/Z/ZE/ZEFRAM/Perl4-CoreLibs-0.003.tar.gz should be: " \ + "https://cpan.metacpan.org/authors/id/Z/ZE/ZEFRAM/Perl4-CoreLibs-0.003.tar.gz", "col" => 2, }, { "url" => "http://ftp.gnome.org/pub/GNOME/binaries/mac/banshee/banshee-2.macosx.intel.dmg", - "msg" => "http://ftp.gnome.org/pub/GNOME/binaries/mac/banshee/banshee-2.macosx.intel.dmg should be " \ - "`https://download.gnome.org/binaries/mac/banshee/banshee-2.macosx.intel.dmg`", + "msg" => "http://ftp.gnome.org/pub/GNOME/binaries/mac/banshee/banshee-2.macosx.intel.dmg should be: " \ + "https://download.gnome.org/binaries/mac/banshee/banshee-2.macosx.intel.dmg", "col" => 2, }, { "url" => "git://anonscm.debian.org/users/foo/foostrap.git", - "msg" => "git://anonscm.debian.org/users/foo/foostrap.git should be " \ - "`https://anonscm.debian.org/git/users/foo/foostrap.git`", + "msg" => "git://anonscm.debian.org/users/foo/foostrap.git should be: " \ + "https://anonscm.debian.org/git/users/foo/foostrap.git", "col" => 2, }, { "url" => "ftp://ftp.mirrorservice.org/foo-1.tar.gz", @@ -44,31 +45,31 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Urls do "col" => 2, }, { "url" => "ftp://ftp.cpan.org/pub/CPAN/foo-1.tar.gz", - "msg" => "ftp://ftp.cpan.org/pub/CPAN/foo-1.tar.gz should be `http://search.cpan.org/CPAN/foo-1.tar.gz`", + "msg" => "ftp://ftp.cpan.org/pub/CPAN/foo-1.tar.gz should be: http://search.cpan.org/CPAN/foo-1.tar.gz", "col" => 2, }, { "url" => "http://sourceforge.net/projects/something/files/Something-1.2.3.dmg", - "msg" => "Use https://downloads.sourceforge.net to get geolocation (url is " \ + "msg" => "Use \"https://downloads.sourceforge.net\" to get geolocation (`url` is " \ "http://sourceforge.net/projects/something/files/Something-1.2.3.dmg).", "col" => 2, }, { "url" => "https://downloads.sourceforge.net/project/foo/download", - "msg" => "Don't use /download in SourceForge urls (url is " \ + "msg" => "Don't use \"/download\" in SourceForge URLs (`url` is " \ "https://downloads.sourceforge.net/project/foo/download).", "col" => 2, }, { "url" => "https://sourceforge.net/project/foo", - "msg" => "Use https://downloads.sourceforge.net to get geolocation " \ - "(url is https://sourceforge.net/project/foo).", + "msg" => "Use \"https://downloads.sourceforge.net\" to get geolocation (`url` is " \ + "https://sourceforge.net/project/foo).", "col" => 2, }, { "url" => "http://prdownloads.sourceforge.net/foo/foo-1.tar.gz", - "msg" => "Don't use prdownloads in SourceForge urls " \ - "(url is http://prdownloads.sourceforge.net/foo/foo-1.tar.gz).", + "msg" => "Don't use \"prdownloads\" in SourceForge URLs (`url` is " \ + "http://prdownloads.sourceforge.net/foo/foo-1.tar.gz).", "col" => 2, }, { "url" => "http://foo.dl.sourceforge.net/sourceforge/foozip/foozip_1.0.tar.bz2", - "msg" => "Don't use specific dl mirrors in SourceForge urls (url is " \ + "msg" => "Don't use specific \"dl\" mirrors in SourceForge URLs (`url` is " \ "http://foo.dl.sourceforge.net/sourceforge/foozip/foozip_1.0.tar.bz2).", "col" => 2, }, { @@ -129,7 +130,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Urls do "col" => 2, }, { "url" => "https://github.com/foo/bar/tarball/v1.2.3", - "msg" => "Use /archive/ URLs for GitHub tarballs (url is https://github.com/foo/bar/tarball/v1.2.3).", + "msg" => "Use /archive/ URLs for GitHub tarballs (`url` is https://github.com/foo/bar/tarball/v1.2.3).", "col" => 2, }, { "url" => "https://codeload.github.com/foo/bar/tar.gz/v0.1.1", @@ -142,8 +143,8 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Urls do "col" => 2, }, { "url" => "https://central.maven.org/maven2/com/bar/foo/1.1/foo-1.1.jar", - "msg" => "https://central.maven.org/maven2/com/bar/foo/1.1/foo-1.1.jar should be " \ - "`https://search.maven.org/remotecontent?filepath=com/bar/foo/1.1/foo-1.1.jar`", + "msg" => "https://central.maven.org/maven2/com/bar/foo/1.1/foo-1.1.jar should be: " \ + "https://search.maven.org/remotecontent?filepath=com/bar/foo/1.1/foo-1.1.jar", "col" => 2, }, { "url" => "https://brew.sh/example-darwin.x86_64.tar.gz", @@ -159,31 +160,31 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Urls do "formula_tap" => "homebrew-core", }, { "url" => "cvs://brew.sh/foo/bar", - "msg" => "Use of the cvs:// scheme is deprecated, pass `:using => :cvs` instead", + "msg" => "Use of the \"cvs://\" scheme is deprecated, pass `using: :cvs` instead", "col" => 2, }, { "url" => "bzr://brew.sh/foo/bar", - "msg" => "Use of the bzr:// scheme is deprecated, pass `:using => :bzr` instead", + "msg" => "Use of the \"bzr://\" scheme is deprecated, pass `using: :bzr` instead", "col" => 2, }, { "url" => "hg://brew.sh/foo/bar", - "msg" => "Use of the hg:// scheme is deprecated, pass `:using => :hg` instead", + "msg" => "Use of the \"hg://\" scheme is deprecated, pass `using: :hg` instead", "col" => 2, }, { "url" => "fossil://brew.sh/foo/bar", - "msg" => "Use of the fossil:// scheme is deprecated, pass `:using => :fossil` instead", + "msg" => "Use of the \"fossil://\" scheme is deprecated, pass `using: :fossil` instead", "col" => 2, }, { "url" => "svn+http://brew.sh/foo/bar", - "msg" => "Use of the svn+http:// scheme is deprecated, pass `:using => :svn` instead", + "msg" => "Use of the \"svn+http://\" scheme is deprecated, pass `using: :svn` instead", "col" => 2, }, { "url" => "https://🫠.sh/foo/bar", - "msg" => "Please use the ASCII (Punycode encoded host, URL-encoded path and query) version of https://🫠.sh/foo/bar.", + "msg" => "Please use the ASCII (Punycode-encoded host, URL-encoded path and query) version of https://🫠.sh/foo/bar.", "col" => 2, }, { "url" => "https://ßrew.sh/foo/bar", - "msg" => "Please use the ASCII (Punycode encoded host, URL-encoded path and query) version of https://ßrew.sh/foo/bar.", + "msg" => "Please use the ASCII (Punycode-encoded host, URL-encoded path and query) version of https://ßrew.sh/foo/bar.", "col" => 2, }] end diff --git a/Library/Homebrew/test/rubocops/uses_from_macos_spec.rb b/Library/Homebrew/test/rubocops/uses_from_macos_spec.rb index 5d00eb4f7c..7bd5e15349 100644 --- a/Library/Homebrew/test/rubocops/uses_from_macos_spec.rb +++ b/Library/Homebrew/test/rubocops/uses_from_macos_spec.rb @@ -13,7 +13,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::UsesFromMacos do homepage "https://brew.sh" uses_from_macos "postgresql" - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/UsesFromMacos: `uses_from_macos` should only be used for macOS dependencies, not postgresql. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/UsesFromMacos: `uses_from_macos` should only be used for macOS dependencies, not 'postgresql'. end RUBY end @@ -25,10 +25,10 @@ RSpec.describe RuboCop::Cop::FormulaAudit::UsesFromMacos do homepage "https://brew.sh" uses_from_macos "boost" - ^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/UsesFromMacos: `uses_from_macos` should only be used for macOS dependencies, not boost. + ^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/UsesFromMacos: `uses_from_macos` should only be used for macOS dependencies, not 'boost'. uses_from_macos "bzip2" uses_from_macos "postgresql" - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/UsesFromMacos: `uses_from_macos` should only be used for macOS dependencies, not postgresql. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FormulaAudit/UsesFromMacos: `uses_from_macos` should only be used for macOS dependencies, not 'postgresql'. uses_from_macos "zlib" end RUBY diff --git a/Library/Homebrew/test/rubocops/version_spec.rb b/Library/Homebrew/test/rubocops/version_spec.rb index c4c9dfef1e..1f8329db49 100644 --- a/Library/Homebrew/test/rubocops/version_spec.rb +++ b/Library/Homebrew/test/rubocops/version_spec.rb @@ -11,7 +11,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Version do class Foo < Formula url 'https://brew.sh/foo-1.0.tgz' version "" - ^^^^^^^^^^ FormulaAudit/Version: version is set to an empty string + ^^^^^^^^^^ FormulaAudit/Version: Version is set to an empty string end RUBY end @@ -21,7 +21,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Version do class Foo < Formula url 'https://brew.sh/foo-1.0.tgz' version "v1.0" - ^^^^^^^^^^^^^^ FormulaAudit/Version: version v1.0 should not have a leading 'v' + ^^^^^^^^^^^^^^ FormulaAudit/Version: Version v1.0 should not have a leading 'v' end RUBY end @@ -31,7 +31,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::Version do class Foo < Formula url 'https://brew.sh/foo-1.0.tgz' version "1_0" - ^^^^^^^^^^^^^ FormulaAudit/Version: version 1_0 should not end with an underline and a number + ^^^^^^^^^^^^^ FormulaAudit/Version: Version 1_0 should not end with an underline and a number end RUBY end diff --git a/Library/Homebrew/test/spec_helper.rb b/Library/Homebrew/test/spec_helper.rb index a40023c2c6..cc62d453c7 100644 --- a/Library/Homebrew/test/spec_helper.rb +++ b/Library/Homebrew/test/spec_helper.rb @@ -59,6 +59,7 @@ TEST_DIRECTORIES = [ CoreTap.instance.path/"Formula", HOMEBREW_CACHE, HOMEBREW_CACHE_FORMULA, + HOMEBREW_CACHE/"api", HOMEBREW_CELLAR, HOMEBREW_LOCKS, HOMEBREW_LOGS, @@ -249,6 +250,11 @@ RSpec.configure do |config| @__stderr = $stderr.clone @__stdin = $stdin.clone + # Link original API cache files to test cache directory. + Pathname("#{ENV.fetch("HOMEBREW_CACHE")}/api").glob("*.json").each do |path| + FileUtils.ln path, HOMEBREW_CACHE/"api/#{path.basename}" + end + begin if example.metadata.keys.exclude?(:focus) && !ENV.key?("HOMEBREW_VERBOSE_TESTS") $stdout.reopen(File::NULL) diff --git a/Library/Homebrew/test/support/fixtures/bottles/testball_bottle-0.1.arm64_tahoe.bottle.tar.gz b/Library/Homebrew/test/support/fixtures/bottles/testball_bottle-0.1.arm64_tahoe.bottle.tar.gz new file mode 120000 index 0000000000..3e989830ba --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/bottles/testball_bottle-0.1.arm64_tahoe.bottle.tar.gz @@ -0,0 +1 @@ +testball_bottle-0.1.yosemite.bottle.tar.gz \ No newline at end of file diff --git a/Library/Homebrew/test/support/fixtures/bottles/testball_bottle-0.1.tahoe.bottle.tar.gz b/Library/Homebrew/test/support/fixtures/bottles/testball_bottle-0.1.tahoe.bottle.tar.gz new file mode 120000 index 0000000000..3e989830ba --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/bottles/testball_bottle-0.1.tahoe.bottle.tar.gz @@ -0,0 +1 @@ +testball_bottle-0.1.yosemite.bottle.tar.gz \ No newline at end of file diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-macos-failure.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-macos-failure.rb index bbde7db9c3..a65cde70d0 100644 --- a/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-macos-failure.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-macos-failure.rb @@ -1,20 +1,18 @@ cask "with-depends-on-macos-failure" do - version "1.2.3" - sha256 "67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94" - # guarantee a mismatched release - on_mojave :or_older do - depends_on macos: :catalina + on_big_sur :or_older do + version "1.2.3" + sha256 "67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94" end - on_catalina do - depends_on macos: :mojave - end - on_big_sur :or_newer do - depends_on macos: :catalina + on_ventura :or_newer do + version "1.2.3" + sha256 "67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94" end url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip" homepage "https://brew.sh/with-depends-on-macos-failure" + depends_on macos: :monterey + app "Caffeine.app" end diff --git a/Library/Homebrew/test/support/helper/spec/shared_context/integration_test.rb b/Library/Homebrew/test/support/helper/spec/shared_context/integration_test.rb index 40d193effb..f97343cfbc 100644 --- a/Library/Homebrew/test/support/helper/spec/shared_context/integration_test.rb +++ b/Library/Homebrew/test/support/helper/spec/shared_context/integration_test.rb @@ -75,14 +75,15 @@ RSpec.shared_context "integration test" do # rubocop:disable RSpec/ContextWordin ].compact.join(File::PATH_SEPARATOR) env.merge!( - "PATH" => path, - "HOMEBREW_PATH" => path, - "HOMEBREW_BREW_FILE" => HOMEBREW_PREFIX/"bin/brew", - "HOMEBREW_INTEGRATION_TEST" => command_id, - "HOMEBREW_TEST_TMPDIR" => TEST_TMPDIR, - "HOMEBREW_DEV_CMD_RUN" => "true", - "HOMEBREW_USE_RUBY_FROM_PATH" => ENV.fetch("HOMEBREW_USE_RUBY_FROM_PATH", nil), - "GEM_HOME" => nil, + "PATH" => path, + "HOMEBREW_PATH" => path, + "HOMEBREW_BREW_FILE" => HOMEBREW_PREFIX/"bin/brew", + "HOMEBREW_INTEGRATION_TEST" => command_id, + "HOMEBREW_TEST_TMPDIR" => TEST_TMPDIR, + "HOMEBREW_DEV_CMD_RUN" => "true", + "HOMEBREW_USE_RUBY_FROM_PATH" => ENV.fetch("HOMEBREW_USE_RUBY_FROM_PATH", nil), + "HOMEBREW_NO_INSTALL_FROM_API" => ENV.fetch("HOMEBREW_NO_INSTALL_FROM_API", nil), + "GEM_HOME" => nil, ) @ruby_args ||= begin @@ -204,6 +205,7 @@ RSpec.shared_context "integration test" do # rubocop:disable RSpec/ContextWordin end formula_path = Formulary.find_formula_in_tap(name.downcase, tap).tap do |path| + path.dirname.mkpath path.write <<~RUBY class #{Formulary.class_s(name)} < Formula #{content.gsub(/^(?!$)/, " ")} diff --git a/Library/Homebrew/test/tap_spec.rb b/Library/Homebrew/test/tap_spec.rb index 8bea008043..6f60403281 100644 --- a/Library/Homebrew/test/tap_spec.rb +++ b/Library/Homebrew/test/tap_spec.rb @@ -500,7 +500,6 @@ RSpec.describe Tap do end it "includes the core tap with the api" do - ENV.delete("HOMEBREW_NO_INSTALL_FROM_API") expect(described_class.to_a).to include(CoreTap.instance) end @@ -580,7 +579,7 @@ RSpec.describe Tap do let(:cask_tap) { CoreCaskTap.instance } let(:core_tap) { CoreTap.instance } - it "returns expected renames" do + it "returns expected renames", :no_api do [ [cask_tap, "gimp", []], [core_tap, "schism-tracker", []], @@ -744,11 +743,11 @@ RSpec.describe Tap do expect(core_tap).to be_a_core_tap end - specify "forbidden operations" do + specify "forbidden operations", :no_api do expect { core_tap.uninstall }.to raise_error(RuntimeError) end - specify "files" do + specify "files", :no_api do path = HOMEBREW_TAP_DIRECTORY/"homebrew/homebrew-core" formula_file = core_tap.formula_dir/"foo.rb" core_tap.formula_dir.mkpath diff --git a/Library/Homebrew/test/utils/shell_spec.rb b/Library/Homebrew/test/utils/shell_spec.rb index 66cf8edfd8..bd07c39d71 100644 --- a/Library/Homebrew/test/utils/shell_spec.rb +++ b/Library/Homebrew/test/utils/shell_spec.rb @@ -107,18 +107,34 @@ RSpec.describe Utils::Shell do end describe "::shell_with_prompt" do + let(:home) { HOMEBREW_TEMP } + let(:notice) { "" } + let(:prompt) { "test" } + let(:path) { "/some/path" } + it "returns zsh-specific prompt configuration" do - ENV["SHELL"] = "/bin/zsh" - expect(described_class.shell_with_prompt("test", preferred_path: "/bin/zsh", notice: "")).to eq( - "PROMPT='%B%F{green}test%f %F{blue}$%f%b ' RPROMPT='[%B%F{red}%~%f%b]' /bin/zsh -f", - ) + preferred_path = "/bin/zsh" + ENV["SHELL"] = preferred_path + ENV["PATH"] = path + zdotdir = "#{HOMEBREW_TEMP}/brew-zsh-prompt-#{Process.euid}" + expect(described_class.shell_with_prompt(prompt, preferred_path:, notice:, home:)).to eq \ + "BREW_PROMPT_PATH=\"#{path}\" BREW_PROMPT_TYPE=\"#{prompt}\" ZDOTDIR=\"#{zdotdir}\" #{preferred_path}" + end + + it "returns bash-specific prompt configuration" do + preferred_path = "/bin/bash" + ENV["SHELL"] = "/bin/bash" + ENV["PATH"] = path + rcfile = "#{HOMEBREW_LIBRARY_PATH}/utils/bash/brew-sh-prompt-bashrc.bash" + expect(described_class.shell_with_prompt(prompt, preferred_path:, notice:, home:)).to eq \ + "BREW_PROMPT_PATH=\"#{path}\" BREW_PROMPT_TYPE=\"#{prompt}\" #{preferred_path} --rcfile \"#{rcfile}\"" end it "returns generic shell prompt configuration" do - ENV["SHELL"] = "/bin/bash" - expect(described_class.shell_with_prompt("test", preferred_path: "/bin/bash", notice: "")).to eq( - "PS1=\"\\[\\033[1;32m\\]brew \\[\\033[1;31m\\]\\w \\[\\033[1;34m\\]$\\[\\033[0m\\] \" /bin/bash", - ) + preferred_path = "/bin/dash" + ENV["SHELL"] = preferred_path + expect(described_class.shell_with_prompt(prompt, preferred_path:, notice:, home:)).to eq \ + "PS1=\"\\[\\033[1;32m\\]#{prompt} \\[\\033[1;31m\\]\\w \\[\\033[1;34m\\]$\\[\\033[0m\\] \" #{preferred_path}" end it "outputs notice when provided" do diff --git a/Library/Homebrew/utils/analytics.rb b/Library/Homebrew/utils/analytics.rb index 54674b019f..003290f824 100644 --- a/Library/Homebrew/utils/analytics.rb +++ b/Library/Homebrew/utils/analytics.rb @@ -4,7 +4,7 @@ require "context" require "erb" require "settings" -require "extend/cachable" +require "cachable" module Utils # Helper module for fetching and reporting analytics data. diff --git a/Library/Homebrew/utils/backtrace.rb b/Library/Homebrew/utils/backtrace.rb index b04f349729..376e5fc5c9 100644 --- a/Library/Homebrew/utils/backtrace.rb +++ b/Library/Homebrew/utils/backtrace.rb @@ -31,7 +31,8 @@ module Utils def self.print_backtrace_message return if @print_backtrace_message - opoo "Removed Sorbet lines from backtrace!" + # This is just unactionable noise in GitHub Actions. + opoo_outside_github_actions "Removed Sorbet lines from backtrace!" puts "Rerun with `--verbose` to see the original backtrace" unless Homebrew::EnvConfig.no_env_hints? @print_backtrace_message = true diff --git a/Library/Homebrew/utils/bash/brew-sh-prompt-bashrc.bash b/Library/Homebrew/utils/bash/brew-sh-prompt-bashrc.bash new file mode 100644 index 0000000000..d4d9dd7e3e --- /dev/null +++ b/Library/Homebrew/utils/bash/brew-sh-prompt-bashrc.bash @@ -0,0 +1,12 @@ +# Read the user's ~/.bashrc first +if [[ -f "${HOME}/.bashrc" ]] +then + source "${HOME}/.bashrc" +fi + +# Override the user's Bash prompt with our custom prompt +export PS1="\\[\\033[1;32m\\]${BREW_PROMPT_TYPE} \\[\\033[1;31m\\]\\w \\[\\033[1;34m\\]$\\[\\033[0m\\] " + +# Add the Homebrew PATH in front of the user's PATH +export PATH="${BREW_PROMPT_PATH}:${PATH}" +unset BREW_PROMPT_TYPE BREW_PROMPT_PATH diff --git a/Library/Homebrew/utils/shell.rb b/Library/Homebrew/utils/shell.rb index 4582542438..bb9396d5fd 100644 --- a/Library/Homebrew/utils/shell.rb +++ b/Library/Homebrew/utils/shell.rb @@ -153,14 +153,28 @@ module Utils str end - sig { params(type: String, preferred_path: String, notice: T.nilable(String)).returns(String) } - def shell_with_prompt(type, preferred_path:, notice:) + sig { params(type: String, preferred_path: String, notice: T.nilable(String), home: String).returns(String) } + def shell_with_prompt(type, preferred_path:, notice:, home: Dir.home) preferred = from_path(preferred_path) + path = ENV.fetch("PATH") subshell = case preferred when :zsh - "PROMPT='%B%F{green}#{type}%f %F{blue}$%f%b ' RPROMPT='[%B%F{red}%~%f%b]' #{preferred_path} -f" + zdotdir = Pathname.new(HOMEBREW_TEMP/"brew-zsh-prompt-#{Process.euid}") + zdotdir.mkpath + FileUtils.chmod_R(0700, zdotdir) + FileUtils.cp(HOMEBREW_LIBRARY_PATH/"utils/zsh/brew-sh-prompt-zshrc.zsh", zdotdir/".zshrc") + %w[.zcompdump .zsh_history .zsh_sessions].each do |file| + FileUtils.ln_sf("#{home}/#{file}", zdotdir/file) + end + <<~ZSH.strip + BREW_PROMPT_PATH="#{path}" BREW_PROMPT_TYPE="#{type}" ZDOTDIR="#{zdotdir}" #{preferred_path} + ZSH + when :bash + <<~BASH.strip + BREW_PROMPT_PATH="#{path}" BREW_PROMPT_TYPE="#{type}" #{preferred_path} --rcfile "#{HOMEBREW_LIBRARY_PATH}/utils/bash/brew-sh-prompt-bashrc.bash" + BASH else - "PS1=\"\\[\\033[1;32m\\]brew \\[\\033[1;31m\\]\\w \\[\\033[1;34m\\]$\\[\\033[0m\\] \" #{preferred_path}" + "PS1=\"\\[\\033[1;32m\\]#{type} \\[\\033[1;31m\\]\\w \\[\\033[1;34m\\]$\\[\\033[0m\\] \" #{preferred_path}" end puts notice if notice.present? diff --git a/Library/Homebrew/utils/zsh/brew-sh-prompt-zshrc.zsh b/Library/Homebrew/utils/zsh/brew-sh-prompt-zshrc.zsh new file mode 100644 index 0000000000..8ef8cda5ac --- /dev/null +++ b/Library/Homebrew/utils/zsh/brew-sh-prompt-zshrc.zsh @@ -0,0 +1,13 @@ +# Read the user's ~/.zshrc first +if [[ -f "${HOME}/.zshrc" ]] +then + source "${HOME}/.zshrc" +fi + +# Override the user's ZSH prompt with our custom prompt +export PROMPT="%B%F{green}${BREW_PROMPT_TYPE}%f %F{blue}$%f%b " +export RPROMPT="[%B%F{red}%~%f%b]" + +# Add the Homebrew PATH in front of the user's PATH +export PATH="${BREW_PROMPT_PATH}:${PATH}" +unset BREW_PROMPT_TYPE BREW_PROMPT_PATH diff --git a/bin/brew b/bin/brew index 3ccf7f68a2..3ed923d1e4 100755 --- a/bin/brew +++ b/bin/brew @@ -57,22 +57,6 @@ do done unset cmd -# Avoid picking up any random `sudo` in `PATH`. -if [[ -x /usr/bin/sudo ]] -then - SUDO=/usr/bin/sudo -else - # Do this after ensuring we're using default Bash builtins. - SUDO="$(command -v sudo 2>/dev/null)" -fi - -# Reset sudo timestamp to avoid running unauthorized sudo commands -if [[ -n "${SUDO}" ]] -then - "${SUDO}" --reset-timestamp 2>/dev/null || true -fi -unset SUDO - # Take the HOMEBREW_PATH if we are running brew within brew, otherwise we would lose the original path. if [[ -n "${HOMEBREW_BREW_FILE:-}" && -n "${HOMEBREW_PATH:-}" ]] then @@ -199,8 +183,8 @@ MANPAGE_VARS=( ) for VAR in "${MANPAGE_VARS[@]}" do - # Skip if variable value is empty. - [[ -z "${!VAR:-}" ]] && continue + # Skip if variable value is empty or set to 0. + [[ -z "${!VAR:-}" || "${!VAR:-}" = "0" ]] && continue VAR_NEW="HOMEBREW_${VAR}" # Skip if existing HOMEBREW_* variable is set. diff --git a/completions/bash/brew b/completions/bash/brew index 7e00bdfa81..9b11a30207 100644 --- a/completions/bash/brew +++ b/completions/bash/brew @@ -1797,6 +1797,22 @@ _brew_ls() { __brew_complete_installed_casks } +_brew_mcp_server() { + local cur="${COMP_WORDS[COMP_CWORD]}" + case "${cur}" in + -*) + __brewcomp " + --debug + --help + --quiet + --verbose + " + return + ;; + *) ;; + esac +} + _brew_migrate() { local cur="${COMP_WORDS[COMP_CWORD]}" case "${cur}" in @@ -2572,6 +2588,7 @@ _brew_tests() { --fail-fast --generic --help + --no-parallel --online --only --profile @@ -3191,6 +3208,7 @@ _brew() { ln) _brew_ln ;; log) _brew_log ;; ls) _brew_ls ;; + mcp-server) _brew_mcp_server ;; migrate) _brew_migrate ;; missing) _brew_missing ;; nodenv-sync) _brew_nodenv_sync ;; diff --git a/completions/fish/brew.fish b/completions/fish/brew.fish index 0457b6dd6a..04701edb8d 100644 --- a/completions/fish/brew.fish +++ b/completions/fish/brew.fish @@ -344,7 +344,7 @@ __fish_brew_complete_arg 'audit' -l audit-debug -d 'Enable debugging and profili __fish_brew_complete_arg 'audit' -l cask -d 'Treat all named arguments as casks' __fish_brew_complete_arg 'audit' -l debug -d 'Display any debugging information' __fish_brew_complete_arg 'audit' -l display-filename -d 'Prefix every line of output with the file or formula name being audited, to make output easy to grep' -__fish_brew_complete_arg 'audit' -l eval-all -d 'Evaluate all available formulae and casks, whether installed or not, to audit them. Implied if `HOMEBREW_EVAL_ALL` is set' +__fish_brew_complete_arg 'audit' -l eval-all -d 'Evaluate all available formulae and casks, whether installed or not, to audit them. Implied if `$HOMEBREW_EVAL_ALL` is set' __fish_brew_complete_arg 'audit' -l except -d 'Specify a comma-separated method list to skip running the methods named `audit_`method' __fish_brew_complete_arg 'audit' -l except-cops -d 'Specify a comma-separated cops list to skip checking for violations of the listed RuboCop cops' __fish_brew_complete_arg 'audit' -l fix -d 'Fix style violations automatically using RuboCop\'s auto-correct feature' @@ -508,9 +508,9 @@ __fish_brew_complete_sub_cmd 'bundle' 'edit' __fish_brew_complete_arg 'bundle' -l all -d '`list` all dependencies' __fish_brew_complete_arg 'bundle' -l cask -d '`list`, `dump` or `cleanup` Homebrew cask dependencies' __fish_brew_complete_arg 'bundle' -l check -d 'Check that all dependencies in the Brewfile are installed before running `exec`, `sh`, or `env`' -__fish_brew_complete_arg 'bundle' -l cleanup -d '`install` performs cleanup operation, same as running `cleanup --force`. This is enabled by default if `$HOMEBREW_BUNDLE_INSTALL_CLEANUP` is set and `--global` is passed' +__fish_brew_complete_arg 'bundle' -l cleanup -d '`install` performs cleanup operation, same as running `cleanup --force`. Enabled by default if `$HOMEBREW_BUNDLE_INSTALL_CLEANUP` is set and `--global` is passed' __fish_brew_complete_arg 'bundle' -l debug -d 'Display any debugging information' -__fish_brew_complete_arg 'bundle' -l describe -d '`dump` adds a description comment above each line, unless the dependency does not have a description. This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_DESCRIBE` is set' +__fish_brew_complete_arg 'bundle' -l describe -d '`dump` adds a description comment above each line, unless the dependency does not have a description. Enabled by default if `$HOMEBREW_BUNDLE_DUMP_DESCRIBE` is set' __fish_brew_complete_arg 'bundle' -l file -d 'Read from or write to the `Brewfile` from this location. Use `--file=-` to pipe to stdin/stdout' __fish_brew_complete_arg 'bundle' -l force -d '`install` runs with `--force`/`--overwrite`. `dump` overwrites an existing `Brewfile`. `cleanup` actually performs its cleanup operations' __fish_brew_complete_arg 'bundle' -l formula -d '`list`, `dump` or `cleanup` Homebrew formula dependencies' @@ -519,10 +519,10 @@ __fish_brew_complete_arg 'bundle' -l help -d 'Show this message' __fish_brew_complete_arg 'bundle' -l install -d 'Run `install` before continuing to other operations e.g. `exec`' __fish_brew_complete_arg 'bundle' -l mas -d '`list` or `dump` Mac App Store dependencies' __fish_brew_complete_arg 'bundle' -l no-restart -d '`dump` does not add `restart_service` to formula lines' -__fish_brew_complete_arg 'bundle' -l no-upgrade -d '`install` does not run `brew upgrade` on outdated dependencies. `check` does not check for outdated dependencies. Note they may still be upgraded by `brew install` if needed. This is enabled by default if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set' -__fish_brew_complete_arg 'bundle' -l no-vscode -d '`dump` without VSCode (and forks/variants) extensions. This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_NO_VSCODE` is set' +__fish_brew_complete_arg 'bundle' -l no-upgrade -d '`install` does not run `brew upgrade` on outdated dependencies. `check` does not check for outdated dependencies. Note they may still be upgraded by `brew install` if needed. Enabled by default if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set' +__fish_brew_complete_arg 'bundle' -l no-vscode -d '`dump` without VSCode (and forks/variants) extensions. Enabled by default if `$HOMEBREW_BUNDLE_DUMP_NO_VSCODE` is set' __fish_brew_complete_arg 'bundle' -l quiet -d 'Make some output more quiet' -__fish_brew_complete_arg 'bundle' -l services -d 'Temporarily start services while running the `exec` or `sh` command. This is enabled by default if `$HOMEBREW_BUNDLE_SERVICES` is set' +__fish_brew_complete_arg 'bundle' -l services -d 'Temporarily start services while running the `exec` or `sh` command. Enabled by default if `$HOMEBREW_BUNDLE_SERVICES` is set' __fish_brew_complete_arg 'bundle' -l tap -d '`list`, `dump` or `cleanup` Homebrew tap dependencies' __fish_brew_complete_arg 'bundle' -l upgrade -d '`install` runs `brew upgrade` on outdated dependencies, even if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set' __fish_brew_complete_arg 'bundle' -l upgrade-formulae -d '`install` runs `brew upgrade` on any of these comma-separated formulae, even if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set' @@ -694,8 +694,8 @@ __fish_brew_complete_arg 'desc; and not __fish_seen_argument -l formula -l formu __fish_brew_complete_cmd 'determine-test-runners' 'Determines the runners used to test formulae or their dependents' __fish_brew_complete_arg 'determine-test-runners' -l all-supported -d 'Instead of selecting runners based on the chosen formula, return all supported runners' __fish_brew_complete_arg 'determine-test-runners' -l debug -d 'Display any debugging information' -__fish_brew_complete_arg 'determine-test-runners' -l dependents -d 'Determine runners for testing dependents. Requires `--eval-all` or `HOMEBREW_EVAL_ALL`' -__fish_brew_complete_arg 'determine-test-runners' -l eval-all -d 'Evaluate all available formulae, whether installed or not, to determine testing dependents' +__fish_brew_complete_arg 'determine-test-runners' -l dependents -d 'Determine runners for testing dependents. Requires `--eval-all` or `$HOMEBREW_EVAL_ALL` to be set' +__fish_brew_complete_arg 'determine-test-runners' -l eval-all -d 'Evaluate all available formulae, whether installed or not, to determine testing dependents. Enabled by default if `$HOMEBREW_EVAL_ALL` is set' __fish_brew_complete_arg 'determine-test-runners' -l help -d 'Show this message' __fish_brew_complete_arg 'determine-test-runners' -l quiet -d 'Make some output more quiet' __fish_brew_complete_arg 'determine-test-runners' -l verbose -d 'Make some output more verbose' @@ -756,7 +756,7 @@ __fish_brew_complete_arg 'dr' -l verbose -d 'Make some output more verbose' __fish_brew_complete_arg 'dr' -a '(__fish_brew_suggest_diagnostic_checks)' -__fish_brew_complete_cmd 'edit' 'Open a formula, cask or tap in the editor set by `EDITOR` or `HOMEBREW_EDITOR`, or open the Homebrew repository for editing if no argument is provided' +__fish_brew_complete_cmd 'edit' 'Open a formula, cask or tap in the editor set by `$EDITOR` or `$HOMEBREW_EDITOR`, or open the Homebrew repository for editing if no argument is provided' __fish_brew_complete_arg 'edit' -l cask -d 'Treat all named arguments as casks' __fish_brew_complete_arg 'edit' -l debug -d 'Display any debugging information' __fish_brew_complete_arg 'edit' -l formula -d 'Treat all named arguments as formulae' @@ -804,9 +804,9 @@ __fish_brew_complete_arg 'fetch' -l force -d 'Remove a previously cached version __fish_brew_complete_arg 'fetch' -l force-bottle -d 'Download a bottle if it exists for the current or newest version of macOS, even if it would not be used during installation' __fish_brew_complete_arg 'fetch' -l formula -d 'Treat all named arguments as formulae' __fish_brew_complete_arg 'fetch' -l help -d 'Show this message' -__fish_brew_complete_arg 'fetch' -l no-quarantine -d 'Disable/enable quarantining of downloads (default: enabled)' +__fish_brew_complete_arg 'fetch' -l no-quarantine -d 'Disable/enable quarantining of downloads (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_QUARANTINE` is set' __fish_brew_complete_arg 'fetch' -l os -d 'Download for the given operating system. (Pass `all` to download for all operating systems.)' -__fish_brew_complete_arg 'fetch' -l quarantine -d 'Disable/enable quarantining of downloads (default: enabled)' +__fish_brew_complete_arg 'fetch' -l quarantine -d 'Disable/enable quarantining of downloads (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_QUARANTINE` is set' __fish_brew_complete_arg 'fetch' -l quiet -d 'Make some output more quiet' __fish_brew_complete_arg 'fetch' -l retry -d 'Retry if downloading fails or re-download if the checksum of a previously cached version no longer matches. Tries at most 5 times with exponential backoff' __fish_brew_complete_arg 'fetch' -l verbose -d 'Do a verbose VCS checkout, if the URL represents a VCS. This is useful for seeing if an existing VCS cache has been updated' @@ -952,9 +952,9 @@ __fish_brew_complete_arg 'instal' -l HEAD -d 'If formula defines it, install the __fish_brew_complete_arg 'instal' -l adopt -d 'Adopt existing artifacts in the destination that are identical to those being installed. Cannot be combined with `--force`' __fish_brew_complete_arg 'instal' -l appdir -d 'Target location for Applications (default: `/Applications`)' __fish_brew_complete_arg 'instal' -l as-dependency -d 'Install but mark as installed as a dependency and not installed on request' -__fish_brew_complete_arg 'instal' -l ask -d 'Ask for confirmation before downloading and installing formulae. Print bottles and dependencies download size and install size' +__fish_brew_complete_arg 'instal' -l ask -d 'Ask for confirmation before downloading and installing formulae. Print download and install sizes of bottles and dependencies. Enabled by default if `$HOMEBREW_ASK` is set' __fish_brew_complete_arg 'instal' -l audio-unit-plugindir -d 'Target location for Audio Unit Plugins (default: `~/Library/Audio/Plug-Ins/Components`)' -__fish_brew_complete_arg 'instal' -l binaries -d 'Disable/enable linking of helper executables (default: enabled)' +__fish_brew_complete_arg 'instal' -l binaries -d 'Disable/enable linking of helper executables (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_BINARIES` is set' __fish_brew_complete_arg 'instal' -l bottle-arch -d 'Optimise bottles for the specified architecture rather than the oldest architecture supported by the version of macOS the bottles are built on' __fish_brew_complete_arg 'instal' -l build-bottle -d 'Prepare the formula for eventual bottling during installation, skipping any post-install steps' __fish_brew_complete_arg 'instal' -l build-from-source -d 'Compile formula from source even if a bottle is provided. Dependencies will still be installed from bottles if they are available' @@ -964,7 +964,7 @@ __fish_brew_complete_arg 'instal' -l colorpickerdir -d 'Target location for Colo __fish_brew_complete_arg 'instal' -l debug -d 'If brewing fails, open an interactive debugging session with access to IRB or a shell inside the temporary build directory' __fish_brew_complete_arg 'instal' -l debug-symbols -d 'Generate debug symbols on build. Source will be retained in a cache directory' __fish_brew_complete_arg 'instal' -l dictionarydir -d 'Target location for Dictionaries (default: `~/Library/Dictionaries`)' -__fish_brew_complete_arg 'instal' -l display-times -d 'Print install times for each package at the end of the run' +__fish_brew_complete_arg 'instal' -l display-times -d 'Print install times for each package at the end of the run. Enabled by default if `$HOMEBREW_DISPLAY_INSTALL_TIMES` is set' __fish_brew_complete_arg 'instal' -l dry-run -d 'Show what would be installed, but do not actually install anything' __fish_brew_complete_arg 'instal' -l fetch-HEAD -d 'Fetch the upstream repository to detect if the HEAD installation of the formula is outdated. Otherwise, the repository\'s HEAD will only be checked for updates when a new stable or development version has been released' __fish_brew_complete_arg 'instal' -l fontdir -d 'Target location for Fonts (default: `~/Library/Fonts`)' @@ -982,15 +982,15 @@ __fish_brew_complete_arg 'instal' -l keep-tmp -d 'Retain the temporary files cre __fish_brew_complete_arg 'instal' -l keyboard-layoutdir -d 'Target location for Keyboard Layouts (default: `/Library/Keyboard Layouts`)' __fish_brew_complete_arg 'instal' -l language -d 'Comma-separated list of language codes to prefer for cask installation. The first matching language is used, otherwise it reverts to the cask\'s default language. The default value is the language of your system' __fish_brew_complete_arg 'instal' -l mdimporterdir -d 'Target location for Spotlight Plugins (default: `~/Library/Spotlight`)' -__fish_brew_complete_arg 'instal' -l no-binaries -d 'Disable/enable linking of helper executables (default: enabled)' -__fish_brew_complete_arg 'instal' -l no-quarantine -d 'Disable/enable quarantining of downloads (default: enabled)' +__fish_brew_complete_arg 'instal' -l no-binaries -d 'Disable/enable linking of helper executables (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_BINARIES` is set' +__fish_brew_complete_arg 'instal' -l no-quarantine -d 'Disable/enable quarantining of downloads (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_QUARANTINE` is set' __fish_brew_complete_arg 'instal' -l only-dependencies -d 'Install the dependencies with specified options but do not install the formula itself' __fish_brew_complete_arg 'instal' -l overwrite -d 'Delete files that already exist in the prefix while linking' __fish_brew_complete_arg 'instal' -l prefpanedir -d 'Target location for Preference Panes (default: `~/Library/PreferencePanes`)' __fish_brew_complete_arg 'instal' -l qlplugindir -d 'Target location for Quick Look Plugins (default: `~/Library/QuickLook`)' -__fish_brew_complete_arg 'instal' -l quarantine -d 'Disable/enable quarantining of downloads (default: enabled)' +__fish_brew_complete_arg 'instal' -l quarantine -d 'Disable/enable quarantining of downloads (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_QUARANTINE` is set' __fish_brew_complete_arg 'instal' -l quiet -d 'Make some output more quiet' -__fish_brew_complete_arg 'instal' -l require-sha -d 'Require all casks to have a checksum' +__fish_brew_complete_arg 'instal' -l require-sha -d 'Require all casks to have a checksum. Enabled by default if `$HOMEBREW_CASK_OPTS_REQUIRE_SHA` is set' __fish_brew_complete_arg 'instal' -l screen-saverdir -d 'Target location for Screen Savers (default: `~/Library/Screen Savers`)' __fish_brew_complete_arg 'instal' -l servicedir -d 'Target location for Services (default: `~/Library/Services`)' __fish_brew_complete_arg 'instal' -l skip-cask-deps -d 'Skip installing cask dependencies' @@ -1009,9 +1009,9 @@ __fish_brew_complete_arg 'install' -l HEAD -d 'If formula defines it, install th __fish_brew_complete_arg 'install' -l adopt -d 'Adopt existing artifacts in the destination that are identical to those being installed. Cannot be combined with `--force`' __fish_brew_complete_arg 'install' -l appdir -d 'Target location for Applications (default: `/Applications`)' __fish_brew_complete_arg 'install' -l as-dependency -d 'Install but mark as installed as a dependency and not installed on request' -__fish_brew_complete_arg 'install' -l ask -d 'Ask for confirmation before downloading and installing formulae. Print bottles and dependencies download size and install size' +__fish_brew_complete_arg 'install' -l ask -d 'Ask for confirmation before downloading and installing formulae. Print download and install sizes of bottles and dependencies. Enabled by default if `$HOMEBREW_ASK` is set' __fish_brew_complete_arg 'install' -l audio-unit-plugindir -d 'Target location for Audio Unit Plugins (default: `~/Library/Audio/Plug-Ins/Components`)' -__fish_brew_complete_arg 'install' -l binaries -d 'Disable/enable linking of helper executables (default: enabled)' +__fish_brew_complete_arg 'install' -l binaries -d 'Disable/enable linking of helper executables (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_BINARIES` is set' __fish_brew_complete_arg 'install' -l bottle-arch -d 'Optimise bottles for the specified architecture rather than the oldest architecture supported by the version of macOS the bottles are built on' __fish_brew_complete_arg 'install' -l build-bottle -d 'Prepare the formula for eventual bottling during installation, skipping any post-install steps' __fish_brew_complete_arg 'install' -l build-from-source -d 'Compile formula from source even if a bottle is provided. Dependencies will still be installed from bottles if they are available' @@ -1021,7 +1021,7 @@ __fish_brew_complete_arg 'install' -l colorpickerdir -d 'Target location for Col __fish_brew_complete_arg 'install' -l debug -d 'If brewing fails, open an interactive debugging session with access to IRB or a shell inside the temporary build directory' __fish_brew_complete_arg 'install' -l debug-symbols -d 'Generate debug symbols on build. Source will be retained in a cache directory' __fish_brew_complete_arg 'install' -l dictionarydir -d 'Target location for Dictionaries (default: `~/Library/Dictionaries`)' -__fish_brew_complete_arg 'install' -l display-times -d 'Print install times for each package at the end of the run' +__fish_brew_complete_arg 'install' -l display-times -d 'Print install times for each package at the end of the run. Enabled by default if `$HOMEBREW_DISPLAY_INSTALL_TIMES` is set' __fish_brew_complete_arg 'install' -l dry-run -d 'Show what would be installed, but do not actually install anything' __fish_brew_complete_arg 'install' -l fetch-HEAD -d 'Fetch the upstream repository to detect if the HEAD installation of the formula is outdated. Otherwise, the repository\'s HEAD will only be checked for updates when a new stable or development version has been released' __fish_brew_complete_arg 'install' -l fontdir -d 'Target location for Fonts (default: `~/Library/Fonts`)' @@ -1039,15 +1039,15 @@ __fish_brew_complete_arg 'install' -l keep-tmp -d 'Retain the temporary files cr __fish_brew_complete_arg 'install' -l keyboard-layoutdir -d 'Target location for Keyboard Layouts (default: `/Library/Keyboard Layouts`)' __fish_brew_complete_arg 'install' -l language -d 'Comma-separated list of language codes to prefer for cask installation. The first matching language is used, otherwise it reverts to the cask\'s default language. The default value is the language of your system' __fish_brew_complete_arg 'install' -l mdimporterdir -d 'Target location for Spotlight Plugins (default: `~/Library/Spotlight`)' -__fish_brew_complete_arg 'install' -l no-binaries -d 'Disable/enable linking of helper executables (default: enabled)' -__fish_brew_complete_arg 'install' -l no-quarantine -d 'Disable/enable quarantining of downloads (default: enabled)' +__fish_brew_complete_arg 'install' -l no-binaries -d 'Disable/enable linking of helper executables (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_BINARIES` is set' +__fish_brew_complete_arg 'install' -l no-quarantine -d 'Disable/enable quarantining of downloads (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_QUARANTINE` is set' __fish_brew_complete_arg 'install' -l only-dependencies -d 'Install the dependencies with specified options but do not install the formula itself' __fish_brew_complete_arg 'install' -l overwrite -d 'Delete files that already exist in the prefix while linking' __fish_brew_complete_arg 'install' -l prefpanedir -d 'Target location for Preference Panes (default: `~/Library/PreferencePanes`)' __fish_brew_complete_arg 'install' -l qlplugindir -d 'Target location for Quick Look Plugins (default: `~/Library/QuickLook`)' -__fish_brew_complete_arg 'install' -l quarantine -d 'Disable/enable quarantining of downloads (default: enabled)' +__fish_brew_complete_arg 'install' -l quarantine -d 'Disable/enable quarantining of downloads (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_QUARANTINE` is set' __fish_brew_complete_arg 'install' -l quiet -d 'Make some output more quiet' -__fish_brew_complete_arg 'install' -l require-sha -d 'Require all casks to have a checksum' +__fish_brew_complete_arg 'install' -l require-sha -d 'Require all casks to have a checksum. Enabled by default if `$HOMEBREW_CASK_OPTS_REQUIRE_SHA` is set' __fish_brew_complete_arg 'install' -l screen-saverdir -d 'Target location for Screen Savers (default: `~/Library/Screen Savers`)' __fish_brew_complete_arg 'install' -l servicedir -d 'Target location for Services (default: `~/Library/Services`)' __fish_brew_complete_arg 'install' -l skip-cask-deps -d 'Skip installing cask dependencies' @@ -1074,7 +1074,7 @@ __fish_brew_complete_cmd 'irb' 'Enter the interactive Homebrew Ruby shell' __fish_brew_complete_arg 'irb' -l debug -d 'Display any debugging information' __fish_brew_complete_arg 'irb' -l examples -d 'Show several examples' __fish_brew_complete_arg 'irb' -l help -d 'Show this message' -__fish_brew_complete_arg 'irb' -l pry -d 'Use Pry instead of IRB. Implied if `HOMEBREW_PRY` is set' +__fish_brew_complete_arg 'irb' -l pry -d 'Use Pry instead of IRB. Enabled by default if `$HOMEBREW_PRY` is set' __fish_brew_complete_arg 'irb' -l quiet -d 'Make some output more quiet' __fish_brew_complete_arg 'irb' -l verbose -d 'Make some output more verbose' @@ -1121,7 +1121,7 @@ __fish_brew_complete_arg 'link' -a '(__fish_brew_suggest_formulae_installed)' __fish_brew_complete_cmd 'linkage' 'Check the library links from the given formula kegs' -__fish_brew_complete_arg 'linkage' -l cached -d 'Print the cached linkage values stored in `HOMEBREW_CACHE`, set by a previous `brew linkage` run' +__fish_brew_complete_arg 'linkage' -l cached -d 'Print the cached linkage values stored in `$HOMEBREW_CACHE`, set by a previous `brew linkage` run' __fish_brew_complete_arg 'linkage' -l debug -d 'Display any debugging information' __fish_brew_complete_arg 'linkage' -l help -d 'Show this message' __fish_brew_complete_arg 'linkage' -l quiet -d 'Make some output more quiet' @@ -1226,6 +1226,13 @@ __fish_brew_complete_arg 'ls; and not __fish_seen_argument -l cask -l casks' -a __fish_brew_complete_arg 'ls; and not __fish_seen_argument -l formula -l formulae' -a '(__fish_brew_suggest_casks_installed)' +__fish_brew_complete_cmd 'mcp-server' 'Starts the Homebrew MCP (Model Context Protocol) server' +__fish_brew_complete_arg 'mcp-server' -l debug -d 'Enable debug logging to stderr' +__fish_brew_complete_arg 'mcp-server' -l help -d 'Show this message' +__fish_brew_complete_arg 'mcp-server' -l quiet -d 'Make some output more quiet' +__fish_brew_complete_arg 'mcp-server' -l verbose -d 'Make some output more verbose' + + __fish_brew_complete_cmd 'migrate' 'Migrate renamed packages to new names, where formula are old names of packages' __fish_brew_complete_arg 'migrate' -l cask -d 'Only migrate casks' __fish_brew_complete_arg 'migrate' -l debug -d 'Display any debugging information' @@ -1272,7 +1279,7 @@ __fish_brew_complete_arg 'outdated' -l cask -d 'List only outdated casks' __fish_brew_complete_arg 'outdated' -l debug -d 'Display any debugging information' __fish_brew_complete_arg 'outdated' -l fetch-HEAD -d 'Fetch the upstream repository to detect if the HEAD installation of the formula is outdated. Otherwise, the repository\'s HEAD will only be checked for updates when a new stable or development version has been released' __fish_brew_complete_arg 'outdated' -l formula -d 'List only outdated formulae' -__fish_brew_complete_arg 'outdated' -l greedy -d 'Also include outdated casks with `auto_updates true` or `version :latest`' +__fish_brew_complete_arg 'outdated' -l greedy -d 'Also include outdated casks with `auto_updates true` or `version :latest`. Enabled by default if `$HOMEBREW_UPGRADE_GREEDY` is set' __fish_brew_complete_arg 'outdated' -l greedy-auto-updates -d 'Also include outdated casks including those with `auto_updates true`' __fish_brew_complete_arg 'outdated' -l greedy-latest -d 'Also include outdated casks including those with `version :latest`' __fish_brew_complete_arg 'outdated' -l help -d 'Show this message' @@ -1417,16 +1424,16 @@ __fish_brew_complete_arg 'readall' -a '(__fish_brew_suggest_taps_installed)' __fish_brew_complete_cmd 'reinstall' 'Uninstall and then reinstall a formula or cask using the same options it was originally installed with, plus any appended options specific to a formula' __fish_brew_complete_arg 'reinstall' -l adopt -d 'Adopt existing artifacts in the destination that are identical to those being installed. Cannot be combined with `--force`' __fish_brew_complete_arg 'reinstall' -l appdir -d 'Target location for Applications (default: `/Applications`)' -__fish_brew_complete_arg 'reinstall' -l ask -d 'Ask for confirmation before downloading and upgrading formulae. Print bottles and dependencies download size, install and net install size' +__fish_brew_complete_arg 'reinstall' -l ask -d 'Ask for confirmation before downloading and upgrading formulae. Print download, install and net install sizes of bottles and dependencies. Enabled by default if `$HOMEBREW_ASK` is set' __fish_brew_complete_arg 'reinstall' -l audio-unit-plugindir -d 'Target location for Audio Unit Plugins (default: `~/Library/Audio/Plug-Ins/Components`)' -__fish_brew_complete_arg 'reinstall' -l binaries -d 'Disable/enable linking of helper executables (default: enabled)' +__fish_brew_complete_arg 'reinstall' -l binaries -d 'Disable/enable linking of helper executables (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_BINARIES` is set' __fish_brew_complete_arg 'reinstall' -l build-from-source -d 'Compile formula from source even if a bottle is available' __fish_brew_complete_arg 'reinstall' -l cask -d 'Treat all named arguments as casks' __fish_brew_complete_arg 'reinstall' -l colorpickerdir -d 'Target location for Color Pickers (default: `~/Library/ColorPickers`)' __fish_brew_complete_arg 'reinstall' -l debug -d 'If brewing fails, open an interactive debugging session with access to IRB or a shell inside the temporary build directory' __fish_brew_complete_arg 'reinstall' -l debug-symbols -d 'Generate debug symbols on build. Source will be retained in a cache directory' __fish_brew_complete_arg 'reinstall' -l dictionarydir -d 'Target location for Dictionaries (default: `~/Library/Dictionaries`)' -__fish_brew_complete_arg 'reinstall' -l display-times -d 'Print install times for each package at the end of the run' +__fish_brew_complete_arg 'reinstall' -l display-times -d 'Print install times for each package at the end of the run. Enabled by default if `$HOMEBREW_DISPLAY_INSTALL_TIMES` is set' __fish_brew_complete_arg 'reinstall' -l fontdir -d 'Target location for Fonts (default: `~/Library/Fonts`)' __fish_brew_complete_arg 'reinstall' -l force -d 'Install without checking for previously installed keg-only or non-migrated versions' __fish_brew_complete_arg 'reinstall' -l force-bottle -d 'Install from a bottle if it exists for the current or newest version of macOS, even if it would not normally be used for installation' @@ -1440,13 +1447,13 @@ __fish_brew_complete_arg 'reinstall' -l keep-tmp -d 'Retain the temporary files __fish_brew_complete_arg 'reinstall' -l keyboard-layoutdir -d 'Target location for Keyboard Layouts (default: `/Library/Keyboard Layouts`)' __fish_brew_complete_arg 'reinstall' -l language -d 'Comma-separated list of language codes to prefer for cask installation. The first matching language is used, otherwise it reverts to the cask\'s default language. The default value is the language of your system' __fish_brew_complete_arg 'reinstall' -l mdimporterdir -d 'Target location for Spotlight Plugins (default: `~/Library/Spotlight`)' -__fish_brew_complete_arg 'reinstall' -l no-binaries -d 'Disable/enable linking of helper executables (default: enabled)' -__fish_brew_complete_arg 'reinstall' -l no-quarantine -d 'Disable/enable quarantining of downloads (default: enabled)' +__fish_brew_complete_arg 'reinstall' -l no-binaries -d 'Disable/enable linking of helper executables (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_BINARIES` is set' +__fish_brew_complete_arg 'reinstall' -l no-quarantine -d 'Disable/enable quarantining of downloads (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_QUARANTINE` is set' __fish_brew_complete_arg 'reinstall' -l prefpanedir -d 'Target location for Preference Panes (default: `~/Library/PreferencePanes`)' __fish_brew_complete_arg 'reinstall' -l qlplugindir -d 'Target location for Quick Look Plugins (default: `~/Library/QuickLook`)' -__fish_brew_complete_arg 'reinstall' -l quarantine -d 'Disable/enable quarantining of downloads (default: enabled)' +__fish_brew_complete_arg 'reinstall' -l quarantine -d 'Disable/enable quarantining of downloads (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_QUARANTINE` is set' __fish_brew_complete_arg 'reinstall' -l quiet -d 'Make some output more quiet' -__fish_brew_complete_arg 'reinstall' -l require-sha -d 'Require all casks to have a checksum' +__fish_brew_complete_arg 'reinstall' -l require-sha -d 'Require all casks to have a checksum. Enabled by default if `$HOMEBREW_CASK_OPTS_REQUIRE_SHA` is set' __fish_brew_complete_arg 'reinstall' -l screen-saverdir -d 'Target location for Screen Savers (default: `~/Library/Screen Savers`)' __fish_brew_complete_arg 'reinstall' -l servicedir -d 'Target location for Services (default: `~/Library/Services`)' __fish_brew_complete_arg 'reinstall' -l skip-cask-deps -d 'Skip installing cask dependencies' @@ -1575,7 +1582,7 @@ __fish_brew_complete_arg 'setup-ruby' -a '(__fish_brew_suggest_commands)' __fish_brew_complete_cmd 'sh' 'Enter an interactive shell for Homebrew\'s build environment' __fish_brew_complete_arg 'sh' -l cmd -d 'Execute commands in a non-interactive shell' __fish_brew_complete_arg 'sh' -l debug -d 'Display any debugging information' -__fish_brew_complete_arg 'sh' -l env -d 'Use the standard `PATH` instead of superenv\'s when `std` is passed' +__fish_brew_complete_arg 'sh' -l env -d 'Use the standard `$PATH` instead of superenv\'s when `std` is passed' __fish_brew_complete_arg 'sh' -l help -d 'Show this message' __fish_brew_complete_arg 'sh' -l quiet -d 'Make some output more quiet' __fish_brew_complete_arg 'sh' -l verbose -d 'Make some output more verbose' @@ -1686,6 +1693,7 @@ __fish_brew_complete_arg 'tests' -l debug -d 'Enable debugging using `ruby/debug __fish_brew_complete_arg 'tests' -l fail-fast -d 'Exit early on the first failing test' __fish_brew_complete_arg 'tests' -l generic -d 'Run only OS-agnostic tests' __fish_brew_complete_arg 'tests' -l help -d 'Show this message' +__fish_brew_complete_arg 'tests' -l no-parallel -d 'Run tests serially' __fish_brew_complete_arg 'tests' -l online -d 'Include tests that use the GitHub API and tests that use any of the taps for official external commands' __fish_brew_complete_arg 'tests' -l only -d 'Run only `test_script_spec.rb`. Appending `:line_number` will start at a specific line' __fish_brew_complete_arg 'tests' -l profile -d 'Run the test suite serially to find the n slowest tests' @@ -1720,7 +1728,7 @@ __fish_brew_complete_arg 'unalias' -l verbose -d 'Make some output more verbose' __fish_brew_complete_cmd 'unbottled' 'Show the unbottled dependents of formulae' __fish_brew_complete_arg 'unbottled' -l debug -d 'Display any debugging information' __fish_brew_complete_arg 'unbottled' -l dependents -d 'Skip getting analytics data and sort by number of dependents instead' -__fish_brew_complete_arg 'unbottled' -l eval-all -d 'Evaluate all available formulae and casks, whether installed or not, to check them. Implied if `HOMEBREW_EVAL_ALL` is set' +__fish_brew_complete_arg 'unbottled' -l eval-all -d 'Evaluate all available formulae and casks, whether installed or not, to check them. Implied if `$HOMEBREW_EVAL_ALL` is set' __fish_brew_complete_arg 'unbottled' -l help -d 'Show this message' __fish_brew_complete_arg 'unbottled' -l lost -d 'Print the `homebrew/core` commits where bottles were lost in the last week' __fish_brew_complete_arg 'unbottled' -l quiet -d 'Make some output more quiet' @@ -1882,22 +1890,22 @@ __fish_brew_complete_arg 'update-test' -l debug -d 'Display any debugging inform __fish_brew_complete_arg 'update-test' -l help -d 'Show this message' __fish_brew_complete_arg 'update-test' -l keep-tmp -d 'Retain the temporary directory containing the new repository clone' __fish_brew_complete_arg 'update-test' -l quiet -d 'Make some output more quiet' -__fish_brew_complete_arg 'update-test' -l to-tag -d 'Set `HOMEBREW_UPDATE_TO_TAG` to test updating between tags' +__fish_brew_complete_arg 'update-test' -l to-tag -d 'Set `$HOMEBREW_UPDATE_TO_TAG` to test updating between tags' __fish_brew_complete_arg 'update-test' -l verbose -d 'Make some output more verbose' __fish_brew_complete_cmd 'upgrade' 'Upgrade outdated casks and outdated, unpinned formulae using the same options they were originally installed with, plus any appended brew formula options' __fish_brew_complete_arg 'upgrade' -l appdir -d 'Target location for Applications (default: `/Applications`)' -__fish_brew_complete_arg 'upgrade' -l ask -d 'Ask for confirmation before downloading and upgrading formulae. Print bottles and dependencies download size, install and net install size' +__fish_brew_complete_arg 'upgrade' -l ask -d 'Ask for confirmation before downloading and upgrading formulae. Print download, install and net install sizes of bottles and dependencies. Enabled by default if `$HOMEBREW_ASK` is set' __fish_brew_complete_arg 'upgrade' -l audio-unit-plugindir -d 'Target location for Audio Unit Plugins (default: `~/Library/Audio/Plug-Ins/Components`)' -__fish_brew_complete_arg 'upgrade' -l binaries -d 'Disable/enable linking of helper executables (default: enabled)' +__fish_brew_complete_arg 'upgrade' -l binaries -d 'Disable/enable linking of helper executables (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_BINARIES` is set' __fish_brew_complete_arg 'upgrade' -l build-from-source -d 'Compile formula from source even if a bottle is available' __fish_brew_complete_arg 'upgrade' -l cask -d 'Treat all named arguments as casks. If no named arguments are specified, upgrade only outdated casks' __fish_brew_complete_arg 'upgrade' -l colorpickerdir -d 'Target location for Color Pickers (default: `~/Library/ColorPickers`)' __fish_brew_complete_arg 'upgrade' -l debug -d 'If brewing fails, open an interactive debugging session with access to IRB or a shell inside the temporary build directory' __fish_brew_complete_arg 'upgrade' -l debug-symbols -d 'Generate debug symbols on build. Source will be retained in a cache directory' __fish_brew_complete_arg 'upgrade' -l dictionarydir -d 'Target location for Dictionaries (default: `~/Library/Dictionaries`)' -__fish_brew_complete_arg 'upgrade' -l display-times -d 'Print install times for each package at the end of the run' +__fish_brew_complete_arg 'upgrade' -l display-times -d 'Print install times for each package at the end of the run. Enabled by default if `$HOMEBREW_DISPLAY_INSTALL_TIMES` is set' __fish_brew_complete_arg 'upgrade' -l dry-run -d 'Show what would be upgraded, but do not actually upgrade anything' __fish_brew_complete_arg 'upgrade' -l fetch-HEAD -d 'Fetch the upstream repository to detect if the HEAD installation of the formula is outdated. Otherwise, the repository\'s HEAD will only be checked for updates when a new stable or development version has been released' __fish_brew_complete_arg 'upgrade' -l fontdir -d 'Target location for Fonts (default: `~/Library/Fonts`)' @@ -1915,14 +1923,14 @@ __fish_brew_complete_arg 'upgrade' -l keep-tmp -d 'Retain the temporary files cr __fish_brew_complete_arg 'upgrade' -l keyboard-layoutdir -d 'Target location for Keyboard Layouts (default: `/Library/Keyboard Layouts`)' __fish_brew_complete_arg 'upgrade' -l language -d 'Comma-separated list of language codes to prefer for cask installation. The first matching language is used, otherwise it reverts to the cask\'s default language. The default value is the language of your system' __fish_brew_complete_arg 'upgrade' -l mdimporterdir -d 'Target location for Spotlight Plugins (default: `~/Library/Spotlight`)' -__fish_brew_complete_arg 'upgrade' -l no-binaries -d 'Disable/enable linking of helper executables (default: enabled)' -__fish_brew_complete_arg 'upgrade' -l no-quarantine -d 'Disable/enable quarantining of downloads (default: enabled)' +__fish_brew_complete_arg 'upgrade' -l no-binaries -d 'Disable/enable linking of helper executables (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_BINARIES` is set' +__fish_brew_complete_arg 'upgrade' -l no-quarantine -d 'Disable/enable quarantining of downloads (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_QUARANTINE` is set' __fish_brew_complete_arg 'upgrade' -l overwrite -d 'Delete files that already exist in the prefix while linking' __fish_brew_complete_arg 'upgrade' -l prefpanedir -d 'Target location for Preference Panes (default: `~/Library/PreferencePanes`)' __fish_brew_complete_arg 'upgrade' -l qlplugindir -d 'Target location for Quick Look Plugins (default: `~/Library/QuickLook`)' -__fish_brew_complete_arg 'upgrade' -l quarantine -d 'Disable/enable quarantining of downloads (default: enabled)' +__fish_brew_complete_arg 'upgrade' -l quarantine -d 'Disable/enable quarantining of downloads (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_QUARANTINE` is set' __fish_brew_complete_arg 'upgrade' -l quiet -d 'Make some output more quiet' -__fish_brew_complete_arg 'upgrade' -l require-sha -d 'Require all casks to have a checksum' +__fish_brew_complete_arg 'upgrade' -l require-sha -d 'Require all casks to have a checksum. Enabled by default if `$HOMEBREW_CASK_OPTS_REQUIRE_SHA` is set' __fish_brew_complete_arg 'upgrade' -l screen-saverdir -d 'Target location for Screen Savers (default: `~/Library/Screen Savers`)' __fish_brew_complete_arg 'upgrade' -l servicedir -d 'Target location for Services (default: `~/Library/Services`)' __fish_brew_complete_arg 'upgrade' -l skip-cask-deps -d 'Skip installing cask dependencies' diff --git a/completions/internal_commands_list.txt b/completions/internal_commands_list.txt index b0e7542097..dbdc755da3 100644 --- a/completions/internal_commands_list.txt +++ b/completions/internal_commands_list.txt @@ -68,6 +68,7 @@ livecheck ln log ls +mcp-server migrate missing nodenv-sync diff --git a/completions/zsh/_brew b/completions/zsh/_brew index 8d1d4e3da9..fe82678362 100644 --- a/completions/zsh/_brew +++ b/completions/zsh/_brew @@ -167,7 +167,7 @@ __brew_internal_commands() { 'dispatch-build-bottle:Build bottles for these formulae with GitHub Actions' 'docs:Open Homebrew'\''s online documentation at https://docs.brew.sh in a browser' 'doctor:Check your system for potential problems' - 'edit:Open a formula, cask or tap in the editor set by `EDITOR` or `HOMEBREW_EDITOR`, or open the Homebrew repository for editing if no argument is provided' + 'edit:Open a formula, cask or tap in the editor set by `$EDITOR` or `$HOMEBREW_EDITOR`, or open the Homebrew repository for editing if no argument is provided' 'extract:Look through repository history to find the most recent version of formula and create a copy in tap' 'fetch:Download a bottle (if available) or source packages for formulae and binaries for casks' 'formula:Display the path where formula is located' @@ -191,6 +191,7 @@ __brew_internal_commands() { 'list:List all installed formulae and casks' 'livecheck:Check for newer versions of formulae and/or casks from upstream' 'log:Show the `git log` for formula or cask, or show the log for the Homebrew repository if no formula or cask is provided' + 'mcp-server:Starts the Homebrew MCP (Model Context Protocol) server' 'migrate:Migrate renamed packages to new names, where formula are old names of packages' 'missing:Check the given formula kegs for missing dependencies' 'nodenv-sync:Create symlinks for Homebrew'\''s installed NodeJS versions in `~/.nodenv/versions`' @@ -467,7 +468,7 @@ _brew_audit() { '--audit-debug[Enable debugging and profiling of audit methods]' \ '--debug[Display any debugging information]' \ '--display-filename[Prefix every line of output with the file or formula name being audited, to make output easy to grep]' \ - '--eval-all[Evaluate all available formulae and casks, whether installed or not, to audit them. Implied if `HOMEBREW_EVAL_ALL` is set]' \ + '--eval-all[Evaluate all available formulae and casks, whether installed or not, to audit them. Implied if `$HOMEBREW_EVAL_ALL` is set]' \ '(--only)--except[Specify a comma-separated method list to skip running the methods named `audit_`method]' \ '(--only-cops --strict --only-cops --only)--except-cops[Specify a comma-separated cops list to skip checking for violations of the listed RuboCop cops]' \ '--fix[Fix style violations automatically using RuboCop'\''s auto-correct feature]' \ @@ -651,9 +652,9 @@ _brew_bundle() { '(--no-vscode)--all[`list` all dependencies]' \ '--cask[`list`, `dump` or `cleanup` Homebrew cask dependencies]' \ '--check[Check that all dependencies in the Brewfile are installed before running `exec`, `sh`, or `env`]' \ - '--cleanup[`install` performs cleanup operation, same as running `cleanup --force`. This is enabled by default if `$HOMEBREW_BUNDLE_INSTALL_CLEANUP` is set and `--global` is passed]' \ + '--cleanup[`install` performs cleanup operation, same as running `cleanup --force`. Enabled by default if `$HOMEBREW_BUNDLE_INSTALL_CLEANUP` is set and `--global` is passed]' \ '--debug[Display any debugging information]' \ - '--describe[`dump` adds a description comment above each line, unless the dependency does not have a description. This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_DESCRIBE` is set]' \ + '--describe[`dump` adds a description comment above each line, unless the dependency does not have a description. Enabled by default if `$HOMEBREW_BUNDLE_DUMP_DESCRIBE` is set]' \ '--file[Read from or write to the `Brewfile` from this location. Use `--file=-` to pipe to stdin/stdout]' \ '--force[`install` runs with `--force`/`--overwrite`. `dump` overwrites an existing `Brewfile`. `cleanup` actually performs its cleanup operations]' \ '--formula[`list`, `dump` or `cleanup` Homebrew formula dependencies]' \ @@ -662,10 +663,10 @@ _brew_bundle() { '(--upgrade)--install[Run `install` before continuing to other operations e.g. `exec`]' \ '--mas[`list` or `dump` Mac App Store dependencies]' \ '--no-restart[`dump` does not add `restart_service` to formula lines]' \ - '--no-upgrade[`install` does not run `brew upgrade` on outdated dependencies. `check` does not check for outdated dependencies. Note they may still be upgraded by `brew install` if needed. This is enabled by default if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set]' \ - '(--all --vscode)--no-vscode[`dump` without VSCode (and forks/variants) extensions. This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_NO_VSCODE` is set]' \ + '--no-upgrade[`install` does not run `brew upgrade` on outdated dependencies. `check` does not check for outdated dependencies. Note they may still be upgraded by `brew install` if needed. Enabled by default if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set]' \ + '(--all --vscode)--no-vscode[`dump` without VSCode (and forks/variants) extensions. Enabled by default if `$HOMEBREW_BUNDLE_DUMP_NO_VSCODE` is set]' \ '--quiet[Make some output more quiet]' \ - '--services[Temporarily start services while running the `exec` or `sh` command. This is enabled by default if `$HOMEBREW_BUNDLE_SERVICES` is set]' \ + '--services[Temporarily start services while running the `exec` or `sh` command. Enabled by default if `$HOMEBREW_BUNDLE_SERVICES` is set]' \ '--tap[`list`, `dump` or `cleanup` Homebrew tap dependencies]' \ '(--install)--upgrade[`install` runs `brew upgrade` on outdated dependencies, even if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set]' \ '--upgrade-formulae[`install` runs `brew upgrade` on any of these comma-separated formulae, even if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set]' \ @@ -874,8 +875,8 @@ _brew_determine_test_runners() { _arguments \ '(--dependents)--all-supported[Instead of selecting runners based on the chosen formula, return all supported runners]' \ '--debug[Display any debugging information]' \ - '(--all-supported)--dependents[Determine runners for testing dependents. Requires `--eval-all` or `HOMEBREW_EVAL_ALL`]' \ - '--eval-all[Evaluate all available formulae, whether installed or not, to determine testing dependents]' \ + '(--all-supported)--dependents[Determine runners for testing dependents. Requires `--eval-all` or `$HOMEBREW_EVAL_ALL` to be set]' \ + '--eval-all[Evaluate all available formulae, whether installed or not, to determine testing dependents. Enabled by default if `$HOMEBREW_EVAL_ALL` is set]' \ '--help[Show this message]' \ '--quiet[Make some output more quiet]' \ '--verbose[Make some output more verbose]' @@ -1008,9 +1009,9 @@ _brew_fetch() { '--force[Remove a previously cached version and re-fetch]' \ '(--build-from-source --build-bottle --bottle-tag --cask)--force-bottle[Download a bottle if it exists for the current or newest version of macOS, even if it would not be used during installation]' \ '--help[Show this message]' \ - '--no-quarantine[Disable/enable quarantining of downloads (default: enabled)]' \ + '--no-quarantine[Disable/enable quarantining of downloads (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_QUARANTINE` is set]' \ '(--bottle-tag)--os[Download for the given operating system. (Pass `all` to download for all operating systems.)]' \ - '--quarantine[Disable/enable quarantining of downloads (default: enabled)]' \ + '--quarantine[Disable/enable quarantining of downloads (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_QUARANTINE` is set]' \ '--quiet[Make some output more quiet]' \ '--retry[Retry if downloading fails or re-download if the checksum of a previously cached version no longer matches. Tries at most 5 times with exponential backoff]' \ '--verbose[Do a verbose VCS checkout, if the URL represents a VCS. This is useful for seeing if an existing VCS cache has been updated]' \ @@ -1196,9 +1197,9 @@ _brew_instal() { '(--formula --force)--adopt[Adopt existing artifacts in the destination that are identical to those being installed. Cannot be combined with `--force`]' \ '(--formula)--appdir[Target location for Applications (default: `/Applications`)]' \ '(--cask)--as-dependency[Install but mark as installed as a dependency and not installed on request]' \ - '--ask[Ask for confirmation before downloading and installing formulae. Print bottles and dependencies download size and install size]' \ + '--ask[Ask for confirmation before downloading and installing formulae. Print download and install sizes of bottles and dependencies. Enabled by default if `$HOMEBREW_ASK` is set]' \ '(--formula)--audio-unit-plugindir[Target location for Audio Unit Plugins (default: `~/Library/Audio/Plug-Ins/Components`)]' \ - '(--formula)--binaries[Disable/enable linking of helper executables (default: enabled)]' \ + '(--formula)--binaries[Disable/enable linking of helper executables (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_BINARIES` is set]' \ '(--cask)--bottle-arch[Optimise bottles for the specified architecture rather than the oldest architecture supported by the version of macOS the bottles are built on]' \ '(--cask --build-from-source --force-bottle)--build-bottle[Prepare the formula for eventual bottling during installation, skipping any post-install steps]' \ '(--cask --build-bottle --force-bottle)--build-from-source[Compile formula from source even if a bottle is provided. Dependencies will still be installed from bottles if they are available]' \ @@ -1207,7 +1208,7 @@ _brew_instal() { '--debug[If brewing fails, open an interactive debugging session with access to IRB or a shell inside the temporary build directory]' \ '(--cask)--debug-symbols[Generate debug symbols on build. Source will be retained in a cache directory]' \ '(--formula)--dictionarydir[Target location for Dictionaries (default: `~/Library/Dictionaries`)]' \ - '--display-times[Print install times for each package at the end of the run]' \ + '--display-times[Print install times for each package at the end of the run. Enabled by default if `$HOMEBREW_DISPLAY_INSTALL_TIMES` is set]' \ '--dry-run[Show what would be installed, but do not actually install anything]' \ '(--cask)--fetch-HEAD[Fetch the upstream repository to detect if the HEAD installation of the formula is outdated. Otherwise, the repository'\''s HEAD will only be checked for updates when a new stable or development version has been released]' \ '(--formula)--fontdir[Target location for Fonts (default: `~/Library/Fonts`)]' \ @@ -1224,15 +1225,15 @@ _brew_instal() { '(--formula)--keyboard-layoutdir[Target location for Keyboard Layouts (default: `/Library/Keyboard Layouts`)]' \ '(--formula)--language[Comma-separated list of language codes to prefer for cask installation. The first matching language is used, otherwise it reverts to the cask'\''s default language. The default value is the language of your system]' \ '(--formula)--mdimporterdir[Target location for Spotlight Plugins (default: `~/Library/Spotlight`)]' \ - '--no-binaries[Disable/enable linking of helper executables (default: enabled)]' \ - '--no-quarantine[Disable/enable quarantining of downloads (default: enabled)]' \ + '--no-binaries[Disable/enable linking of helper executables (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_BINARIES` is set]' \ + '--no-quarantine[Disable/enable quarantining of downloads (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_QUARANTINE` is set]' \ '(--cask --ignore-dependencies)--only-dependencies[Install the dependencies with specified options but do not install the formula itself]' \ '(--cask)--overwrite[Delete files that already exist in the prefix while linking]' \ '(--formula)--prefpanedir[Target location for Preference Panes (default: `~/Library/PreferencePanes`)]' \ '(--formula)--qlplugindir[Target location for Quick Look Plugins (default: `~/Library/QuickLook`)]' \ - '(--formula)--quarantine[Disable/enable quarantining of downloads (default: enabled)]' \ + '(--formula)--quarantine[Disable/enable quarantining of downloads (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_QUARANTINE` is set]' \ '--quiet[Make some output more quiet]' \ - '(--formula)--require-sha[Require all casks to have a checksum]' \ + '(--formula)--require-sha[Require all casks to have a checksum. Enabled by default if `$HOMEBREW_CASK_OPTS_REQUIRE_SHA` is set]' \ '(--formula)--screen-saverdir[Target location for Screen Savers (default: `~/Library/Screen Savers`)]' \ '(--formula)--servicedir[Target location for Services (default: `~/Library/Services`)]' \ '(--formula)--skip-cask-deps[Skip installing cask dependencies]' \ @@ -1257,9 +1258,9 @@ _brew_install() { '(--formula --force)--adopt[Adopt existing artifacts in the destination that are identical to those being installed. Cannot be combined with `--force`]' \ '(--formula)--appdir[Target location for Applications (default: `/Applications`)]' \ '(--cask)--as-dependency[Install but mark as installed as a dependency and not installed on request]' \ - '--ask[Ask for confirmation before downloading and installing formulae. Print bottles and dependencies download size and install size]' \ + '--ask[Ask for confirmation before downloading and installing formulae. Print download and install sizes of bottles and dependencies. Enabled by default if `$HOMEBREW_ASK` is set]' \ '(--formula)--audio-unit-plugindir[Target location for Audio Unit Plugins (default: `~/Library/Audio/Plug-Ins/Components`)]' \ - '(--formula)--binaries[Disable/enable linking of helper executables (default: enabled)]' \ + '(--formula)--binaries[Disable/enable linking of helper executables (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_BINARIES` is set]' \ '(--cask)--bottle-arch[Optimise bottles for the specified architecture rather than the oldest architecture supported by the version of macOS the bottles are built on]' \ '(--cask --build-from-source --force-bottle)--build-bottle[Prepare the formula for eventual bottling during installation, skipping any post-install steps]' \ '(--cask --build-bottle --force-bottle)--build-from-source[Compile formula from source even if a bottle is provided. Dependencies will still be installed from bottles if they are available]' \ @@ -1268,7 +1269,7 @@ _brew_install() { '--debug[If brewing fails, open an interactive debugging session with access to IRB or a shell inside the temporary build directory]' \ '(--cask)--debug-symbols[Generate debug symbols on build. Source will be retained in a cache directory]' \ '(--formula)--dictionarydir[Target location for Dictionaries (default: `~/Library/Dictionaries`)]' \ - '--display-times[Print install times for each package at the end of the run]' \ + '--display-times[Print install times for each package at the end of the run. Enabled by default if `$HOMEBREW_DISPLAY_INSTALL_TIMES` is set]' \ '--dry-run[Show what would be installed, but do not actually install anything]' \ '(--cask)--fetch-HEAD[Fetch the upstream repository to detect if the HEAD installation of the formula is outdated. Otherwise, the repository'\''s HEAD will only be checked for updates when a new stable or development version has been released]' \ '(--formula)--fontdir[Target location for Fonts (default: `~/Library/Fonts`)]' \ @@ -1285,15 +1286,15 @@ _brew_install() { '(--formula)--keyboard-layoutdir[Target location for Keyboard Layouts (default: `/Library/Keyboard Layouts`)]' \ '(--formula)--language[Comma-separated list of language codes to prefer for cask installation. The first matching language is used, otherwise it reverts to the cask'\''s default language. The default value is the language of your system]' \ '(--formula)--mdimporterdir[Target location for Spotlight Plugins (default: `~/Library/Spotlight`)]' \ - '--no-binaries[Disable/enable linking of helper executables (default: enabled)]' \ - '--no-quarantine[Disable/enable quarantining of downloads (default: enabled)]' \ + '--no-binaries[Disable/enable linking of helper executables (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_BINARIES` is set]' \ + '--no-quarantine[Disable/enable quarantining of downloads (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_QUARANTINE` is set]' \ '(--cask --ignore-dependencies)--only-dependencies[Install the dependencies with specified options but do not install the formula itself]' \ '(--cask)--overwrite[Delete files that already exist in the prefix while linking]' \ '(--formula)--prefpanedir[Target location for Preference Panes (default: `~/Library/PreferencePanes`)]' \ '(--formula)--qlplugindir[Target location for Quick Look Plugins (default: `~/Library/QuickLook`)]' \ - '(--formula)--quarantine[Disable/enable quarantining of downloads (default: enabled)]' \ + '(--formula)--quarantine[Disable/enable quarantining of downloads (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_QUARANTINE` is set]' \ '--quiet[Make some output more quiet]' \ - '(--formula)--require-sha[Require all casks to have a checksum]' \ + '(--formula)--require-sha[Require all casks to have a checksum. Enabled by default if `$HOMEBREW_CASK_OPTS_REQUIRE_SHA` is set]' \ '(--formula)--screen-saverdir[Target location for Screen Savers (default: `~/Library/Screen Savers`)]' \ '(--formula)--servicedir[Target location for Services (default: `~/Library/Services`)]' \ '(--formula)--skip-cask-deps[Skip installing cask dependencies]' \ @@ -1328,7 +1329,7 @@ _brew_irb() { '--debug[Display any debugging information]' \ '--examples[Show several examples]' \ '--help[Show this message]' \ - '--pry[Use Pry instead of IRB. Implied if `HOMEBREW_PRY` is set]' \ + '--pry[Use Pry instead of IRB. Enabled by default if `$HOMEBREW_PRY` is set]' \ '--quiet[Make some output more quiet]' \ '--verbose[Make some output more verbose]' } @@ -1386,7 +1387,7 @@ _brew_link() { # brew linkage _brew_linkage() { _arguments \ - '--cached[Print the cached linkage values stored in `HOMEBREW_CACHE`, set by a previous `brew linkage` run]' \ + '--cached[Print the cached linkage values stored in `$HOMEBREW_CACHE`, set by a previous `brew linkage` run]' \ '--debug[Display any debugging information]' \ '--help[Show this message]' \ '--quiet[Make some output more quiet]' \ @@ -1511,6 +1512,15 @@ _brew_ls() { '*:installed_cask:__brew_installed_casks' } +# brew mcp-server +_brew_mcp_server() { + _arguments \ + '--debug[Enable debug logging to stderr]' \ + '--help[Show this message]' \ + '--quiet[Make some output more quiet]' \ + '--verbose[Make some output more verbose]' +} + # brew migrate _brew_migrate() { _arguments \ @@ -1569,7 +1579,7 @@ _brew_outdated() { _arguments \ '--debug[Display any debugging information]' \ '--fetch-HEAD[Fetch the upstream repository to detect if the HEAD installation of the formula is outdated. Otherwise, the repository'\''s HEAD will only be checked for updates when a new stable or development version has been released]' \ - '--greedy[Also include outdated casks with `auto_updates true` or `version :latest`]' \ + '--greedy[Also include outdated casks with `auto_updates true` or `version :latest`. Enabled by default if `$HOMEBREW_UPGRADE_GREEDY` is set]' \ '--greedy-auto-updates[Also include outdated casks including those with `auto_updates true`]' \ '--greedy-latest[Also include outdated casks including those with `version :latest`]' \ '--help[Show this message]' \ @@ -1747,15 +1757,15 @@ _brew_reinstall() { _arguments \ '(--formula)--adopt[Adopt existing artifacts in the destination that are identical to those being installed. Cannot be combined with `--force`]' \ '(--formula)--appdir[Target location for Applications (default: `/Applications`)]' \ - '--ask[Ask for confirmation before downloading and upgrading formulae. Print bottles and dependencies download size, install and net install size]' \ + '--ask[Ask for confirmation before downloading and upgrading formulae. Print download, install and net install sizes of bottles and dependencies. Enabled by default if `$HOMEBREW_ASK` is set]' \ '(--formula)--audio-unit-plugindir[Target location for Audio Unit Plugins (default: `~/Library/Audio/Plug-Ins/Components`)]' \ - '(--formula)--binaries[Disable/enable linking of helper executables (default: enabled)]' \ + '(--formula)--binaries[Disable/enable linking of helper executables (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_BINARIES` is set]' \ '(--cask --force-bottle)--build-from-source[Compile formula from source even if a bottle is available]' \ '(--formula)--colorpickerdir[Target location for Color Pickers (default: `~/Library/ColorPickers`)]' \ '--debug[If brewing fails, open an interactive debugging session with access to IRB or a shell inside the temporary build directory]' \ '(--cask)--debug-symbols[Generate debug symbols on build. Source will be retained in a cache directory]' \ '(--formula)--dictionarydir[Target location for Dictionaries (default: `~/Library/Dictionaries`)]' \ - '--display-times[Print install times for each package at the end of the run]' \ + '--display-times[Print install times for each package at the end of the run. Enabled by default if `$HOMEBREW_DISPLAY_INSTALL_TIMES` is set]' \ '(--formula)--fontdir[Target location for Fonts (default: `~/Library/Fonts`)]' \ '--force[Install without checking for previously installed keg-only or non-migrated versions]' \ '(--cask --build-from-source)--force-bottle[Install from a bottle if it exists for the current or newest version of macOS, even if it would not normally be used for installation]' \ @@ -1768,13 +1778,13 @@ _brew_reinstall() { '(--formula)--keyboard-layoutdir[Target location for Keyboard Layouts (default: `/Library/Keyboard Layouts`)]' \ '(--formula)--language[Comma-separated list of language codes to prefer for cask installation. The first matching language is used, otherwise it reverts to the cask'\''s default language. The default value is the language of your system]' \ '(--formula)--mdimporterdir[Target location for Spotlight Plugins (default: `~/Library/Spotlight`)]' \ - '--no-binaries[Disable/enable linking of helper executables (default: enabled)]' \ - '--no-quarantine[Disable/enable quarantining of downloads (default: enabled)]' \ + '--no-binaries[Disable/enable linking of helper executables (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_BINARIES` is set]' \ + '--no-quarantine[Disable/enable quarantining of downloads (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_QUARANTINE` is set]' \ '(--formula)--prefpanedir[Target location for Preference Panes (default: `~/Library/PreferencePanes`)]' \ '(--formula)--qlplugindir[Target location for Quick Look Plugins (default: `~/Library/QuickLook`)]' \ - '(--formula)--quarantine[Disable/enable quarantining of downloads (default: enabled)]' \ + '(--formula)--quarantine[Disable/enable quarantining of downloads (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_QUARANTINE` is set]' \ '--quiet[Make some output more quiet]' \ - '(--formula)--require-sha[Require all casks to have a checksum]' \ + '(--formula)--require-sha[Require all casks to have a checksum. Enabled by default if `$HOMEBREW_CASK_OPTS_REQUIRE_SHA` is set]' \ '(--formula)--screen-saverdir[Target location for Screen Savers (default: `~/Library/Screen Savers`)]' \ '(--formula)--servicedir[Target location for Services (default: `~/Library/Services`)]' \ '(--formula)--skip-cask-deps[Skip installing cask dependencies]' \ @@ -1928,7 +1938,7 @@ _brew_sh() { _arguments \ '--cmd[Execute commands in a non-interactive shell]' \ '--debug[Display any debugging information]' \ - '--env[Use the standard `PATH` instead of superenv'\''s when `std` is passed]' \ + '--env[Use the standard `$PATH` instead of superenv'\''s when `std` is passed]' \ '--help[Show this message]' \ '--quiet[Make some output more quiet]' \ '--verbose[Make some output more verbose]' \ @@ -2071,6 +2081,7 @@ _brew_tests() { '--fail-fast[Exit early on the first failing test]' \ '--generic[Run only OS-agnostic tests]' \ '--help[Show this message]' \ + '--no-parallel[Run tests serially]' \ '--online[Include tests that use the GitHub API and tests that use any of the taps for official external commands]' \ '(--changed)--only[Run only `test_script_spec.rb`. Appending `:line_number` will start at a specific line]' \ '--profile[Run the test suite serially to find the n slowest tests]' \ @@ -2112,7 +2123,7 @@ _brew_unbottled() { _arguments \ '--debug[Display any debugging information]' \ '(--total --lost)--dependents[Skip getting analytics data and sort by number of dependents instead]' \ - '--eval-all[Evaluate all available formulae and casks, whether installed or not, to check them. Implied if `HOMEBREW_EVAL_ALL` is set]' \ + '--eval-all[Evaluate all available formulae and casks, whether installed or not, to check them. Implied if `$HOMEBREW_EVAL_ALL` is set]' \ '--help[Show this message]' \ '(--dependents --total)--lost[Print the `homebrew/core` commits where bottles were lost in the last week]' \ '--quiet[Make some output more quiet]' \ @@ -2318,7 +2329,7 @@ _brew_update_test() { '--help[Show this message]' \ '--keep-tmp[Retain the temporary directory containing the new repository clone]' \ '--quiet[Make some output more quiet]' \ - '--to-tag[Set `HOMEBREW_UPDATE_TO_TAG` to test updating between tags]' \ + '--to-tag[Set `$HOMEBREW_UPDATE_TO_TAG` to test updating between tags]' \ '--verbose[Make some output more verbose]' } @@ -2326,15 +2337,15 @@ _brew_update_test() { _brew_upgrade() { _arguments \ '(--formula)--appdir[Target location for Applications (default: `/Applications`)]' \ - '--ask[Ask for confirmation before downloading and upgrading formulae. Print bottles and dependencies download size, install and net install size]' \ + '--ask[Ask for confirmation before downloading and upgrading formulae. Print download, install and net install sizes of bottles and dependencies. Enabled by default if `$HOMEBREW_ASK` is set]' \ '(--formula)--audio-unit-plugindir[Target location for Audio Unit Plugins (default: `~/Library/Audio/Plug-Ins/Components`)]' \ - '(--formula)--binaries[Disable/enable linking of helper executables (default: enabled)]' \ + '(--formula)--binaries[Disable/enable linking of helper executables (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_BINARIES` is set]' \ '(--cask --force-bottle)--build-from-source[Compile formula from source even if a bottle is available]' \ '(--formula)--colorpickerdir[Target location for Color Pickers (default: `~/Library/ColorPickers`)]' \ '--debug[If brewing fails, open an interactive debugging session with access to IRB or a shell inside the temporary build directory]' \ '(--cask)--debug-symbols[Generate debug symbols on build. Source will be retained in a cache directory]' \ '(--formula)--dictionarydir[Target location for Dictionaries (default: `~/Library/Dictionaries`)]' \ - '--display-times[Print install times for each package at the end of the run]' \ + '--display-times[Print install times for each package at the end of the run. Enabled by default if `$HOMEBREW_DISPLAY_INSTALL_TIMES` is set]' \ '--dry-run[Show what would be upgraded, but do not actually upgrade anything]' \ '(--cask)--fetch-HEAD[Fetch the upstream repository to detect if the HEAD installation of the formula is outdated. Otherwise, the repository'\''s HEAD will only be checked for updates when a new stable or development version has been released]' \ '(--formula)--fontdir[Target location for Fonts (default: `~/Library/Fonts`)]' \ @@ -2351,14 +2362,14 @@ _brew_upgrade() { '(--formula)--keyboard-layoutdir[Target location for Keyboard Layouts (default: `/Library/Keyboard Layouts`)]' \ '(--formula)--language[Comma-separated list of language codes to prefer for cask installation. The first matching language is used, otherwise it reverts to the cask'\''s default language. The default value is the language of your system]' \ '(--formula)--mdimporterdir[Target location for Spotlight Plugins (default: `~/Library/Spotlight`)]' \ - '--no-binaries[Disable/enable linking of helper executables (default: enabled)]' \ - '--no-quarantine[Disable/enable quarantining of downloads (default: enabled)]' \ + '--no-binaries[Disable/enable linking of helper executables (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_BINARIES` is set]' \ + '--no-quarantine[Disable/enable quarantining of downloads (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_QUARANTINE` is set]' \ '(--cask)--overwrite[Delete files that already exist in the prefix while linking]' \ '(--formula)--prefpanedir[Target location for Preference Panes (default: `~/Library/PreferencePanes`)]' \ '(--formula)--qlplugindir[Target location for Quick Look Plugins (default: `~/Library/QuickLook`)]' \ - '(--formula)--quarantine[Disable/enable quarantining of downloads (default: enabled)]' \ + '(--formula)--quarantine[Disable/enable quarantining of downloads (default: enabled). Enabled by default if `$HOMEBREW_CASK_OPTS_QUARANTINE` is set]' \ '--quiet[Make some output more quiet]' \ - '(--formula)--require-sha[Require all casks to have a checksum]' \ + '(--formula)--require-sha[Require all casks to have a checksum. Enabled by default if `$HOMEBREW_CASK_OPTS_REQUIRE_SHA` is set]' \ '(--formula)--screen-saverdir[Target location for Screen Savers (default: `~/Library/Screen Savers`)]' \ '(--formula)--servicedir[Target location for Services (default: `~/Library/Services`)]' \ '(--formula)--skip-cask-deps[Skip installing cask dependencies]' \ diff --git a/docs/Manpage.md b/docs/Manpage.md index 861f6d0e92..082d03949d 100644 --- a/docs/Manpage.md +++ b/docs/Manpage.md @@ -239,8 +239,8 @@ flags which will help with finding keg-only dependencies like `openssl`, : `install` does not run `brew upgrade` on outdated dependencies. `check` does not check for outdated dependencies. Note they may still be upgraded by `brew - install` if needed. This is enabled by default if - `$HOMEBREW_BUNDLE_NO_UPGRADE` is set. + install` if needed. Enabled by default if `$HOMEBREW_BUNDLE_NO_UPGRADE` is + set. `--upgrade` @@ -258,8 +258,8 @@ flags which will help with finding keg-only dependencies like `openssl`, `--services` -: Temporarily start services while running the `exec` or `sh` command. This is - enabled by default if `$HOMEBREW_BUNDLE_SERVICES` is set. +: Temporarily start services while running the `exec` or `sh` command. Enabled + by default if `$HOMEBREW_BUNDLE_SERVICES` is set. `-f`, `--force` @@ -268,9 +268,9 @@ flags which will help with finding keg-only dependencies like `openssl`, `--cleanup` -: `install` performs cleanup operation, same as running `cleanup --force`. This - is enabled by default if `$HOMEBREW_BUNDLE_INSTALL_CLEANUP` is set and - `--global` is passed. +: `install` performs cleanup operation, same as running `cleanup --force`. + Enabled by default if `$HOMEBREW_BUNDLE_INSTALL_CLEANUP` is set and `--global` + is passed. `--all` @@ -302,14 +302,14 @@ flags which will help with finding keg-only dependencies like `openssl`, `--no-vscode` -: `dump` without VSCode (and forks/variants) extensions. This is enabled by - default if `$HOMEBREW_BUNDLE_DUMP_NO_VSCODE` is set. +: `dump` without VSCode (and forks/variants) extensions. Enabled by default if + `$HOMEBREW_BUNDLE_DUMP_NO_VSCODE` is set. `--describe` : `dump` adds a description comment above each line, unless the dependency does - not have a description. This is enabled by default if - `$HOMEBREW_BUNDLE_DUMP_DESCRIBE` is set. + not have a description. Enabled by default if `$HOMEBREW_BUNDLE_DUMP_DESCRIBE` + is set. `--no-restart` @@ -397,8 +397,7 @@ required and recommended dependencies. If any version of each formula argument is installed and no other options are passed, this command displays their actual runtime dependencies (similar to -`brew linkage`), which may differ from the current versions' stated dependencies -if the installed versions are outdated. +`brew linkage`), which may differ from a formula's declared dependencies. *Note:* `--missing` and `--skip-recommended` have precedence over `--include-*`. @@ -627,7 +626,8 @@ binaries for *`cask`*s. For files, also print SHA-256 checksums. `--[no-]quarantine` -: Disable/enable quarantining of downloads (default: enabled). +: Disable/enable quarantining of downloads (default: enabled). Enabled by + default if `$HOMEBREW_CASK_OPTS_QUARANTINE` is set. `--formula` @@ -763,7 +763,8 @@ upgrade *`formula`* if it is already installed but outdated. `--display-times` -: Print install times for each package at the end of the run. +: Print install times for each package at the end of the run. Enabled by default + if `$HOMEBREW_DISPLAY_INSTALL_TIMES` is set. `-f`, `--force` @@ -781,8 +782,9 @@ upgrade *`formula`* if it is already installed but outdated. `--ask` -: Ask for confirmation before downloading and installing formulae. Print bottles - and dependencies download size and install size. +: Ask for confirmation before downloading and installing formulae. Print + download and install sizes of bottles and dependencies. Enabled by default if + `$HOMEBREW_ASK` is set. `--formula` @@ -884,15 +886,18 @@ upgrade *`formula`* if it is already installed but outdated. `--[no-]binaries` -: Disable/enable linking of helper executables (default: enabled). +: Disable/enable linking of helper executables (default: enabled). Enabled by + default if `$HOMEBREW_CASK_OPTS_BINARIES` is set. `--require-sha` -: Require all casks to have a checksum. +: Require all casks to have a checksum. Enabled by default if + `$HOMEBREW_CASK_OPTS_REQUIRE_SHA` is set. `--[no-]quarantine` -: Disable/enable quarantining of downloads (default: enabled). +: Disable/enable quarantining of downloads (default: enabled). Enabled by + default if `$HOMEBREW_CASK_OPTS_QUARANTINE` is set. `--adopt` @@ -1046,6 +1051,14 @@ repository if no formula or cask is provided. : Treat all named arguments as casks. +### `mcp-server` \[`--debug`\] + +Starts the Homebrew MCP (Model Context Protocol) server. + +`-d`, `--debug` + +: Enable debug logging to stderr. + ### `migrate` \[*`options`*\] *`installed_formula`*\|*`installed_cask`* \[...\] Migrate renamed packages to new names, where *`formula`* are old names of @@ -1145,6 +1158,7 @@ otherwise. `-g`, `--greedy` : Also include outdated casks with `auto_updates true` or `version :latest`. + Enabled by default if `$HOMEBREW_UPGRADE_GREEDY` is set. `--greedy-latest` @@ -1234,7 +1248,8 @@ for the reinstalled formulae or, every 30 days, for all formulae. `--display-times` -: Print install times for each package at the end of the run. +: Print install times for each package at the end of the run. Enabled by default + if `$HOMEBREW_DISPLAY_INSTALL_TIMES` is set. `-f`, `--force` @@ -1247,8 +1262,9 @@ for the reinstalled formulae or, every 30 days, for all formulae. `--ask` -: Ask for confirmation before downloading and upgrading formulae. Print bottles - and dependencies download size, install and net install size. +: Ask for confirmation before downloading and upgrading formulae. Print + download, install and net install sizes of bottles and dependencies. Enabled + by default if `$HOMEBREW_ASK` is set. `--formula` @@ -1287,15 +1303,18 @@ for the reinstalled formulae or, every 30 days, for all formulae. `--[no-]binaries` -: Disable/enable linking of helper executables (default: enabled). +: Disable/enable linking of helper executables (default: enabled). Enabled by + default if `$HOMEBREW_CASK_OPTS_BINARIES` is set. `--require-sha` -: Require all casks to have a checksum. +: Require all casks to have a checksum. Enabled by default if + `$HOMEBREW_CASK_OPTS_REQUIRE_SHA` is set. `--[no-]quarantine` -: Disable/enable quarantining of downloads (default: enabled). +: Disable/enable quarantining of downloads (default: enabled). Enabled by + default if `$HOMEBREW_CASK_OPTS_QUARANTINE` is set. `--adopt` @@ -1464,12 +1483,12 @@ run Bundler if necessary for that command. Valid shells: bash\|csh\|fish\|pwsh\|sh\|tcsh\|zsh Print export statements. When run in a shell, this installation of Homebrew will -be added to your `PATH`, `MANPATH`, and `INFOPATH`. +be added to your `$PATH`, `$MANPATH`, and `$INFOPATH`. The variables `$HOMEBREW_PREFIX`, `$HOMEBREW_CELLAR` and `$HOMEBREW_REPOSITORY` are also exported to avoid querying them multiple times. To help guarantee idempotence, this command produces no output when Homebrew's `bin` and `sbin` -directories are first and second respectively in your `PATH`. Consider adding +directories are first and second respectively in your `$PATH`. Consider adding evaluation of this command's output to your dotfiles (e.g. `~/.bash_profile` or ~/.zprofile` on macOS and ~/.bashrc` or ~/.zshrc` on Linux) with: `eval "$(brew shellenv)"\` @@ -1663,7 +1682,8 @@ for the upgraded formulae or, every 30 days, for all formulae. `--display-times` -: Print install times for each package at the end of the run. +: Print install times for each package at the end of the run. Enabled by default + if `$HOMEBREW_DISPLAY_INSTALL_TIMES` is set. `-f`, `--force` @@ -1681,8 +1701,9 @@ for the upgraded formulae or, every 30 days, for all formulae. `--ask` -: Ask for confirmation before downloading and upgrading formulae. Print bottles - and dependencies download size, install and net install size. +: Ask for confirmation before downloading and upgrading formulae. Print + download, install and net install sizes of bottles and dependencies. Enabled + by default if `$HOMEBREW_ASK` is set. `--formula` @@ -1745,15 +1766,18 @@ for the upgraded formulae or, every 30 days, for all formulae. `--[no-]binaries` -: Disable/enable linking of helper executables (default: enabled). +: Disable/enable linking of helper executables (default: enabled). Enabled by + default if `$HOMEBREW_CASK_OPTS_BINARIES` is set. `--require-sha` -: Require all casks to have a checksum. +: Require all casks to have a checksum. Enabled by default if + `$HOMEBREW_CASK_OPTS_REQUIRE_SHA` is set. `--[no-]quarantine` -: Disable/enable quarantining of downloads (default: enabled). +: Disable/enable quarantining of downloads (default: enabled). Enabled by + default if `$HOMEBREW_CASK_OPTS_QUARANTINE` is set. ### `uses` \[*`options`*\] *`formula`* \[...\] @@ -1951,7 +1975,7 @@ checks. Will exit with a non-zero status if any errors are found. `--eval-all` : Evaluate all available formulae and casks, whether installed or not, to audit - them. Implied if `HOMEBREW_EVAL_ALL` is set. + them. Implied if `$HOMEBREW_EVAL_ALL` is set. `--new` @@ -2551,9 +2575,9 @@ Build bottles for these formulae with GitHub Actions. ### `edit` \[*`options`*\] \[*`formula`*\|*`cask`*\|*`tap`* ...\] -Open a *`formula`*, *`cask`* or *`tap`* in the editor set by `EDITOR` or -`HOMEBREW_EDITOR`, or open the Homebrew repository for editing if no argument is -provided. +Open a *`formula`*, *`cask`* or *`tap`* in the editor set by `$EDITOR` or +`$HOMEBREW_EDITOR`, or open the Homebrew repository for editing if no argument +is provided. `--formula` @@ -2715,7 +2739,7 @@ Enter the interactive Homebrew Ruby shell. `--pry` -: Use Pry instead of IRB. Implied if `HOMEBREW_PRY` is set. +: Use Pry instead of IRB. Enabled by default if `$HOMEBREW_PRY` is set. ### `linkage` \[*`options`*\] \[*`installed_formula`* ...\] @@ -2739,14 +2763,14 @@ provided, check all kegs. Raises an error if run on uninstalled formulae. `--cached` -: Print the cached linkage values stored in `HOMEBREW_CACHE`, set by a previous +: Print the cached linkage values stored in `$HOMEBREW_CACHE`, set by a previous `brew linkage` run. ### `livecheck`, `lc` \[*`options`*\] \[*`formula`*\|*`cask`* ...\] 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`. +from `$HOMEBREW_LIVECHECK_WATCHLIST` or `~/.homebrew/livecheck_watchlist.txt`. `--full-name` @@ -3068,11 +3092,11 @@ Enter an interactive shell for Homebrew's build environment. Use years-battle-hardened build logic to help your `./configure && make && make install` and even your `gem install` succeed. Especially handy if you run Homebrew in an Xcode-only configuration since it adds tools like `make` to your -`PATH` which build systems would not find otherwise. +`$PATH` which build systems would not find otherwise. `--env` -: Use the standard `PATH` instead of superenv's when `std` is passed. +: Use the standard `$PATH` instead of superenv's when `std` is passed. `-c`, `--cmd` @@ -3186,6 +3210,10 @@ Run Homebrew's unit and integration tests. : Exit early on the first failing test. +`--no-parallel` + +: Run tests serially. + `--only` : Run only `_spec.rb`. Appending `:` will start at a @@ -3263,7 +3291,7 @@ Show the unbottled dependents of formulae. `--eval-all` : Evaluate all available formulae and casks, whether installed or not, to check - them. Implied if `HOMEBREW_EVAL_ALL` is set. + them. Implied if `$HOMEBREW_EVAL_ALL` is set. ### `unpack` \[*`options`*\] *`formula`* \[...\] @@ -3350,7 +3378,7 @@ passed, use `origin/master` as the start commit. `--to-tag` -: Set `HOMEBREW_UPDATE_TO_TAG` to test updating between tags. +: Set `$HOMEBREW_UPDATE_TO_TAG` to test updating between tags. `--keep-tmp` @@ -3738,7 +3766,7 @@ Database update for `brew which-formula`. ## CUSTOM EXTERNAL COMMANDS Homebrew, like `git`(1), supports external commands. These are executable -scripts that reside somewhere in the `PATH`, named `brew-`*`cmdname`* or +scripts that reside somewhere in the `$PATH`, named `brew-`*`cmdname`* or `brew-`*`cmdname`*`.rb`, which can be invoked like `brew` *`cmdname`*. This allows you to create your own commands without modifying Homebrew's internals. @@ -3785,7 +3813,7 @@ files: User-specific environment files take precedence over prefix-specific files and prefix-specific files take precedence over system-wide files (unless -`HOMEBREW_SYSTEM_ENV_TAKES_PRIORITY` is set, see below). +`$HOMEBREW_SYSTEM_ENV_TAKES_PRIORITY` is set, see below). Note that these files do not support shell variable expansion e.g. `$HOME` or command execution e.g. `$(cat file)`. @@ -4333,7 +4361,7 @@ command execution e.g. `$(cat file)`. `HOMEBREW_SUDO_THROUGH_SUDO_USER` -: If set, Homebrew will use the `SUDO_USER` environment variable to define the +: If set, Homebrew will use the `$SUDO_USER` environment variable to define the user to `sudo`(8) through when running `sudo`(8). `HOMEBREW_SVN` diff --git a/docs/Typechecking.md b/docs/Typechecking.md index 216b79f396..ea291945a8 100644 --- a/docs/Typechecking.md +++ b/docs/Typechecking.md @@ -34,7 +34,7 @@ For more information on how to express more complex types, refer to the official ### Ruby interface files (`.rbi`) -[RBI files](https://sorbet.org/docs/rbi) help Sorbet learn about constants, ancestors and methods defined in ways it doesn't understand natively. We can also create an RBI file to help Sorbet understand dynamic definitions. Some of these files are automatically generated (see the next section) and some are manually written, e.g. [`extend/on_system.rbi`](https://github.com/Homebrew/brew/blob/975fe8a83fd57a8d8e790ec6fb10c2f13f705d02/Library/Homebrew/extend/on_system.rbi). +[RBI files](https://sorbet.org/docs/rbi) help Sorbet learn about constants, ancestors and methods defined in ways it doesn't understand natively. We can also create an RBI file to help Sorbet understand dynamic definitions. Some of these files are automatically generated (see the next section) and some are manually written, e.g. [`on_system.rbi`](https://github.com/Homebrew/brew/blob/HEAD/Library/Homebrew/on_system.rbi). There are also a very small number of files that Homebrew loads before `sorbet-runtime`, such as `utils/gems.rb`. Those files cannot have type signatures alongside the code itself, so RBI files are used there instead to retain static type checking. diff --git a/manpages/brew.1 b/manpages/brew.1 index 1d84a042df..a0bcbde4e4 100644 --- a/manpages/brew.1 +++ b/manpages/brew.1 @@ -1,5 +1,5 @@ .\" generated by kramdown -.TH "BREW" "1" "May 2025" "Homebrew" +.TH "BREW" "1" "June 2025" "Homebrew" .SH NAME brew \- The Missing Package Manager for macOS (or Linux) .SH "SYNOPSIS" @@ -145,7 +145,7 @@ Read from or write to the \fBBrewfile\fP from \fB$HOMEBREW_BUNDLE_FILE_GLOBAL\fP \fBinstall\fP prints output from commands as they are run\. \fBcheck\fP lists all missing dependencies\. .TP \fB\-\-no\-upgrade\fP -\fBinstall\fP does not run \fBbrew upgrade\fP on outdated dependencies\. \fBcheck\fP does not check for outdated dependencies\. Note they may still be upgraded by \fBbrew install\fP if needed\. This is enabled by default if \fB$HOMEBREW_BUNDLE_NO_UPGRADE\fP is set\. +\fBinstall\fP does not run \fBbrew upgrade\fP on outdated dependencies\. \fBcheck\fP does not check for outdated dependencies\. Note they may still be upgraded by \fBbrew install\fP if needed\. Enabled by default if \fB$HOMEBREW_BUNDLE_NO_UPGRADE\fP is set\. .TP \fB\-\-upgrade\fP \fBinstall\fP runs \fBbrew upgrade\fP on outdated dependencies, even if \fB$HOMEBREW_BUNDLE_NO_UPGRADE\fP is set\. @@ -157,13 +157,13 @@ Read from or write to the \fBBrewfile\fP from \fB$HOMEBREW_BUNDLE_FILE_GLOBAL\fP Run \fBinstall\fP before continuing to other operations e\.g\. \fBexec\fP\&\. .TP \fB\-\-services\fP -Temporarily start services while running the \fBexec\fP or \fBsh\fP command\. This is enabled by default if \fB$HOMEBREW_BUNDLE_SERVICES\fP is set\. +Temporarily start services while running the \fBexec\fP or \fBsh\fP command\. Enabled by default if \fB$HOMEBREW_BUNDLE_SERVICES\fP is set\. .TP \fB\-f\fP, \fB\-\-force\fP \fBinstall\fP runs with \fB\-\-force\fP/\fB\-\-overwrite\fP\&\. \fBdump\fP overwrites an existing \fBBrewfile\fP\&\. \fBcleanup\fP actually performs its cleanup operations\. .TP \fB\-\-cleanup\fP -\fBinstall\fP performs cleanup operation, same as running \fBcleanup \-\-force\fP\&\. This is enabled by default if \fB$HOMEBREW_BUNDLE_INSTALL_CLEANUP\fP is set and \fB\-\-global\fP is passed\. +\fBinstall\fP performs cleanup operation, same as running \fBcleanup \-\-force\fP\&\. Enabled by default if \fB$HOMEBREW_BUNDLE_INSTALL_CLEANUP\fP is set and \fB\-\-global\fP is passed\. .TP \fB\-\-all\fP \fBlist\fP all dependencies\. @@ -187,10 +187,10 @@ Temporarily start services while running the \fBexec\fP or \fBsh\fP command\. Th \fBlist\fP, \fBdump\fP or \fBcleanup\fP VSCode (and forks/variants) extensions\. .TP \fB\-\-no\-vscode\fP -\fBdump\fP without VSCode (and forks/variants) extensions\. This is enabled by default if \fB$HOMEBREW_BUNDLE_DUMP_NO_VSCODE\fP is set\. +\fBdump\fP without VSCode (and forks/variants) extensions\. Enabled by default if \fB$HOMEBREW_BUNDLE_DUMP_NO_VSCODE\fP is set\. .TP \fB\-\-describe\fP -\fBdump\fP adds a description comment above each line, unless the dependency does not have a description\. This is enabled by default if \fB$HOMEBREW_BUNDLE_DUMP_DESCRIBE\fP is set\. +\fBdump\fP adds a description comment above each line, unless the dependency does not have a description\. Enabled by default if \fB$HOMEBREW_BUNDLE_DUMP_DESCRIBE\fP is set\. .TP \fB\-\-no\-restart\fP \fBdump\fP does not add \fBrestart_service\fP to formula lines\. @@ -241,7 +241,7 @@ Show Homebrew and system configuration info useful for debugging\. If you file a .SS "\fBdeps\fP \fR[\fIoptions\fP] \fR[\fIformula\fP|\fIcask\fP \.\.\.]" Show dependencies for \fIformula\fP\&\. When given multiple formula arguments, show the intersection of dependencies for each formula\. By default, \fBdeps\fP shows all required and recommended dependencies\. .P -If any version of each formula argument is installed and no other options are passed, this command displays their actual runtime dependencies (similar to \fBbrew linkage\fP), which may differ from the current versions\[u2019] stated dependencies if the installed versions are outdated\. +If any version of each formula argument is installed and no other options are passed, this command displays their actual runtime dependencies (similar to \fBbrew linkage\fP), which may differ from a formula\[u2019]s declared dependencies\. .P \fINote:\fP \fB\-\-missing\fP and \fB\-\-skip\-recommended\fP have precedence over \fB\-\-include\-*\fP\&\. .TP @@ -393,7 +393,7 @@ Download source packages (for eventual bottling) rather than a bottle\. Download a bottle if it exists for the current or newest version of macOS, even if it would not be used during installation\. .TP \fB\-\-[no\-]quarantine\fP -Disable/enable quarantining of downloads (default: enabled)\. +Disable/enable quarantining of downloads (default: enabled)\. Enabled by default if \fB$HOMEBREW_CASK_OPTS_QUARANTINE\fP is set\. .TP \fB\-\-formula\fP Treat all named arguments as formulae\. @@ -476,7 +476,7 @@ Unless \fB$HOMEBREW_NO_INSTALL_UPGRADE\fP is set, \fBbrew install\fP \fIformula\ If brewing fails, open an interactive debugging session with access to IRB or a shell inside the temporary build directory\. .TP \fB\-\-display\-times\fP -Print install times for each package at the end of the run\. +Print install times for each package at the end of the run\. Enabled by default if \fB$HOMEBREW_DISPLAY_INSTALL_TIMES\fP is set\. .TP \fB\-f\fP, \fB\-\-force\fP Install formulae without checking for previously installed keg\-only or non\-migrated versions\. When installing casks, overwrite existing files (binaries and symlinks are excluded, unless originally from the same cask)\. @@ -488,7 +488,7 @@ Print the verification and post\-install steps\. Show what would be installed, but do not actually install anything\. .TP \fB\-\-ask\fP -Ask for confirmation before downloading and installing formulae\. Print bottles and dependencies download size and install size\. +Ask for confirmation before downloading and installing formulae\. Print download and install sizes of bottles and dependencies\. Enabled by default if \fB$HOMEBREW_ASK\fP is set\. .TP \fB\-\-formula\fP Treat all named arguments as formulae\. @@ -551,13 +551,13 @@ Delete files that already exist in the prefix while linking\. Treat all named arguments as casks\. .TP \fB\-\-[no\-]binaries\fP -Disable/enable linking of helper executables (default: enabled)\. +Disable/enable linking of helper executables (default: enabled)\. Enabled by default if \fB$HOMEBREW_CASK_OPTS_BINARIES\fP is set\. .TP \fB\-\-require\-sha\fP -Require all casks to have a checksum\. +Require all casks to have a checksum\. Enabled by default if \fB$HOMEBREW_CASK_OPTS_REQUIRE_SHA\fP is set\. .TP \fB\-\-[no\-]quarantine\fP -Disable/enable quarantining of downloads (default: enabled)\. +Disable/enable quarantining of downloads (default: enabled)\. Enabled by default if \fB$HOMEBREW_CASK_OPTS_QUARANTINE\fP is set\. .TP \fB\-\-adopt\fP Adopt existing artifacts in the destination that are identical to those being installed\. Cannot be combined with \fB\-\-force\fP\&\. @@ -656,6 +656,11 @@ Treat all named arguments as formulae\. .TP \fB\-\-cask\fP Treat all named arguments as casks\. +.SS "\fBmcp\-server\fP \fR[\fB\-\-debug\fP]" +Starts the Homebrew MCP (Model Context Protocol) server\. +.TP +\fB\-d\fP, \fB\-\-debug\fP +Enable debug logging to stderr\. .SS "\fBmigrate\fP \fR[\fIoptions\fP] \fIinstalled_formula\fP|\fIinstalled_cask\fP \fR[\.\.\.]" Migrate renamed packages to new names, where \fIformula\fP are old names of packages\. .TP @@ -715,7 +720,7 @@ Print output in JSON format\. There are two versions: \fBv1\fP and \fBv2\fP\&\. Fetch the upstream repository to detect if the HEAD installation of the formula is outdated\. Otherwise, the repository\[u2019]s HEAD will only be checked for updates when a new stable or development version has been released\. .TP \fB\-g\fP, \fB\-\-greedy\fP -Also include outdated casks with \fBauto_updates true\fP or \fBversion :latest\fP\&\. +Also include outdated casks with \fBauto_updates true\fP or \fBversion :latest\fP\&\. Enabled by default if \fB$HOMEBREW_UPGRADE_GREEDY\fP is set\. .TP \fB\-\-greedy\-latest\fP Also include outdated casks including those with \fBversion :latest\fP\&\. @@ -767,7 +772,7 @@ Unless \fB$HOMEBREW_NO_INSTALL_CLEANUP\fP is set, \fBbrew cleanup\fP will then b If brewing fails, open an interactive debugging session with access to IRB or a shell inside the temporary build directory\. .TP \fB\-\-display\-times\fP -Print install times for each package at the end of the run\. +Print install times for each package at the end of the run\. Enabled by default if \fB$HOMEBREW_DISPLAY_INSTALL_TIMES\fP is set\. .TP \fB\-f\fP, \fB\-\-force\fP Install without checking for previously installed keg\-only or non\-migrated versions\. @@ -776,7 +781,7 @@ Install without checking for previously installed keg\-only or non\-migrated ver Print the verification and post\-install steps\. .TP \fB\-\-ask\fP -Ask for confirmation before downloading and upgrading formulae\. Print bottles and dependencies download size, install and net install size\. +Ask for confirmation before downloading and upgrading formulae\. Print download, install and net install sizes of bottles and dependencies\. Enabled by default if \fB$HOMEBREW_ASK\fP is set\. .TP \fB\-\-formula\fP Treat all named arguments as formulae\. @@ -803,13 +808,13 @@ Create a Git repository, useful for creating patches to the software\. Treat all named arguments as casks\. .TP \fB\-\-[no\-]binaries\fP -Disable/enable linking of helper executables (default: enabled)\. +Disable/enable linking of helper executables (default: enabled)\. Enabled by default if \fB$HOMEBREW_CASK_OPTS_BINARIES\fP is set\. .TP \fB\-\-require\-sha\fP -Require all casks to have a checksum\. +Require all casks to have a checksum\. Enabled by default if \fB$HOMEBREW_CASK_OPTS_REQUIRE_SHA\fP is set\. .TP \fB\-\-[no\-]quarantine\fP -Disable/enable quarantining of downloads (default: enabled)\. +Disable/enable quarantining of downloads (default: enabled)\. Enabled by default if \fB$HOMEBREW_CASK_OPTS_QUARANTINE\fP is set\. .TP \fB\-\-adopt\fP Adopt existing artifacts in the destination that are identical to those being installed\. Cannot be combined with \fB\-\-force\fP\&\. @@ -920,9 +925,9 @@ Installs and configures Homebrew\[u2019]s Ruby\. If \fBcommand\fP is passed, it .SS "\fBshellenv\fP \fR[\fIshell\fP \.\.\.]" Valid shells: bash|csh|fish|pwsh|sh|tcsh|zsh .P -Print export statements\. When run in a shell, this installation of Homebrew will be added to your \fBPATH\fP, \fBMANPATH\fP, and \fBINFOPATH\fP\&\. +Print export statements\. When run in a shell, this installation of Homebrew will be added to your \fB$PATH\fP, \fB$MANPATH\fP, and \fB$INFOPATH\fP\&\. .P -The variables \fB$HOMEBREW_PREFIX\fP, \fB$HOMEBREW_CELLAR\fP and \fB$HOMEBREW_REPOSITORY\fP are also exported to avoid querying them multiple times\. To help guarantee idempotence, this command produces no output when Homebrew\[u2019]s \fBbin\fP and \fBsbin\fP directories are first and second respectively in your \fBPATH\fP\&\. Consider adding evaluation of this command\[u2019]s output to your dotfiles (e\.g\. \fB~/\.bash_profile\fP or ~/\.zprofile\fB on macOS and ~/\.bashrc\fP or ~/\.zshrc\fB on Linux) with: \fPeval \[u201c]$(brew shellenv)\[u201d]` +The variables \fB$HOMEBREW_PREFIX\fP, \fB$HOMEBREW_CELLAR\fP and \fB$HOMEBREW_REPOSITORY\fP are also exported to avoid querying them multiple times\. To help guarantee idempotence, this command produces no output when Homebrew\[u2019]s \fBbin\fP and \fBsbin\fP directories are first and second respectively in your \fB$PATH\fP\&\. Consider adding evaluation of this command\[u2019]s output to your dotfiles (e\.g\. \fB~/\.bash_profile\fP or ~/\.zprofile\fB on macOS and ~/\.bashrc\fP or ~/\.zshrc\fB on Linux) with: \fPeval \[u201c]$(brew shellenv)\[u201d]` .P The shell can be specified explicitly with a supported shell name parameter\. Unknown shells will output POSIX exports\. .SS "\fBtab\fP \fR[\fIoptions\fP] \fIinstalled_formula\fP|\fIinstalled_cask\fP \fR[\.\.\.]" @@ -1034,7 +1039,7 @@ Unless \fB$HOMEBREW_NO_INSTALL_CLEANUP\fP is set, \fBbrew cleanup\fP will then b If brewing fails, open an interactive debugging session with access to IRB or a shell inside the temporary build directory\. .TP \fB\-\-display\-times\fP -Print install times for each package at the end of the run\. +Print install times for each package at the end of the run\. Enabled by default if \fB$HOMEBREW_DISPLAY_INSTALL_TIMES\fP is set\. .TP \fB\-f\fP, \fB\-\-force\fP Install formulae without checking for previously installed keg\-only or non\-migrated versions\. When installing casks, overwrite existing files (binaries and symlinks are excluded, unless originally from the same cask)\. @@ -1046,7 +1051,7 @@ Print the verification and post\-install steps\. Show what would be upgraded, but do not actually upgrade anything\. .TP \fB\-\-ask\fP -Ask for confirmation before downloading and upgrading formulae\. Print bottles and dependencies download size, install and net install size\. +Ask for confirmation before downloading and upgrading formulae\. Print download, install and net install sizes of bottles and dependencies\. Enabled by default if \fB$HOMEBREW_ASK\fP is set\. .TP \fB\-\-formula\fP Treat all named arguments as formulae\. If no named arguments are specified, upgrade only outdated formulae\. @@ -1088,13 +1093,13 @@ Also include casks with \fBversion :latest\fP\&\. Also include casks with \fBauto_updates true\fP\&\. .TP \fB\-\-[no\-]binaries\fP -Disable/enable linking of helper executables (default: enabled)\. +Disable/enable linking of helper executables (default: enabled)\. Enabled by default if \fB$HOMEBREW_CASK_OPTS_BINARIES\fP is set\. .TP \fB\-\-require\-sha\fP -Require all casks to have a checksum\. +Require all casks to have a checksum\. Enabled by default if \fB$HOMEBREW_CASK_OPTS_REQUIRE_SHA\fP is set\. .TP \fB\-\-[no\-]quarantine\fP -Disable/enable quarantining of downloads (default: enabled)\. +Disable/enable quarantining of downloads (default: enabled)\. Enabled by default if \fB$HOMEBREW_CASK_OPTS_QUARANTINE\fP is set\. .SS "\fBuses\fP \fR[\fIoptions\fP] \fIformula\fP \fR[\.\.\.]" Show formulae and casks that specify \fIformula\fP as a dependency; that is, show dependents of \fIformula\fP\&\. When given multiple formula arguments, show the intersection of formulae that use \fIformula\fP\&\. By default, \fBuses\fP shows all formulae and casks that specify \fIformula\fP as a required or recommended dependency for their stable builds\. .P @@ -1223,7 +1228,7 @@ Run additional, slower style checks that require a network connection\. Only check formulae and casks that are currently installed\. .TP \fB\-\-eval\-all\fP -Evaluate all available formulae and casks, whether installed or not, to audit them\. Implied if \fBHOMEBREW_EVAL_ALL\fP is set\. +Evaluate all available formulae and casks, whether installed or not, to audit them\. Implied if \fB$HOMEBREW_EVAL_ALL\fP is set\. .TP \fB\-\-new\fP Run various additional style checks to determine if a new formula or cask is eligible for Homebrew\. This should be used when creating new formulae or casks and implies \fB\-\-strict\fP and \fB\-\-online\fP\&\. @@ -1621,7 +1626,7 @@ Dispatch bottle for Linux x86_64 (using self\-hosted runner)\. \fB\-\-linux\-wheezy\fP Use Debian Wheezy container for building the bottle on Linux\. .SS "\fBedit\fP \fR[\fIoptions\fP] \fR[\fIformula\fP|\fIcask\fP|\fItap\fP \.\.\.]" -Open a \fIformula\fP, \fIcask\fP or \fItap\fP in the editor set by \fBEDITOR\fP or \fBHOMEBREW_EDITOR\fP, or open the Homebrew repository for editing if no argument is provided\. +Open a \fIformula\fP, \fIcask\fP or \fItap\fP in the editor set by \fB$EDITOR\fP or \fB$HOMEBREW_EDITOR\fP, or open the Homebrew repository for editing if no argument is provided\. .TP \fB\-\-formula\fP Treat all named arguments as formulae\. @@ -1729,7 +1734,7 @@ Enter the interactive Homebrew Ruby shell\. Show several examples\. .TP \fB\-\-pry\fP -Use Pry instead of IRB\. Implied if \fBHOMEBREW_PRY\fP is set\. +Use Pry instead of IRB\. Enabled by default if \fB$HOMEBREW_PRY\fP is set\. .SS "\fBlinkage\fP \fR[\fIoptions\fP] \fR[\fIinstalled_formula\fP \.\.\.]" Check the library links from the given \fIformula\fP kegs\. If no \fIformula\fP are provided, check all kegs\. Raises an error if run on uninstalled formulae\. .TP @@ -1743,9 +1748,9 @@ Exit with a non\-zero status if any undeclared dependencies with linkage are fou For every library that a keg references, print its dylib path followed by the binaries that link to it\. .TP \fB\-\-cached\fP -Print the cached linkage values stored in \fBHOMEBREW_CACHE\fP, set by a previous \fBbrew linkage\fP run\. +Print the cached linkage values stored in \fB$HOMEBREW_CACHE\fP, set by a previous \fBbrew linkage\fP run\. .SS "\fBlivecheck\fP, \fBlc\fP \fR[\fIoptions\fP] \fR[\fIformula\fP|\fIcask\fP \.\.\.]" -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 \fBHOMEBREW_LIVECHECK_WATCHLIST\fP or \fB~/\.homebrew/livecheck_watchlist\.txt\fP\&\. +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 \fB$HOMEBREW_LIVECHECK_WATCHLIST\fP or \fB~/\.homebrew/livecheck_watchlist\.txt\fP\&\. .TP \fB\-\-full\-name\fP Print formulae and casks with fully\-qualified names\. @@ -1954,10 +1959,10 @@ Only generate public API documentation\. \fB\-\-open\fP Open generated documentation in a browser\. .SS "\fBsh\fP \fR[\fB\-\-env=\fP] \fR[\fB\-\-cmd=\fP] \fR[\fIfile\fP]" -Enter an interactive shell for Homebrew\[u2019]s build environment\. Use years\-battle\-hardened build logic to help your \fB\&\./configure && make && make install\fP and even your \fBgem install\fP succeed\. Especially handy if you run Homebrew in an Xcode\-only configuration since it adds tools like \fBmake\fP to your \fBPATH\fP which build systems would not find otherwise\. +Enter an interactive shell for Homebrew\[u2019]s build environment\. Use years\-battle\-hardened build logic to help your \fB\&\./configure && make && make install\fP and even your \fBgem install\fP succeed\. Especially handy if you run Homebrew in an Xcode\-only configuration since it adds tools like \fBmake\fP to your \fB$PATH\fP which build systems would not find otherwise\. .TP \fB\-\-env\fP -Use the standard \fBPATH\fP instead of superenv\[u2019]s when \fBstd\fP is passed\. +Use the standard \fB$PATH\fP instead of superenv\[u2019]s when \fBstd\fP is passed\. .TP \fB\-c\fP, \fB\-\-cmd\fP Execute commands in a non\-interactive shell\. @@ -2034,6 +2039,9 @@ Only runs tests on files that were changed from the master branch\. \fB\-\-fail\-fast\fP Exit early on the first failing test\. .TP +\fB\-\-no\-parallel\fP +Run tests serially\. +.TP \fB\-\-only\fP Run only \fB_spec\.rb\fP\&\. Appending \fB:\fP will start at a specific line\. .TP @@ -2087,7 +2095,7 @@ Print the number of unbottled and total formulae\. Print the \fBhomebrew/core\fP commits where bottles were lost in the last week\. .TP \fB\-\-eval\-all\fP -Evaluate all available formulae and casks, whether installed or not, to check them\. Implied if \fBHOMEBREW_EVAL_ALL\fP is set\. +Evaluate all available formulae and casks, whether installed or not, to check them\. Implied if \fB$HOMEBREW_EVAL_ALL\fP is set\. .SS "\fBunpack\fP \fR[\fIoptions\fP] \fIformula\fP \fR[\.\.\.]" Unpack the source files for \fIformula\fP into subdirectories of the current working directory\. .TP @@ -2141,7 +2149,7 @@ Update the list of GitHub Sponsors in the \fBHomebrew/brew\fP README\. Run a test of \fBbrew update\fP with a new repository clone\. If no options are passed, use \fBorigin/master\fP as the start commit\. .TP \fB\-\-to\-tag\fP -Set \fBHOMEBREW_UPDATE_TO_TAG\fP to test updating between tags\. +Set \fB$HOMEBREW_UPDATE_TO_TAG\fP to test updating between tags\. .TP \fB\-\-keep\-tmp\fP Retain the temporary directory containing the new repository clone\. @@ -2401,7 +2409,7 @@ Evaluate all installed taps, rather than just the core tap\. \fB\-\-max\-downloads\fP Specify a maximum number of formulae to download and update\. .SH "CUSTOM EXTERNAL COMMANDS" -Homebrew, like \fBgit\fP(1), supports external commands\. These are executable scripts that reside somewhere in the \fBPATH\fP, named \fBbrew\-\fP\fIcmdname\fP or \fBbrew\-\fP\fIcmdname\fP\fB\&\.rb\fP, which can be invoked like \fBbrew\fP \fIcmdname\fP\&\. This allows you to create your own commands without modifying Homebrew\[u2019]s internals\. +Homebrew, like \fBgit\fP(1), supports external commands\. These are executable scripts that reside somewhere in the \fB$PATH\fP, named \fBbrew\-\fP\fIcmdname\fP or \fBbrew\-\fP\fIcmdname\fP\fB\&\.rb\fP, which can be invoked like \fBbrew\fP \fIcmdname\fP\&\. This allows you to create your own commands without modifying Homebrew\[u2019]s internals\. .P Instructions for creating your own commands can be found in the docs: .UR https://docs\.brew\.sh/External\-Commands @@ -2427,7 +2435,7 @@ Note that environment variables must have a value set to be detected\. For examp .IP \(bu 4 \fB$XDG_CONFIG_HOME/homebrew/brew\.env\fP if \fB$XDG_CONFIG_HOME\fP is set or \fB~/\.homebrew/brew\.env\fP otherwise (user\-specific) .P -User\-specific environment files take precedence over prefix\-specific files and prefix\-specific files take precedence over system\-wide files (unless \fBHOMEBREW_SYSTEM_ENV_TAKES_PRIORITY\fP is set, see below)\. +User\-specific environment files take precedence over prefix\-specific files and prefix\-specific files take precedence over system\-wide files (unless \fB$HOMEBREW_SYSTEM_ENV_TAKES_PRIORITY\fP is set, see below)\. .P Note that these files do not support shell variable expansion e\.g\. \fB$HOME\fP or command execution e\.g\. \fB$(cat file)\fP\&\. .TP @@ -2836,7 +2844,7 @@ If set, Homebrew will use the given config file instead of \fB~/\.ssh/config\fP .RE .TP \fBHOMEBREW_SUDO_THROUGH_SUDO_USER\fP -If set, Homebrew will use the \fBSUDO_USER\fP environment variable to define the user to \fBsudo\fP(8) through when running \fBsudo\fP(8)\. +If set, Homebrew will use the \fB$SUDO_USER\fP environment variable to define the user to \fBsudo\fP(8) through when running \fBsudo\fP(8)\. .TP \fBHOMEBREW_SVN\fP Use this as the \fBsvn\fP(1) binary\.