diff --git a/Library/Homebrew/attestation.rb b/Library/Homebrew/attestation.rb index 88062e6d0c..9ec91cd6ea 100644 --- a/Library/Homebrew/attestation.rb +++ b/Library/Homebrew/attestation.rb @@ -66,7 +66,7 @@ module Homebrew sig { returns(Pathname) } def self.gh_executable @gh_executable ||= T.let(nil, T.nilable(Pathname)) - return @gh_executable if @gh_executable.present? + return @gh_executable if @gh_executable # NOTE: We set HOMEBREW_NO_VERIFY_ATTESTATIONS when installing `gh` itself, # to prevent a cycle during bootstrapping. This can eventually be resolved diff --git a/Library/Homebrew/brew.rb b/Library/Homebrew/brew.rb index 78eb9a7db9..13b3bacd31 100644 --- a/Library/Homebrew/brew.rb +++ b/Library/Homebrew/brew.rb @@ -77,7 +77,7 @@ begin # External commands expect a normal PATH ENV["PATH"] = homebrew_path.to_s - external_ruby_v2_cmd = Commands.external_ruby_v2_cmd_path(cmd).present? + external_ruby_v2_cmd = !Commands.external_ruby_v2_cmd_path(cmd).nil? external_ruby_cmd_path = Commands.external_ruby_cmd_path(cmd) unless external_ruby_v2_cmd external_cmd_path = Commands.external_cmd_path(cmd) if !external_ruby_v2_cmd && external_ruby_cmd_path.nil? end diff --git a/Library/Homebrew/build.rb b/Library/Homebrew/build.rb index a7552bfd79..be833176c0 100644 --- a/Library/Homebrew/build.rb +++ b/Library/Homebrew/build.rb @@ -238,7 +238,7 @@ class Build elsif formula.prefix.directory? formula.prefix elsif (children = formula.rack.children.presence) && children.size == 1 && - (first_child = children.first.presence) && first_child.directory? + (first_child = children.first) && first_child.directory? first_child else raise diff --git a/Library/Homebrew/bundle.rb b/Library/Homebrew/bundle.rb index 881f151292..04cceb71de 100644 --- a/Library/Homebrew/bundle.rb +++ b/Library/Homebrew/bundle.rb @@ -150,7 +150,7 @@ module Homebrew tab = Tab.for_name(name) tabfile = tab.tabfile - next if tabfile.blank? || !tabfile.exist? + next unless tabfile&.exist? next if tab.installed_on_request next name if use_brew_tab diff --git a/Library/Homebrew/bundle/subcommand/exec.rb b/Library/Homebrew/bundle/subcommand/exec.rb index bde3a3697e..4763c9ae24 100644 --- a/Library/Homebrew/bundle/subcommand/exec.rb +++ b/Library/Homebrew/bundle/subcommand/exec.rb @@ -169,7 +169,7 @@ module Homebrew # For commands which aren't either absolute or relative # Add the command directory to PATH, since it may get blown away by superenv - if command.exclude?("/") && (which_command = which(command)).present? + if command.exclude?("/") && (which_command = which(command)) ENV.prepend_path "PATH", which_command.dirname.to_s end diff --git a/Library/Homebrew/cleanup.rb b/Library/Homebrew/cleanup.rb index 2bb355950f..2840b14eae 100644 --- a/Library/Homebrew/cleanup.rb +++ b/Library/Homebrew/cleanup.rb @@ -750,7 +750,7 @@ module Homebrew db.each_key do |keg| keg = T.cast(keg, String) - next if rack.present? && !keg.start_with?("#{rack}/") + next if rack && !keg.start_with?("#{rack}/") next if File.directory?(keg) LinkageCacheStore.new( diff --git a/Library/Homebrew/cmd/info.rb b/Library/Homebrew/cmd/info.rb index 61c62e575d..f586513df1 100644 --- a/Library/Homebrew/cmd/info.rb +++ b/Library/Homebrew/cmd/info.rb @@ -581,7 +581,7 @@ module Homebrew return cask.sourcefile_path.to_s if tap.blank? || tap.remote.blank? sourcefile_path = cask.sourcefile_path - if sourcefile_path.blank? || sourcefile_path.extname != ".rb" + if !sourcefile_path || sourcefile_path.extname != ".rb" return "#{tap.default_remote}/blob/HEAD/#{tap.relative_cask_path(cask.token)}" end diff --git a/Library/Homebrew/cmd/tab.rb b/Library/Homebrew/cmd/tab.rb index 4c9329875e..c6bdd1c61c 100644 --- a/Library/Homebrew/cmd/tab.rb +++ b/Library/Homebrew/cmd/tab.rb @@ -65,15 +65,15 @@ module Homebrew cask = formula_or_cask cask_tab = cask.tab cask_tabfile = cask_tab.tabfile - if cask_tabfile.blank? || !cask_tabfile.exist? - [cask.token, Cask::Tab.create(cask), true] - else + if cask_tabfile&.exist? [cask.token, cask_tab, false] + else + [cask.token, Cask::Tab.create(cask), true] end end tabfile = tab.tabfile - if !created_tab && (tabfile.blank? || !tabfile.exist?) + if !created_tab && !tabfile&.exist? raise ArgumentError, "Tab file for #{name} does not exist." end diff --git a/Library/Homebrew/commands.rb b/Library/Homebrew/commands.rb index 1fb645e323..4d6bd1d5e1 100644 --- a/Library/Homebrew/commands.rb +++ b/Library/Homebrew/commands.rb @@ -242,7 +242,7 @@ module Commands return if command == "help" path = self.path(command) - return if path.blank? + return unless path if (cmd_parser = Homebrew::CLI::Parser.from_cmd_path(path)) processed_options = if subcommand.nil? && cmd_parser.subcommands.present? @@ -275,7 +275,7 @@ module Commands sig { params(command: String, short: T::Boolean).returns(T.nilable(String)) } def self.command_description(command, short: false) path = self.path(command) - return if path.blank? + return unless path if (cmd_parser = Homebrew::CLI::Parser.from_cmd_path(path)) if short @@ -305,7 +305,7 @@ module Commands sig { params(command: String).returns(T::Array[Homebrew::CLI::Parser::Subcommand]) } def self.command_subcommands(command) path = self.path(command) - return [] if path.blank? + return [] unless path cmd_parser = Homebrew::CLI::Parser.from_cmd_path(path) return [] if cmd_parser.blank? @@ -319,7 +319,7 @@ module Commands } def self.named_args_type(command, subcommand: nil) path = self.path(command) - return if path.blank? + return unless path cmd_parser = Homebrew::CLI::Parser.from_cmd_path(path) return if cmd_parser.blank? @@ -336,7 +336,7 @@ module Commands sig { params(command: String, option: String).returns(T.nilable(T::Array[String])) } def self.option_conflicts(command, option) path = self.path(command) - return if path.blank? + return unless path cmd_parser = Homebrew::CLI::Parser.from_cmd_path(path) return if cmd_parser.blank? diff --git a/Library/Homebrew/dev-cmd/bottle.rb b/Library/Homebrew/dev-cmd/bottle.rb index b669eb4684..cf21057051 100644 --- a/Library/Homebrew/dev-cmd/bottle.rb +++ b/Library/Homebrew/dev-cmd/bottle.rb @@ -390,7 +390,7 @@ module Homebrew sig { params(formula: Formula).void } def bottle_formula(formula) - local_bottle_json = args.json? && formula.local_bottle_path.present? + local_bottle_json = args.json? && formula.local_bottle_path unless local_bottle_json unless formula.latest_version_installed? @@ -458,7 +458,7 @@ module Homebrew if local_bottle_json bottle_path = formula.local_bottle_path - return if bottle_path.blank? + return unless bottle_path local_filename = bottle_path.basename.to_s diff --git a/Library/Homebrew/dev-cmd/vendor-gems.rb b/Library/Homebrew/dev-cmd/vendor-gems.rb index 666da2b9c0..9a79facbaa 100644 --- a/Library/Homebrew/dev-cmd/vendor-gems.rb +++ b/Library/Homebrew/dev-cmd/vendor-gems.rb @@ -74,7 +74,7 @@ module Homebrew "--no-document", "--no-wrappers", "--ignore-dependencies", "--force" (HOMEBREW_LIBRARY_PATH/"vendor/gems").cd do source = Pathname.glob("#{gem}-*/").first - next if source.blank? + next unless source # We cannot use `#ln_sf` here because that has unintended consequences when # the symlink we want to create exists and points to an existing directory. diff --git a/Library/Homebrew/development_tools.rb b/Library/Homebrew/development_tools.rb index fcba64033f..a94b810a92 100644 --- a/Library/Homebrew/development_tools.rb +++ b/Library/Homebrew/development_tools.rb @@ -28,7 +28,7 @@ class DevelopmentTools sig { returns(T::Boolean) } def installed? - locate("clang").present? || locate("gcc").present? + !!(locate("clang") || locate("gcc")) end sig { returns(String) } diff --git a/Library/Homebrew/extend/blank.rb b/Library/Homebrew/extend/blank.rb index 4c80b1bc47..9685e6e919 100644 --- a/Library/Homebrew/extend/blank.rb +++ b/Library/Homebrew/extend/blank.rb @@ -56,4 +56,5 @@ require "extend/blank/hash" require "extend/blank/symbol" require "extend/blank/string" require "extend/blank/numeric" +require "extend/blank/pathname" require "extend/blank/time" diff --git a/Library/Homebrew/extend/blank/pathname.rb b/Library/Homebrew/extend/blank/pathname.rb new file mode 100644 index 0000000000..2d1c3725ce --- /dev/null +++ b/Library/Homebrew/extend/blank/pathname.rb @@ -0,0 +1,24 @@ +# typed: strict +# frozen_string_literal: true + +class Pathname + # A Pathname is blank if its path is empty. Unlike `Pathname#empty?`, + # this never touches the filesystem, so an existing-but-empty file or + # directory is still present. + # + # ```ruby + # Pathname.new("").blank? # => true + # Pathname.new(" ").blank? # => false + # Pathname.new("test").blank? # => false + # ``` + # + # @see https://github.com/rails/rails/blob/main/activesupport/lib/active_support/core_ext/pathname/blank.rb + # `Pathname#blank?` + sig { returns(T::Boolean) } + def blank? + to_s.empty? + end + + sig { returns(T::Boolean) } + def present? = !blank? # :nodoc: +end diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index ae1e7fe073..256f4195e4 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -499,7 +499,7 @@ class Formula return @unresolved_path if @unresolved_path.exist? - return local_bottle_path if local_bottle_path.presence&.exist? + return local_bottle_path if local_bottle_path&.exist? alias_path || @unresolved_path end @@ -962,8 +962,6 @@ class Formula def linked_keg linked_keg = possible_names.map { |name| HOMEBREW_LINKED_KEGS/name } .find(&:directory?) - # Truthiness, not `.present?`: `Pathname#present?` checks directory - # emptiness on disk, which is a wasted syscall here. linked_keg || (HOMEBREW_LINKED_KEGS/name) end diff --git a/Library/Homebrew/formula_auditor.rb b/Library/Homebrew/formula_auditor.rb index fde28a63c9..421669ad08 100644 --- a/Library/Homebrew/formula_auditor.rb +++ b/Library/Homebrew/formula_auditor.rb @@ -666,7 +666,7 @@ module Homebrew return unless @new_formula # Using internal API here as using `Formulary.factory` is too slow - return if !@online && Homebrew::API::Internal.cached_packages_json_file_path.blank? + return if !@online && !Homebrew::API::Internal.cached_packages_json_file_path.exist? formula_url = formula.stable&.url return unless formula_url diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb index 186aa0aa7d..1514b46965 100644 --- a/Library/Homebrew/formula_installer.rb +++ b/Library/Homebrew/formula_installer.rb @@ -268,7 +268,7 @@ class FormulaInstaller return false end - return true if formula.local_bottle_path.present? + return true if formula.local_bottle_path bottle = api_bottle || formula.bottle_for_tag(Utils::Bottles.tag) return false if bottle.nil? @@ -1380,7 +1380,7 @@ on_request: installed_on_request?, options:) keg_formula_path = installed_prefix/".brew/#{formula.name}.rb" return keg_formula_path if formula.loaded_from_api? - return keg_formula_path if formula.local_bottle_path.present? + return keg_formula_path if formula.local_bottle_path return keg_formula_path if build_from_source? return keg_formula_path unless tap_formula_path.exist? @@ -1470,7 +1470,7 @@ on_request: installed_on_request?, options:) sig { params(quiet: T::Boolean, enqueue: T::Boolean).void } def fetch_bottle_tab(quiet: false, enqueue: false) return if @fetch_bottle_tab - return if formula.local_bottle_path.present? + return if formula.local_bottle_path if (bottle = api_bottle || formula.bottle) && (manifest_resource = bottle.github_packages_manifest_resource) && @@ -1500,7 +1500,7 @@ on_request: installed_on_request?, options:) fetch_dependencies return if only_deps? - return if formula.local_bottle_path.present? + return if formula.local_bottle_path downloadable_object = downloadable check_attestation = if pour_bottle?(output_warning: true) diff --git a/Library/Homebrew/os.rb b/Library/Homebrew/os.rb index 412e6c6ace..4a840e7e67 100644 --- a/Library/Homebrew/os.rb +++ b/Library/Homebrew/os.rb @@ -124,7 +124,7 @@ module OS else "https://docs.brew.sh/Troubleshooting" end.freeze - PATH_OPEN = if wsl? && (wslview = which("wslview").presence) + PATH_OPEN = if wsl? && (wslview = which("wslview")) wslview.to_s else "xdg-open" diff --git a/Library/Homebrew/services/cli.rb b/Library/Homebrew/services/cli.rb index 6aed62d5e0..683f6e5f1e 100644 --- a/Library/Homebrew/services/cli.rb +++ b/Library/Homebrew/services/cli.rb @@ -146,7 +146,7 @@ module Homebrew install_service_file(service, file) - if file.blank? && verbose + if !file && verbose ohai "Generated service file for #{service.formula.name}:" puts " #{service.dest.read.gsub("\n", "\n ")}" puts @@ -412,7 +412,7 @@ module Homebrew end temp = Tempfile.new(service.service_name) - temp << if file.blank? + temp << if file.nil? contents = service.service_file.read if sudo_service_user && System.launchctl? diff --git a/Library/Homebrew/test/extend/blank/pathname_spec.rb b/Library/Homebrew/test/extend/blank/pathname_spec.rb new file mode 100644 index 0000000000..3d968dd563 --- /dev/null +++ b/Library/Homebrew/test/extend/blank/pathname_spec.rb @@ -0,0 +1,50 @@ +# typed: true +# frozen_string_literal: true + +require "extend/blank" + +# Modelled on ActiveSupport's `test/core_ext/pathname/blank_test.rb`. +RSpec.describe Pathname do + let(:blank) { [described_class.new("")] } + let(:present) { [described_class.new(" "), described_class.new("."), described_class.new("test")] } + + describe "#blank?" do + it "is blank if and only if the path string is empty" do + blank.each { |path| expect(path.blank?).to be(true), "#{path.inspect} should be blank" } + present.each { |path| expect(path.blank?).to be(false), "#{path.inspect} should not be blank" } + end + end + + describe "#present?" do + it "is present if and only if the path string is not empty" do + blank.each { |path| expect(path.present?).to be(false), "#{path.inspect} should not be present" } + present.each { |path| expect(path.present?).to be(true), "#{path.inspect} should be present" } + end + end + + describe "#presence" do + it "returns the pathname when present, otherwise nil" do + blank.each { |path| expect(path.presence).to be_nil } + present.each { |path| expect(path.presence).to be path } + end + end + + describe "filesystem independence" do + # Before `Pathname#blank?` was redefined it dispatched to the filesystem + # via `Pathname#empty?`, so the empty path string was present and the + # existing empty file and directory were blank. A nonexistent path was + # present under both implementations. + it "judges by the path string, not filesystem content" do + expect(described_class.new("").blank?).to be true + expect(mktmpdir.present?).to be true + expect((mktmpdir/"nonexistent").present?).to be true + end + + it "treats an existing empty file as present" do + file = mktmpdir/"empty-file" + FileUtils.touch file + + expect(file.present?).to be true + end + end +end diff --git a/Library/Homebrew/test/formula_auditor_spec.rb b/Library/Homebrew/test/formula_auditor_spec.rb index ecde040dbc..f0c9b3c381 100644 --- a/Library/Homebrew/test/formula_auditor_spec.rb +++ b/Library/Homebrew/test/formula_auditor_spec.rb @@ -1997,7 +1997,7 @@ RSpec.describe Homebrew::FormulaAuditor do end specify "it warns if new formula uses the same URL as already existing package" do - fa = formula_auditor "duplicate-foo", <<~RUBY, new_formula: true, core_tap: true + fa = formula_auditor "duplicate-foo", <<~RUBY, new_formula: true, core_tap: true, online: true class DuplicateFoo < Formula url "https://brew.sh/foo-1.0.tgz" end @@ -2010,7 +2010,7 @@ RSpec.describe Homebrew::FormulaAuditor do end specify "it does not warn about duplicates if formula is not new" do - fa = formula_auditor "duplicate-foo", <<~RUBY, new_formula: false, core_tap: true + fa = formula_auditor "duplicate-foo", <<~RUBY, new_formula: false, core_tap: true, online: true class DuplicateFoo < Formula url "https://brew.sh/foo-1.0.tgz" end @@ -2020,6 +2020,20 @@ RSpec.describe Homebrew::FormulaAuditor do expect(fa.new_formula_problems).to be_empty end + + specify "it skips the duplicate check offline when no packages data is cached" do + fa = formula_auditor "duplicate-foo", <<~RUBY, new_formula: true, core_tap: true, online: false + class DuplicateFoo < Formula + url "https://brew.sh/foo-1.0.tgz" + end + RUBY + allow(Homebrew::API::Internal).to receive(:cached_packages_json_file_path) + .and_return(Pathname("/nonexistent/packages.jws.json")) + + fa.audit_duplicate_formula + + expect(fa.new_formula_problems).to be_empty + end end describe "#audit_conflicts" do diff --git a/Library/Homebrew/test/utils/tar_spec.rb b/Library/Homebrew/test/utils/tar_spec.rb index 4f5c583c2c..93e461c03c 100644 --- a/Library/Homebrew/test/utils/tar_spec.rb +++ b/Library/Homebrew/test/utils/tar_spec.rb @@ -17,7 +17,7 @@ RSpec.describe Utils::Tar do describe ".available?" do it "returns true if tar or gnu-tar is available" do - if described_class.executable.present? + if described_class.executable expect(described_class).to be_available else expect(described_class).not_to be_available diff --git a/Library/Homebrew/test_bot/test_formulae.rb b/Library/Homebrew/test_bot/test_formulae.rb index 0c36632063..0a9a63a216 100644 --- a/Library/Homebrew/test_bot/test_formulae.rb +++ b/Library/Homebrew/test_bot/test_formulae.rb @@ -67,7 +67,8 @@ module Homebrew # If we have a cached event payload, then we failed to get the artifact we wanted # from `GITHUB_EVENT_PATH`, so use the cached payload to check for a SHA1. - event_payload = JSON.parse(T.must(cached_event_json).read) if cached_event_json.present? + cached_json = cached_event_json + event_payload = JSON.parse(cached_json.read) if cached_json event_payload ||= payload event_payload.fetch("before", nil) @@ -236,7 +237,7 @@ module Homebrew sig { params(formula: String, bottle_dir: Pathname).returns(T.nilable(T::Hash[String, T.untyped])) } def local_bottle_hash(formula, bottle_dir:) - return if (local_bottle_json = bottle_glob(formula, bottle_dir, ".json").first).blank? + return unless (local_bottle_json = bottle_glob(formula, bottle_dir, ".json").first) JSON.parse(local_bottle_json.read) end diff --git a/Library/Homebrew/utils/git.rb b/Library/Homebrew/utils/git.rb index 7aea21aeab..5af2ea9362 100644 --- a/Library/Homebrew/utils/git.rb +++ b/Library/Homebrew/utils/git.rb @@ -213,7 +213,7 @@ module Utils to: T.nilable(String)).returns(Integer) } def self.count_coauthors(repository_path, person, from:, to:) - return 0 if repository_path.blank? + return 0 unless repository_path cmd = [git.to_s, "-C", repository_path.to_s, "log", "--oneline"] cmd << "--format='%(trailers:key=Co-authored-by:)''" diff --git a/Library/Homebrew/utils/github/actions.rb b/Library/Homebrew/utils/github/actions.rb index 41554e39ee..bfce1edc17 100644 --- a/Library/Homebrew/utils/github/actions.rb +++ b/Library/Homebrew/utils/github/actions.rb @@ -107,7 +107,7 @@ module GitHub # the `GITHUB_WORKSPACE` directory or if no `file` is specified. sig { returns(T::Boolean) } def relevant? - return true if @file.blank? + return true unless @file @file.descend.next.to_s != ".." end diff --git a/Library/Homebrew/utils/tar.rb b/Library/Homebrew/utils/tar.rb index ac1b094d6c..3523538e95 100644 --- a/Library/Homebrew/utils/tar.rb +++ b/Library/Homebrew/utils/tar.rb @@ -15,7 +15,7 @@ module Utils sig { returns(T::Boolean) } def available? - executable.present? + !!executable end sig { returns(T.nilable(Pathname)) }