diff options
209 files changed, 2687 insertions, 1722 deletions
diff --git a/Library/.rubocop.yml b/Library/.rubocop.yml index dd6e039b0..ca7ff4dc8 100644 --- a/Library/.rubocop.yml +++ b/Library/.rubocop.yml @@ -29,7 +29,7 @@ Layout/IndentArray: EnforcedStyle: special_inside_parentheses Layout/IndentHeredoc: - EnforcedStyle: unindent + EnforcedStyle: squiggly # conflicts with DSL-style path concatenation with `/` Layout/SpaceAroundOperators: @@ -63,26 +63,28 @@ Metrics/AbcSize: Max: 250 Metrics/BlockLength: - Max: 1250 + Max: 144 Metrics/ClassLength: - Max: 1500 + Max: 589 Metrics/CyclomaticComplexity: Max: 75 Metrics/LineLength: - Max: 400 + Max: 324 + # ignore manpage comments + IgnoredPatterns: ['#: '] Metrics/MethodLength: - Max: 250 + Max: 222 Metrics/ModuleLength: CountComments: false - Exclude: - - '**/bin/**/*' - - '**/cmd/**/*' - - '**/lib/**/*' + Max: 367 + +Metrics/ParameterLists: + CountKeywordArgs: false Metrics/PerceivedComplexity: Max: 100 @@ -94,6 +96,9 @@ Performance/Caller: Style/Alias: EnforcedStyle: prefer_alias +Style/AsciiComments: + Enabled: false + Style/AutoResourceCleanup: Enabled: true @@ -118,6 +123,10 @@ Style/Documentation: Style/Encoding: Enabled: true +# use spaces for indentation; detect tabs +Layout/Tab: + Enabled: true + # dashes in filenames are typical Naming/FileName: Regex: !ruby/regexp /^[\w\@\-\+\.]+(\.rb)?$/ diff --git a/Library/.auditcops.yml b/Library/.rubocop_audit.yml index b5b7a8b58..b5b7a8b58 100644 --- a/Library/.auditcops.yml +++ b/Library/.rubocop_audit.yml diff --git a/Library/Homebrew/.rubocop.yml b/Library/Homebrew/.rubocop.yml index 3b440c33c..0e1fb2d04 100644 --- a/Library/Homebrew/.rubocop.yml +++ b/Library/Homebrew/.rubocop.yml @@ -1,6 +1,5 @@ inherit_from: - ../.rubocop.yml - - .rubocop_todo.yml AllCops: Include: @@ -26,21 +25,20 @@ Lint/NestedMethodDefinition: Lint/ParenthesesAsGroupedExpression: Enabled: true -Metrics/ParameterLists: - CountKeywordArgs: false +Metrics/BlockLength: + Max: 1250 -Style/BlockDelimiters: - Exclude: - - '**/*_spec.rb' - - '**/shared_examples/**/*.rb' +Metrics/BlockNesting: + Max: 5 -# so many of these in formulae but none in here -Style/GuardClause: - Enabled: true +Metrics/ClassLength: + Max: 1226 -# hash-rockets preferred for formulae, a: 1 preferred elsewhere -Style/HashSyntax: - EnforcedStyle: ruby19_no_mixed_keys +Metrics/LineLength: + Max: 244 + +Metrics/MethodLength: + Max: 195 # we won't change backward compatible method names Naming/MethodName: @@ -52,3 +50,16 @@ Naming/PredicateName: Exclude: - 'compat/**/*' NameWhitelist: is_32_bit?, is_64_bit? + +Style/BlockDelimiters: + Exclude: + - '**/*_spec.rb' + - '**/shared_examples/**/*.rb' + +# so many of these in formulae but none in here +Style/GuardClause: + Enabled: true + +# hash-rockets preferred for formulae, a: 1 preferred elsewhere +Style/HashSyntax: + EnforcedStyle: ruby19_no_mixed_keys diff --git a/Library/Homebrew/.rubocop_todo.yml b/Library/Homebrew/.rubocop_todo.yml deleted file mode 100644 index 96c2f3676..000000000 --- a/Library/Homebrew/.rubocop_todo.yml +++ /dev/null @@ -1,138 +0,0 @@ -# This configuration was generated by -# `rubocop --auto-gen-config --exclude-limit 100` -# on 2017-01-27 21:44:55 +0000 using RuboCop version 0.47.1. -# The point is for the user to remove these configuration records -# one by one as the offenses are removed from the code base. -# Note that changes in the inspected code, or installation of new -# versions of RuboCop, may require this file to be generated again. - -# Offense count: 17 -Lint/HandleExceptions: - Exclude: - - 'cmd/install.rb' - - 'cmd/reinstall.rb' - - 'cmd/tap.rb' - - 'cmd/update-report.rb' - - 'cmd/upgrade.rb' - - 'cmd/uses.rb' - - 'descriptions.rb' - - 'diagnostic.rb' - - 'extend/ENV/super.rb' - - 'extend/pathname.rb' - - 'formula.rb' - - 'formula_versions.rb' - - 'test/ENV_test.rb' - -# Offense count: 3 -Lint/IneffectiveAccessModifier: - Exclude: - - 'formula.rb' - - 'version.rb' - -# Offense count: 1 -Lint/Loop: - Exclude: - - 'patch.rb' - -# Offense count: 28 -Lint/RescueException: - Exclude: - - 'brew.rb' - - 'build.rb' - - 'cmd/fetch.rb' - - 'cmd/reinstall.rb' - - 'cmd/update-report.rb' - - 'debrew.rb' - - 'dev-cmd/pull.rb' - - 'dev-cmd/test.rb' - - 'formula.rb' - - 'formula_installer.rb' - - 'migrator.rb' - - 'postinstall.rb' - - 'readall.rb' - - 'test.rb' - - 'test/ENV_test.rb' - - 'utils/fork.rb' - -# Offense count: 1 -Lint/ShadowedException: - Exclude: - - 'utils/fork.rb' - -# Offense count: 13 -# Configuration parameters: CountBlocks. -Metrics/BlockNesting: - Max: 5 - -# Offense count: 19 -# Configuration parameters: CountComments. -Metrics/ModuleLength: - Max: 400 - -# Offense count: 1 -# Configuration parameters: CountKeywordArgs. -Metrics/ParameterLists: - Max: 6 - -# Offense count: 2 -Security/MarshalLoad: - Exclude: - - 'dependency.rb' - - 'utils/fork.rb' - -# Offense count: 1 -Naming/AccessorMethodName: - Exclude: - - 'extend/ENV/super.rb' - -# Offense count: 6 -Style/ClassVars: - Exclude: - - 'dev-cmd/audit.rb' - - 'formula_installer.rb' - - 'test/support/helper/fs_leak_logger.rb' - -# Offense count: 13 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. -# SupportedStyles: compact, expanded -Style/EmptyMethod: - Exclude: - - 'debrew/irb.rb' - - 'download_strategy.rb' - - 'extend/ENV/super.rb' - - 'formula.rb' - - 'patch.rb' - -# Offense count: 13 -# Configuration parameters: AllowedVariables. -Style/GlobalVars: - Exclude: - - 'diagnostic.rb' - - 'utils.rb' - -# Offense count: 1 -# Configuration parameters: EnforcedStyle, SupportedStyles. -# SupportedStyles: module_function, extend_self -Style/ModuleFunction: - Exclude: - - 'os/mac/xcode.rb' - -# Offense count: 8 -Style/MultilineBlockChain: - Exclude: - - 'cmd/search.rb' - - 'dev-cmd/aspell-dictionaries.rb' - - 'dev-cmd/audit.rb' - - 'dev-cmd/man.rb' - - 'diagnostic.rb' - - 'test/patching_test.rb' - -# Offense count: 4 -# Cop supports --auto-correct. -Style/MutableConstant: - Exclude: - - 'dependency_collector.rb' - - 'formulary.rb' - - 'tab.rb' - - 'tap.rb' diff --git a/Library/Homebrew/brew.rb b/Library/Homebrew/brew.rb index 7a004240e..2cc339a83 100644 --- a/Library/Homebrew/brew.rb +++ b/Library/Homebrew/brew.rb @@ -9,7 +9,7 @@ RUBY_VERSION_SPLIT = RUBY_VERSION.split "." RUBY_X = RUBY_VERSION_SPLIT[0].to_i RUBY_Y = RUBY_VERSION_SPLIT[1].to_i if RUBY_X < 2 || (RUBY_X == 2 && RUBY_Y < 3) - raise "Homebrew must be run under Ruby 2.3!" + raise "Homebrew must be run under Ruby 2.3! You're running #{RUBY_VERSION}." end require "pathname" @@ -150,7 +150,7 @@ rescue MethodDeprecatedError => e $stderr.puts " #{Formatter.url(e.issues_url)}" end exit 1 -rescue Exception => e +rescue Exception => e # rubocop:disable Lint/RescueException onoe e if internal_cmd && defined?(OS::ISSUES_URL) && !ENV["HOMEBREW_NO_AUTO_UPDATE"] diff --git a/Library/Homebrew/build.rb b/Library/Homebrew/build.rb index cd2fa4c02..836b360da 100644 --- a/Library/Homebrew/build.rb +++ b/Library/Homebrew/build.rb @@ -190,7 +190,7 @@ begin options = Options.create(ARGV.flags_only) build = Build.new(formula, options) build.install -rescue Exception => e +rescue Exception => e # rubocop:disable Lint/RescueException Marshal.dump(e, error_pipe) error_pipe.close exit! 1 diff --git a/Library/Homebrew/build_environment.rb b/Library/Homebrew/build_environment.rb index dc28b2293..3c494428f 100644 --- a/Library/Homebrew/build_environment.rb +++ b/Library/Homebrew/build_environment.rb @@ -46,6 +46,7 @@ module Homebrew HOMEBREW_SDKROOT HOMEBREW_BUILD_FROM_SOURCE MAKE GIT CPP ACLOCAL_PATH PATH CPATH + LD_LIBRARY_PATH LD_RUN_PATH LD_PRELOAD LIBRARY_PATH ].select { |key| env.key?(key) } end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/abstract_uninstall.rb b/Library/Homebrew/cask/lib/hbc/artifact/abstract_uninstall.rb index 3f63dae8f..7505ac49a 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/abstract_uninstall.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/abstract_uninstall.rb @@ -253,7 +253,7 @@ module Hbc end def trash_paths(*paths, command: nil, **_) - result = command.run!("/usr/bin/osascript", args: ["-e", <<-'EOS'.undent, *paths]) + result = command.run!("/usr/bin/osascript", args: ["-e", <<~'EOS', *paths]) on run argv repeat with i from 1 to (count argv) set item i of argv to (item i of argv as POSIX file) diff --git a/Library/Homebrew/cask/lib/hbc/artifact/installer.rb b/Library/Homebrew/cask/lib/hbc/artifact/installer.rb index 588bcabd5..5cd388c7f 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/installer.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/installer.rb @@ -10,7 +10,7 @@ module Hbc module ManualInstaller def install_phase(**) - puts <<-EOS.undent + puts <<~EOS To complete the installation of Cask #{cask}, you must also run the installer at diff --git a/Library/Homebrew/cask/lib/hbc/audit.rb b/Library/Homebrew/cask/lib/hbc/audit.rb index bd25477ac..5180c5688 100644 --- a/Library/Homebrew/cask/lib/hbc/audit.rb +++ b/Library/Homebrew/cask/lib/hbc/audit.rb @@ -174,7 +174,7 @@ module Hbc add_warning "error retrieving appcast: #{result[:command_result].stderr}" else expected = cask.appcast.checkpoint - add_warning <<-EOS.undent unless expected == actual_checkpoint + add_warning <<~EOS unless expected == actual_checkpoint appcast checkpoint mismatch Expected: #{expected} Actual: #{actual_checkpoint} diff --git a/Library/Homebrew/cask/lib/hbc/cask_loader.rb b/Library/Homebrew/cask/lib/hbc/cask_loader.rb index 08d457643..c32b35584 100644 --- a/Library/Homebrew/cask/lib/hbc/cask_loader.rb +++ b/Library/Homebrew/cask/lib/hbc/cask_loader.rb @@ -190,7 +190,7 @@ module Hbc when 2..Float::INFINITY loaders = possible_tap_casks.map(&FromTapPathLoader.method(:new)) - raise CaskError, <<-EOS.undent + raise CaskError, <<~EOS Cask #{ref} exists in multiple taps: #{loaders.map { |loader| " #{loader.tap}/#{loader.token}" }.join("\n")} EOS diff --git a/Library/Homebrew/cask/lib/hbc/cli.rb b/Library/Homebrew/cask/lib/hbc/cli.rb index 92f0333ad..e147c8280 100644 --- a/Library/Homebrew/cask/lib/hbc/cli.rb +++ b/Library/Homebrew/cask/lib/hbc/cli.rb @@ -234,7 +234,7 @@ module Hbc end def purpose - puts <<-EOS.undent + puts <<~EOS brew-cask provides a friendly homebrew-style CLI workflow for the administration of macOS applications distributed as binaries. diff --git a/Library/Homebrew/cask/lib/hbc/cli/create.rb b/Library/Homebrew/cask/lib/hbc/cli/create.rb index 8de101092..e6ca3d7bc 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/create.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/create.rb @@ -21,7 +21,7 @@ module Hbc end def self.template(cask_token) - <<-EOS.undent + <<~EOS cask '#{cask_token}' do version '' sha256 '' diff --git a/Library/Homebrew/cask/lib/hbc/cli/edit.rb b/Library/Homebrew/cask/lib/hbc/cli/edit.rb index 8bce81c52..693edcd51 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/edit.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/edit.rb @@ -8,9 +8,6 @@ module Hbc end def run - cask = casks.first - cask_path = cask.sourcefile_path - odebug "Opening editor for Cask #{cask.token}" exec_editor cask_path rescue CaskUnavailableError => e reason = e.reason.empty? ? "" : "#{e.reason} " @@ -18,6 +15,14 @@ module Hbc raise e.class.new(e.token, reason) end + def cask_path + casks.first.sourcefile_path + rescue CaskInvalidError + path = CaskLoader.path(args.first) + return path if path.file? + raise + end + def self.help "edits the given Cask" end diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_audit_modified_casks.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_audit_modified_casks.rb index b83224fb1..f06e2acc5 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/internal_audit_modified_casks.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_audit_modified_casks.rb @@ -16,7 +16,7 @@ module Hbc super if args.count != 1 - raise ArgumentError, <<-EOS.undent + raise ArgumentError, <<~EOS This command requires exactly one argument. #{self.class.usage} @@ -31,7 +31,7 @@ module Hbc end def self.usage - <<-EOS.undent + <<~EOS Usage: brew cask _audit_modified_casks [options...] <commit range> Given a range of Git commits, find any Casks that were modified and run `brew diff --git a/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb b/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb index f2059605c..c962632bc 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb @@ -25,7 +25,7 @@ module Hbc single = versions.count == 1 - puts <<-EOS.undent + puts <<~EOS #{cask} #{versions.join(", ")} #{single ? "is" : "are"} still installed. Remove #{single ? "it" : "them all"} with `brew cask uninstall --force #{cask}`. EOS diff --git a/Library/Homebrew/cask/lib/hbc/container/air.rb b/Library/Homebrew/cask/lib/hbc/container/air.rb index 4b083e538..f2ebb6bcd 100644 --- a/Library/Homebrew/cask/lib/hbc/container/air.rb +++ b/Library/Homebrew/cask/lib/hbc/container/air.rb @@ -13,7 +13,7 @@ module Hbc def self.installer_cmd return @installer_cmd ||= INSTALLER_PATHNAME if installer_exist? - raise CaskError, <<-EOS.undent + raise CaskError, <<~EOS Adobe AIR runtime not present, try installing it via brew cask install adobe-air diff --git a/Library/Homebrew/cask/lib/hbc/container/dmg.rb b/Library/Homebrew/cask/lib/hbc/container/dmg.rb index 1d172a4b7..c0e43f68a 100644 --- a/Library/Homebrew/cask/lib/hbc/container/dmg.rb +++ b/Library/Homebrew/cask/lib/hbc/container/dmg.rb @@ -88,7 +88,7 @@ module Hbc bomfile.close Tempfile.open(["", ".list"]) do |filelist| - filelist.write(bom_filelist_from_path(mount)) + filelist.puts(bom_filelist_from_path(mount)) filelist.close @command.run!("/usr/bin/mkbom", args: ["-s", "-i", filelist.path, "--", bomfile.path]) @@ -98,16 +98,17 @@ module Hbc end def bom_filelist_from_path(mount) - Dir.chdir(mount) do - Dir.glob("**/*", File::FNM_DOTMATCH).map do |path| - next if skip_path?(Pathname(path)) - (path == ".") ? path : path.prepend("./") - end.compact.join("\n").concat("\n") - end + # We need to use `find` here instead of Ruby in order to properly handle + # file names containing special characters, such as “e” + “´” vs. “é”. + @command.run("/usr/bin/find", args: [".", "-print0"], chdir: mount, print_stderr: false).stdout + .split("\0") + .reject { |path| skip_path?(mount, path) } + .join("\n") end - def skip_path?(path) - dmg_metadata?(path) || system_dir_symlink?(path) + def skip_path?(mount, path) + path = Pathname(path.sub(%r{^\./}, "")) + dmg_metadata?(path) || system_dir_symlink?(mount, path) end # unnecessary DMG metadata @@ -130,9 +131,10 @@ module Hbc DMG_METADATA_FILES.include?(relative_root.basename.to_s) end - def system_dir_symlink?(path) + def system_dir_symlink?(mount, path) + full_path = Pathname(mount).join(path) # symlinks to system directories (commonly to /Applications) - path.symlink? && MacOS.system_dir?(path.readlink) + full_path.symlink? && MacOS.system_dir?(full_path.readlink) end def mounts_from_plist(plist) diff --git a/Library/Homebrew/cask/lib/hbc/dsl/caveats.rb b/Library/Homebrew/cask/lib/hbc/dsl/caveats.rb index 7d373b5f3..45ee5d160 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/caveats.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/caveats.rb @@ -9,22 +9,22 @@ module Hbc class DSL class Caveats < Base def path_environment_variable(path) - puts <<-EOS.undent - To use #{@cask}, you may need to add the #{path} directory - to your PATH environment variable, eg (for bash shell): + puts <<~EOS + To use #{@cask}, you may need to add the #{path} directory + to your PATH environment variable, eg (for bash shell): - export PATH=#{path}:"$PATH" + export PATH=#{path}:"$PATH" EOS end def zsh_path_helper(path) - puts <<-EOS.undent - To use #{@cask}, zsh users may need to add the following line to their - ~/.zprofile. (Among other effects, #{path} will be added to the - PATH environment variable): + puts <<~EOS + To use #{@cask}, zsh users may need to add the following line to their + ~/.zprofile. (Among other effects, #{path} will be added to the + PATH environment variable): - eval `/usr/libexec/path_helper -s` + eval `/usr/libexec/path_helper -s` EOS end @@ -32,7 +32,7 @@ module Hbc def files_in_usr_local localpath = "/usr/local" return unless HOMEBREW_PREFIX.to_s.downcase.start_with?(localpath) - puts <<-EOS.undent + puts <<~EOS Cask #{@cask} installs files under "#{localpath}". The presence of such files can cause warnings when running "brew doctor", which is considered to be a bug in Homebrew-Cask. @@ -42,72 +42,72 @@ module Hbc def depends_on_java(java_version = "any") if java_version == "any" - puts <<-EOS.undent - #{@cask} requires Java. You can install the latest version with + puts <<~EOS + #{@cask} requires Java. You can install the latest version with - brew cask install java + brew cask install java EOS elsif java_version.include?("9") || java_version.include?("+") - puts <<-EOS.undent - #{@cask} requires Java #{java_version}. You can install the latest version with + puts <<~EOS + #{@cask} requires Java #{java_version}. You can install the latest version with - brew cask install java + brew cask install java EOS else - puts <<-EOS.undent - #{@cask} requires Java #{java_version}. You can install it with + puts <<~EOS + #{@cask} requires Java #{java_version}. You can install it with - brew cask install caskroom/versions/java#{java_version} + brew cask install caskroom/versions/java#{java_version} EOS end end def logout - puts <<-EOS.undent - You must log out and log back in for the installation of #{@cask} - to take effect. + puts <<~EOS + You must log out and log back in for the installation of #{@cask} + to take effect. EOS end def reboot - puts <<-EOS.undent - You must reboot for the installation of #{@cask} to take effect. + puts <<~EOS + You must reboot for the installation of #{@cask} to take effect. EOS end def discontinued - puts <<-EOS.undent - #{@cask} has been officially discontinued upstream. - It may stop working correctly (or at all) in recent versions of macOS. + puts <<~EOS + #{@cask} has been officially discontinued upstream. + It may stop working correctly (or at all) in recent versions of macOS. EOS end def free_license(web_page) - puts <<-EOS.undent - The vendor offers a free license for #{@cask} at - #{web_page} + puts <<~EOS + The vendor offers a free license for #{@cask} at + #{web_page} EOS end def malware(radar_number) - puts <<-EOS.undent - #{@cask} has been reported to bundle malware. Like with any app, use at your own risk. + puts <<~EOS + #{@cask} has been reported to bundle malware. Like with any app, use at your own risk. - A report has been made to Apple about this app. Their certificate will hopefully be revoked. - See the public report at - #{Formatter.url("https://openradar.appspot.com/#{radar_number}")} + A report has been made to Apple about this app. Their certificate will hopefully be revoked. + See the public report at + #{Formatter.url("https://openradar.appspot.com/#{radar_number}")} - If this report is accurate, please duplicate it at - #{Formatter.url("https://bugreport.apple.com/")} - If this report is a mistake, please let us know by opening an issue at - #{Formatter.url("https://github.com/caskroom/homebrew-cask/issues/new")} + If this report is accurate, please duplicate it at + #{Formatter.url("https://bugreport.apple.com/")} + If this report is a mistake, please let us know by opening an issue at + #{Formatter.url("https://github.com/caskroom/homebrew-cask/issues/new")} EOS end diff --git a/Library/Homebrew/cask/lib/hbc/exceptions.rb b/Library/Homebrew/cask/lib/hbc/exceptions.rb index f7f9e43b6..2626a467a 100644 --- a/Library/Homebrew/cask/lib/hbc/exceptions.rb +++ b/Library/Homebrew/cask/lib/hbc/exceptions.rb @@ -44,7 +44,7 @@ module Hbc class CaskAlreadyInstalledError < AbstractCaskErrorWithToken def to_s - <<-EOS.undent + <<~EOS Cask '#{token}' is already installed. To re-install #{token}, run: @@ -80,7 +80,7 @@ module Hbc class CaskX11DependencyError < AbstractCaskErrorWithToken def to_s - <<-EOS.undent + <<~EOS Cask '#{token}' requires XQuartz/X11, which can be installed using Homebrew-Cask by running #{Formatter.identifier("brew cask install xquartz")} @@ -132,7 +132,7 @@ module Hbc class CaskSha256MissingError < CaskSha256Error def to_s - <<-EOS.undent + <<~EOS Cask '#{token}' requires a checksum: #{Formatter.identifier("sha256 '#{actual}'")} EOS @@ -148,7 +148,7 @@ module Hbc end def to_s - <<-EOS.undent + <<~EOS Checksum for Cask '#{token}' does not match. Expected: #{Formatter.success(expected.to_s)} @@ -162,7 +162,7 @@ module Hbc class CaskNoShasumError < CaskSha256Error def to_s - <<-EOS.undent + <<~EOS Cask '#{token}' does not have a sha256 checksum defined and was not installed. This means you have the #{Formatter.identifier("--require-sha")} option set, perhaps in your HOMEBREW_CASK_OPTS. EOS diff --git a/Library/Homebrew/cask/lib/hbc/installer.rb b/Library/Homebrew/cask/lib/hbc/installer.rb index 68b9595e1..1063f488b 100644 --- a/Library/Homebrew/cask/lib/hbc/installer.rb +++ b/Library/Homebrew/cask/lib/hbc/installer.rb @@ -326,7 +326,7 @@ module Hbc ], sudo: true) else - opoo <<-EOS.undent + opoo <<~EOS Accessibility access cannot be enabled automatically on this version of macOS. See System Preferences to enable it manually. EOS @@ -347,7 +347,7 @@ module Hbc ], sudo: true) else - opoo <<-EOS.undent + opoo <<~EOS Accessibility access cannot be disabled automatically on this version of macOS. See System Preferences to disable it manually. EOS diff --git a/Library/Homebrew/cask/lib/hbc/system_command.rb b/Library/Homebrew/cask/lib/hbc/system_command.rb index be083c29e..3c8311a3b 100644 --- a/Library/Homebrew/cask/lib/hbc/system_command.rb +++ b/Library/Homebrew/cask/lib/hbc/system_command.rb @@ -8,14 +8,14 @@ require "hbc/utils/hash_validator" module Hbc class SystemCommand - attr_reader :command + extend Predicable - def self.run(executable, options = {}) - new(executable, options).run! + def self.run(executable, **options) + new(executable, **options).run! end - def self.run!(command, options = {}) - run(command, options.merge(must_succeed: true)) + def self.run!(command, **options) + run(command, **options, must_succeed: true) end def run! @@ -26,38 +26,49 @@ module Hbc case type when :stdout processed_output[:stdout] << line - ohai line.chomp if options[:print_stdout] + ohai line.chomp if print_stdout? when :stderr processed_output[:stderr] << line - ohai line.chomp if options[:print_stderr] + ohai line.chomp if print_stderr? end end - assert_success if options[:must_succeed] + assert_success if must_succeed? result end - def initialize(executable, options) + def initialize(executable, args: [], sudo: false, input: [], print_stdout: false, print_stderr: true, must_succeed: false, **options) + executable, *args = Shellwords.shellescape(executable) if args.empty? + @executable = executable + @args = args + @sudo = sudo + @input = input + @print_stdout = print_stdout + @print_stderr = print_stderr + @must_succeed = must_succeed + options.extend(HashValidator).assert_valid_keys(:chdir) @options = options - process_options! + end + + def command + @command ||= [ + *sudo_prefix, + executable, + *args, + ].freeze end private - attr_reader :executable, :options, :processed_output, :processed_status - - def process_options! - options.extend(HashValidator) - .assert_valid_keys :input, :print_stdout, :print_stderr, :args, :must_succeed, :sudo - sudo_prefix = %w[/usr/bin/sudo -E --] - sudo_prefix = sudo_prefix.insert(1, "-A") unless ENV["SUDO_ASKPASS"].nil? - @command = [executable] - options[:print_stderr] = true unless options.key?(:print_stderr) - @command.unshift(*sudo_prefix) if options[:sudo] - @command.concat(options[:args]) if options.key?(:args) && !options[:args].empty? - @command[0] = Shellwords.shellescape(@command[0]) if @command.size == 1 - nil + attr_reader :executable, :args, :input, :options, :processed_output, :processed_status + + attr_predicate :sudo?, :print_stdout?, :print_stderr?, :must_succeed? + + def sudo_prefix + return [] unless sudo? + askpass_flags = ENV.key?("SUDO_ASKPASS") ? ["-A"] : [] + ["/usr/bin/sudo", *askpass_flags, "-E", "--"] end def assert_success @@ -77,7 +88,7 @@ module Hbc def each_output_line(&b) raw_stdin, raw_stdout, raw_stderr, raw_wait_thr = - Open3.popen3(*expanded_command) + Open3.popen3(*expanded_command, **options) write_input_to(raw_stdin) raw_stdin.close_write @@ -87,7 +98,7 @@ module Hbc end def write_input_to(raw_stdin) - [*options[:input]].each { |line| raw_stdin.print line } + [*input].each(&raw_stdin.method(:print)) end def each_line_from(sources) @@ -155,12 +166,12 @@ module Hbc _warn_plist_garbage(command, Regexp.last_match[2]) xml = Plist.parse_xml(output) unless xml.respond_to?(:keys) && !xml.keys.empty? - raise CaskError, <<-EOS - Empty result parsing plist output from command. - command was: - #{command} - output we attempted to parse: - #{output} + raise CaskError, <<~EOS + Empty result parsing plist output from command. + command was: + #{command} + output we attempted to parse: + #{output} EOS end xml diff --git a/Library/Homebrew/cask/lib/hbc/utils.rb b/Library/Homebrew/cask/lib/hbc/utils.rb index 22f826e74..0f44c0157 100644 --- a/Library/Homebrew/cask/lib/hbc/utils.rb +++ b/Library/Homebrew/cask/lib/hbc/utils.rb @@ -90,7 +90,7 @@ module Hbc end def self.error_message_with_suggestions - <<-EOS.undent + <<~EOS Follow the instructions here: #{Formatter.url(BUG_REPORTS_URL)} EOS diff --git a/Library/Homebrew/cask/lib/hbc/version.rb b/Library/Homebrew/cask/lib/hbc/version.rb index 2eb942b95..c7ce8e2d8 100644 --- a/Library/Homebrew/cask/lib/hbc/version.rb +++ b/Library/Homebrew/cask/lib/hbc/version.rb @@ -1,7 +1,7 @@ module Hbc def self.full_version @full_version ||= begin - <<-EOS.undent + <<~EOS Homebrew-Cask #{HOMEBREW_VERSION} caskroom/homebrew-cask #{Hbc.default_tap.version_string} EOS diff --git a/Library/Homebrew/caveats.rb b/Library/Homebrew/caveats.rb index 1849ea79b..485116cff 100644 --- a/Library/Homebrew/caveats.rb +++ b/Library/Homebrew/caveats.rb @@ -44,7 +44,7 @@ class Caveats def keg_only_text return unless f.keg_only? - s = <<-EOS.undent + s = <<~EOS This formula is keg-only, which means it was not symlinked into #{HOMEBREW_PREFIX}, because #{f.keg_only_reason.to_s.chomp}. EOS @@ -86,12 +86,12 @@ class Caveats case shell when :bash - <<-EOS.undent + <<~EOS Bash completion has been installed to: #{HOMEBREW_PREFIX}/etc/bash_completion.d EOS when :zsh - <<-EOS.undent + <<~EOS zsh #{installed.join(" and ")} have been installed to: #{HOMEBREW_PREFIX}/share/zsh/site-functions EOS @@ -111,7 +111,7 @@ class Caveats homebrew_site_packages = Language::Python.homebrew_site_packages user_site_packages = Language::Python.user_site_packages "python" pth_file = user_site_packages/"homebrew.pth" - instructions = <<-EOS.undent.gsub(/^/, " ") + instructions = <<~EOS.gsub(/^/, " ") mkdir -p #{user_site_packages} echo 'import site; site.addsitedir("#{homebrew_site_packages}")' >> #{pth_file} EOS @@ -119,7 +119,7 @@ class Caveats if f.keg_only? keg_site_packages = f.opt_prefix/"lib/python2.7/site-packages" unless Language::Python.in_sys_path?("python", keg_site_packages) - s = <<-EOS.undent + s = <<~EOS If you need Python to find bindings for this keg-only formula, run: echo #{keg_site_packages} >> #{homebrew_site_packages/f.name}.pth EOS @@ -131,7 +131,7 @@ class Caveats return if Language::Python.reads_brewed_pth_files?("python") if !Language::Python.in_sys_path?("python", homebrew_site_packages) - s = <<-EOS.undent + s = <<~EOS Python modules have been installed and Homebrew's site-packages is not in your Python sys.path, so you will not be able to import the modules this formula installed. If you plan to develop with these modules, @@ -139,7 +139,7 @@ class Caveats EOS s += instructions elsif keg.python_pth_files_installed? - s = <<-EOS.undent + s = <<~EOS This formula installed .pth files to Homebrew's site-packages and your Python isn't configured to process them, so you will not be able to import the modules this formula installed. If you plan to develop @@ -155,55 +155,13 @@ class Caveats return unless keg return unless keg.elisp_installed? - <<-EOS.undent + <<~EOS Emacs Lisp files have been installed to: #{HOMEBREW_PREFIX}/share/emacs/site-lisp/#{f.name} EOS end - def plist_caveats - s = [] - if f.plist || (keg&.plist_installed?) - plist_domain = f.plist_path.basename(".plist") - - # we readlink because this path probably doesn't exist since caveats - # occurs before the link step of installation - # Yosemite security measures mildly tighter rules: - # https://github.com/Homebrew/legacy-homebrew/issues/33815 - if !plist_path.file? || !plist_path.symlink? - if f.plist_startup - s << "To have launchd start #{f.full_name} now and restart at startup:" - s << " sudo brew services start #{f.full_name}" - else - s << "To have launchd start #{f.full_name} now and restart at login:" - s << " brew services start #{f.full_name}" - end - # For startup plists, we cannot tell whether it's running on launchd, - # as it requires for `sudo launchctl list` to get real result. - elsif f.plist_startup - s << "To restart #{f.full_name} after an upgrade:" - s << " sudo brew services restart #{f.full_name}" - elsif Kernel.system "/bin/launchctl list #{plist_domain} &>/dev/null" - s << "To restart #{f.full_name} after an upgrade:" - s << " brew services restart #{f.full_name}" - else - s << "To start #{f.full_name}:" - s << " brew services start #{f.full_name}" - end - - if f.plist_manual - s << "Or, if you don't want/need a background service you can just run:" - s << " #{f.plist_manual}" - end - - # pbpaste is the system clipboard tool on macOS and fails with `tmux` by default - # check if this is being run under `tmux` to avoid failing - if ENV["TMUX"] && !quiet_system("/usr/bin/pbpaste") - s << "" << "WARNING: brew services will fail when run under tmux." - end - end - s.join("\n") + "\n" unless s.empty? - end + def plist_caveats; end def plist_path destination = if f.plist_startup @@ -222,3 +180,5 @@ class Caveats destination_path/plist_filename end end + +require "extend/os/caveats" diff --git a/Library/Homebrew/cmd/cleanup.rb b/Library/Homebrew/cmd/cleanup.rb index d8f669e85..290b748de 100644 --- a/Library/Homebrew/cmd/cleanup.rb +++ b/Library/Homebrew/cmd/cleanup.rb @@ -38,7 +38,7 @@ module Homebrew end def report_unremovable_kegs - ofail <<-EOS.undent + ofail <<~EOS Could not cleanup old kegs! Fix your permissions on: #{Cleanup.unremovable_kegs.join "\n "} EOS diff --git a/Library/Homebrew/cmd/commands.rb b/Library/Homebrew/cmd/commands.rb index addccd609..0dfc6c451 100644 --- a/Library/Homebrew/cmd/commands.rb +++ b/Library/Homebrew/cmd/commands.rb @@ -16,12 +16,12 @@ module Homebrew else # Find commands in Homebrew/cmd puts "Built-in commands" - puts Formatter.columns(internal_commands) + puts Formatter.columns(internal_commands.sort) # Find commands in Homebrew/dev-cmd puts puts "Built-in developer commands" - puts Formatter.columns(internal_developer_commands) + puts Formatter.columns(internal_developer_commands.sort) # Find commands in the path unless (exts = external_commands).empty? @@ -51,8 +51,8 @@ module Homebrew end def find_internal_commands(directory) - directory.children.each_with_object([]) do |f, cmds| - cmds << f.basename.to_s.sub(/\.(?:rb|sh)$/, "") if f.file? - end + Pathname.glob(directory/"*") + .select(&:file?) + .map { |f| f.basename.to_s.sub(/\.(?:rb|sh)$/, "") } end end diff --git a/Library/Homebrew/cmd/deps.rb b/Library/Homebrew/cmd/deps.rb index de7aa4a51..ae758e143 100644 --- a/Library/Homebrew/cmd/deps.rb +++ b/Library/Homebrew/cmd/deps.rb @@ -68,16 +68,16 @@ module Homebrew if mode.tree? if mode.installed? - puts_deps_tree Formula.installed, !ARGV.one? + puts_deps_tree Formula.installed.sort, !ARGV.one? else raise FormulaUnspecifiedError if ARGV.named.empty? puts_deps_tree ARGV.formulae, !ARGV.one? end elsif mode.all? - puts_deps Formula + puts_deps Formula.sort elsif ARGV.named.empty? raise FormulaUnspecifiedError unless mode.installed? - puts_deps Formula.installed + puts_deps Formula.installed.sort elsif mode.for_each? puts_deps ARGV.formulae else diff --git a/Library/Homebrew/cmd/diy.rb b/Library/Homebrew/cmd/diy.rb index a8f6440df..3980b3d9e 100644 --- a/Library/Homebrew/cmd/diy.rb +++ b/Library/Homebrew/cmd/diy.rb @@ -43,7 +43,7 @@ module Homebrew detected_name = basename[/(.*?)-?#{Regexp.escape(version)}/, 1] || basename canonical_name = Formulary.canonical_name(detected_name) - odie <<-EOS.undent if detected_name != canonical_name + odie <<~EOS if detected_name != canonical_name The detected name #{detected_name.inspect} exists in Homebrew as an alias of #{canonical_name.inspect}. Consider using the canonical name instead: brew diy --name=#{canonical_name} diff --git a/Library/Homebrew/cmd/doctor.rb b/Library/Homebrew/cmd/doctor.rb index cca2dca03..7b1778e63 100644 --- a/Library/Homebrew/cmd/doctor.rb +++ b/Library/Homebrew/cmd/doctor.rb @@ -43,7 +43,7 @@ module Homebrew out = checks.send(method) next if out.nil? || out.empty? if first_warning - $stderr.puts <<-EOS.undent + $stderr.puts <<~EOS #{Tty.bold}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 and just ignore them. Thanks!#{Tty.reset} diff --git a/Library/Homebrew/cmd/fetch.rb b/Library/Homebrew/cmd/fetch.rb index 006c63746..411753992 100644 --- a/Library/Homebrew/cmd/fetch.rb +++ b/Library/Homebrew/cmd/fetch.rb @@ -49,8 +49,10 @@ module Homebrew if fetch_bottle?(f) begin fetch_formula(f.bottle) - rescue Exception => e - raise if ARGV.homebrew_developer? || e.is_a?(Interrupt) + rescue Interrupt + raise + rescue => e + raise if ARGV.homebrew_developer? fetched_bottle = false onoe e.message opoo "Bottle fetch failed: fetching the source." diff --git a/Library/Homebrew/cmd/gist-logs.rb b/Library/Homebrew/cmd/gist-logs.rb index 012121b08..45537602b 100644 --- a/Library/Homebrew/cmd/gist-logs.rb +++ b/Library/Homebrew/cmd/gist-logs.rb @@ -29,7 +29,7 @@ module Homebrew files["00.config.out"] = { content: s.string } files["00.doctor.out"] = { content: `brew doctor 2>&1` } unless f.core_formula? - tap = <<-EOS.undent + tap = <<~EOS Formula: #{f.name} Tap: #{f.tap} Path: #{f.path} @@ -47,7 +47,7 @@ module Homebrew if ARGV.include?("--new-issue") || ARGV.switch?("n") if GitHub.api_credentials_type == :none - puts <<-EOS.undent + puts <<~EOS You can create a new personal access token: #{GitHub::ALL_SCOPES_URL} and then set the new HOMEBREW_GITHUB_API_TOKEN as the authentication method. @@ -64,7 +64,7 @@ module Homebrew def brief_build_info(f) build_time_str = f.logs.ctime.strftime("%Y-%m-%d %H:%M:%S") - s = <<-EOS.undent + s = <<~EOS Homebrew build logs for #{f.full_name} on #{OS_VERSION} EOS if ARGV.include?("--with-hostname") diff --git a/Library/Homebrew/cmd/help.rb b/Library/Homebrew/cmd/help.rb index a0c44854b..c85916f9b 100644 --- a/Library/Homebrew/cmd/help.rb +++ b/Library/Homebrew/cmd/help.rb @@ -1,4 +1,4 @@ -HOMEBREW_HELP = <<-EOS.unindent.freeze +HOMEBREW_HELP = <<~EOS.freeze Example usage: brew search [TEXT|/REGEX/] brew (info|home|options) [FORMULA...] diff --git a/Library/Homebrew/cmd/info.rb b/Library/Homebrew/cmd/info.rb index 5eb033706..83bb712ab 100644 --- a/Library/Homebrew/cmd/info.rb +++ b/Library/Homebrew/cmd/info.rb @@ -67,9 +67,9 @@ module Homebrew def print_json ff = if ARGV.include? "--all" - Formula + Formula.sort elsif ARGV.include? "--installed" - Formula.installed + Formula.installed.sort else ARGV.formulae end @@ -128,7 +128,7 @@ module Homebrew "#{c.name}#{reason}" end.sort! unless conflicts.empty? - puts <<-EOS.undent + puts <<~EOS Conflicts with: #{conflicts.join("\n ")} EOS diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb index 732e96b00..575dbc4b3 100644 --- a/Library/Homebrew/cmd/install.rb +++ b/Library/Homebrew/cmd/install.rb @@ -110,17 +110,17 @@ module Homebrew ARGV.formulae.each do |f| # head-only without --HEAD is an error if !ARGV.build_head? && f.stable.nil? && f.devel.nil? - raise <<-EOS.undent - #{f.full_name} is a head-only formula - Install with `brew install --HEAD #{f.full_name}` + raise <<~EOS + #{f.full_name} is a head-only formula + Install with `brew install --HEAD #{f.full_name}` EOS end # devel-only without --devel is an error if !ARGV.build_devel? && f.stable.nil? && f.head.nil? - raise <<-EOS.undent - #{f.full_name} is a devel-only formula - Install with `brew install --devel #{f.full_name}` + raise <<~EOS + #{f.full_name} is a devel-only formula + Install with `brew install --devel #{f.full_name}` EOS end @@ -150,12 +150,12 @@ module Homebrew # sure --force flag is passed. if f.outdated? optlinked_version = Keg.for(f.opt_prefix).version - onoe <<-EOS.undent + onoe <<~EOS #{f.full_name} #{optlinked_version} is already installed To upgrade to #{f.version}, run `brew upgrade #{f.name}` EOS else - opoo <<-EOS.undent + opoo <<~EOS #{f.full_name} #{f.pkg_version} is already installed EOS end @@ -173,13 +173,13 @@ module Homebrew msg = "#{f.full_name} #{installed_version} is already installed" linked_not_equals_installed = f.linked_version != installed_version if f.linked? && linked_not_equals_installed - msg = <<-EOS.undent + msg = <<~EOS #{msg} The currently linked version is #{f.linked_version} You can use `brew switch #{f} #{installed_version}` to link this version. EOS elsif !f.linked? || f.keg_only? - msg = <<-EOS.undent + msg = <<~EOS #{msg}, it's just not linked. You can use `brew link #{f}` to link this version. EOS @@ -188,7 +188,7 @@ module Homebrew elsif !f.any_version_installed? && old_formula = f.old_installed_formulae.first msg = "#{old_formula.full_name} #{old_formula.installed_version} already installed" if !old_formula.linked? && !old_formula.keg_only? - msg = <<-EOS.undent + msg = <<~EOS #{msg}, it's just not linked. You can use `brew link #{old_formula.full_name}` to link this version. EOS @@ -197,7 +197,7 @@ module Homebrew elsif f.migration_needed? && !ARGV.force? # Check if the formula we try to install is the same as installed # but not migrated one. If --force passed then install anyway. - opoo <<-EOS.undent + opoo <<~EOS #{f.oldname} already installed, it's just not migrated You can migrate formula with `brew migrate #{f}` Or you can force install it with `brew install #{f} --force` @@ -283,7 +283,7 @@ module Homebrew def check_ppc case Hardware::CPU.type when :ppc - abort <<-EOS.undent + abort <<~EOS Sorry, Homebrew does not support your computer's CPU architecture. For PPC support, see: https://github.com/mistydemeo/tigerbrew EOS @@ -308,7 +308,7 @@ module Homebrew def check_cellar FileUtils.mkdir_p HOMEBREW_CELLAR unless File.exist? HOMEBREW_CELLAR rescue - raise <<-EOS.undent + raise <<~EOS Could not create #{HOMEBREW_CELLAR} Check you have permission to write to #{HOMEBREW_CELLAR.parent} EOS @@ -339,6 +339,7 @@ module Homebrew rescue FormulaInstallationAlreadyAttemptedError # We already attempted to install f as part of the dependency tree of # another formula. In that case, don't generate an error, just move on. + return rescue CannotInstallFormulaError => e ofail e.message end diff --git a/Library/Homebrew/cmd/leaves.rb b/Library/Homebrew/cmd/leaves.rb index 4038aee4c..ecebedbb3 100644 --- a/Library/Homebrew/cmd/leaves.rb +++ b/Library/Homebrew/cmd/leaves.rb @@ -9,20 +9,11 @@ module Homebrew module_function def leaves - installed = Formula.installed + installed = Formula.installed.sort deps_of_installed = Set.new installed.each do |f| - deps = [] - - f.deps.each do |dep| - if dep.optional? || dep.recommended? - deps << dep.to_formula.full_name if f.build.with?(dep) - else - deps << dep.to_formula.full_name - end - end - + deps = f.runtime_dependencies.map { |d| d.to_formula.full_name } deps_of_installed.merge(deps) end diff --git a/Library/Homebrew/cmd/link.rb b/Library/Homebrew/cmd/link.rb index 6c4b912e8..5afb19ed6 100644 --- a/Library/Homebrew/cmd/link.rb +++ b/Library/Homebrew/cmd/link.rb @@ -29,7 +29,7 @@ module Homebrew keg_only = keg_only?(keg.rack) if HOMEBREW_PREFIX.to_s == "/usr/local" && keg_only && keg.name.start_with?("openssl", "libressl") - opoo <<-EOS.undent + opoo <<~EOS Refusing to link: #{keg.name} Linking keg-only #{keg.name} means you may end up linking against the insecure, deprecated system OpenSSL while using the headers from Homebrew's #{keg.name}. diff --git a/Library/Homebrew/cmd/linkapps.rb b/Library/Homebrew/cmd/linkapps.rb index 8713b609e..e8d482529 100644 --- a/Library/Homebrew/cmd/linkapps.rb +++ b/Library/Homebrew/cmd/linkapps.rb @@ -19,7 +19,7 @@ module Homebrew module_function def linkapps - opoo <<-EOS.undent + opoo <<~EOS `brew linkapps` has been deprecated and will eventually be removed! Unfortunately `brew linkapps` cannot behave nicely with e.g. Spotlight using diff --git a/Library/Homebrew/cmd/list.rb b/Library/Homebrew/cmd/list.rb index 436fc1f97..f17667286 100644 --- a/Library/Homebrew/cmd/list.rb +++ b/Library/Homebrew/cmd/list.rb @@ -39,7 +39,7 @@ module Homebrew filtered_list elsif ARGV.named.empty? if ARGV.include? "--full-name" - full_names = Formula.installed.map(&:full_name).sort &tap_and_name_comparison + full_names = Formula.installed.map(&:full_name).sort(&tap_and_name_comparison) return if full_names.empty? puts Formatter.columns(full_names) else @@ -87,7 +87,7 @@ module Homebrew dirs.delete "etc" dirs.delete "var" - args = dirs + %w[-type f (] + args = dirs.sort + %w[-type f (] args.concat UNBREWED_EXCLUDE_FILES.flat_map { |f| %W[! -name #{f}] } args.concat UNBREWED_EXCLUDE_PATHS.flat_map { |d| %W[! -path #{d}] } args.concat %w[)] diff --git a/Library/Homebrew/cmd/log.rb b/Library/Homebrew/cmd/log.rb index 9323c762d..898e921ba 100644 --- a/Library/Homebrew/cmd/log.rb +++ b/Library/Homebrew/cmd/log.rb @@ -31,7 +31,7 @@ module Homebrew end if File.exist? "#{repo}/.git/shallow" - opoo <<-EOS.undent + opoo <<~EOS #{name} is a shallow clone so only partial output will be shown. To get a full clone run: git -C "#{git_cd}" fetch --unshallow diff --git a/Library/Homebrew/cmd/missing.rb b/Library/Homebrew/cmd/missing.rb index 8a1dc506d..707ad6834 100644 --- a/Library/Homebrew/cmd/missing.rb +++ b/Library/Homebrew/cmd/missing.rb @@ -16,9 +16,9 @@ module Homebrew return unless HOMEBREW_CELLAR.exist? ff = if ARGV.named.empty? - Formula.installed + Formula.installed.sort else - ARGV.resolved_formulae + ARGV.resolved_formulae.sort end ff.each do |f| diff --git a/Library/Homebrew/cmd/options.rb b/Library/Homebrew/cmd/options.rb index 843d3a1ee..6bb6afafe 100644 --- a/Library/Homebrew/cmd/options.rb +++ b/Library/Homebrew/cmd/options.rb @@ -16,9 +16,9 @@ module Homebrew def options if ARGV.include? "--all" - puts_options Formula.to_a + puts_options Formula.to_a.sort elsif ARGV.include? "--installed" - puts_options Formula.installed + puts_options Formula.installed.sort else raise FormulaUnspecifiedError if ARGV.named.empty? puts_options ARGV.formulae diff --git a/Library/Homebrew/cmd/readall.rb b/Library/Homebrew/cmd/readall.rb index 3591e0c09..9fac52713 100644 --- a/Library/Homebrew/cmd/readall.rb +++ b/Library/Homebrew/cmd/readall.rb @@ -1,6 +1,7 @@ #: @hide_from_man_page #: * `readall` [tap]: -#: Import all formulae in a tap (defaults to core tap). +#: Import all formulae from specified taps (defaults to +#: all installed taps). #: #: This can be useful for debugging issues across all formulae #: when making significant changes to `formula.rb`, @@ -13,16 +14,8 @@ module Homebrew def readall if ARGV.include?("--syntax") - ruby_files = [] - scan_files = %W[ - #{HOMEBREW_LIBRARY}/*.rb - #{HOMEBREW_LIBRARY}/Homebrew/**/*.rb - ] - Dir.glob(scan_files).each do |rb| - next if rb.include?("/vendor/") - next if rb.include?("/cask/") - ruby_files << rb - end + scan_files = "#{HOMEBREW_LIBRARY_PATH}/**/*.rb" + ruby_files = Dir.glob(scan_files).reject { |file| file =~ %r{/(vendor|cask)/} } Homebrew.failed = true unless Readall.valid_ruby_syntax?(ruby_files) end @@ -31,7 +24,7 @@ module Homebrew taps = if ARGV.named.empty? Tap else - [Tap.fetch(ARGV.named.first)] + ARGV.named.map { |t| Tap.fetch(t) } end taps.each do |tap| Homebrew.failed = true unless Readall.valid_tap?(tap, options) diff --git a/Library/Homebrew/cmd/reinstall.rb b/Library/Homebrew/cmd/reinstall.rb index 94096d2dd..6727c0b6b 100644 --- a/Library/Homebrew/cmd/reinstall.rb +++ b/Library/Homebrew/cmd/reinstall.rb @@ -47,8 +47,8 @@ module Homebrew fi.install fi.finish rescue FormulaInstallationAlreadyAttemptedError - # next - rescue Exception + return + rescue Exception # rubocop:disable Lint/RescueException ignore_interrupts { restore_backup(keg, keg_was_linked) } raise else diff --git a/Library/Homebrew/cmd/search.rb b/Library/Homebrew/cmd/search.rb index c01a11c10..4ba5247f1 100644 --- a/Library/Homebrew/cmd/search.rb +++ b/Library/Homebrew/cmd/search.rb @@ -24,7 +24,7 @@ module Homebrew def search if ARGV.empty? - puts Formatter.columns(Formula.full_names) + puts Formatter.columns(Formula.full_names.sort) elsif ARGV.include? "--macports" exec_browser "https://www.macports.org/ports.php?by=name&substr=#{ARGV.next}" elsif ARGV.include? "--fink" @@ -52,15 +52,15 @@ module Homebrew results = search_taps(name) end - puts Formatter.columns(results) unless results.empty? + puts Formatter.columns(results.sort) unless results.empty? else query = ARGV.first regex = query_regexp(query) local_results = search_formulae(regex) - puts Formatter.columns(local_results) unless local_results.empty? + puts Formatter.columns(local_results.sort) unless local_results.empty? tap_results = search_taps(query) - puts Formatter.columns(tap_results) unless tap_results.empty? + puts Formatter.columns(tap_results.sort) unless tap_results.empty? if $stdout.tty? count = local_results.length + tap_results.length @@ -87,7 +87,7 @@ module Homebrew arg.include?(char) && !arg.start_with?("/") end end - ohai <<-EOS.undent + ohai <<~EOS Did you mean to perform a regular expression search? Surround your query with /slashes/ to search locally by regex. EOS diff --git a/Library/Homebrew/cmd/sh.rb b/Library/Homebrew/cmd/sh.rb index 69f329cb3..3fe5f3005 100644 --- a/Library/Homebrew/cmd/sh.rb +++ b/Library/Homebrew/cmd/sh.rb @@ -27,14 +27,14 @@ module Homebrew end ENV["PS1"] = 'brew \[\033[1;32m\]\w\[\033[0m\]$ ' ENV["VERBOSE"] = "1" - puts <<-EOS.undent_________________________________________________________72 - Your shell has been configured to use Homebrew's build environment; - this should help you build stuff. Notably though, the system versions of - gem and pip will ignore our configuration and insist on using the - environment they were built under (mostly). Sadly, scons will also - ignore our configuration. - When done, type `exit'. - EOS + puts <<~EOS + Your shell has been configured to use Homebrew's build environment; + this should help you build stuff. Notably though, the system versions of + gem and pip will ignore our configuration and insist on using the + environment they were built under (mostly). Sadly, scons will also + ignore our configuration. + When done, type `exit'. + EOS $stdout.flush exec ENV["SHELL"] end diff --git a/Library/Homebrew/cmd/style.rb b/Library/Homebrew/cmd/style.rb index e816db5dc..89484d67d 100644 --- a/Library/Homebrew/cmd/style.rb +++ b/Library/Homebrew/cmd/style.rb @@ -109,7 +109,7 @@ module Homebrew args << "--config" << HOMEBREW_LIBRARY_PATH/".rubocop.yml" args << HOMEBREW_LIBRARY_PATH else - args << "--config" << HOMEBREW_LIBRARY/".auditcops.yml" + args << "--config" << HOMEBREW_LIBRARY/".rubocop_audit.yml" args += files end @@ -117,6 +117,7 @@ module Homebrew case output_type when :print + args << "--debug" if ARGV.debug? args << "--display-cop-names" if ARGV.include? "--display-cop-names" args << "--format" << "simple" if files system(cache_env, "rubocop", "_#{HOMEBREW_RUBOCOP_VERSION}_", *args) diff --git a/Library/Homebrew/cmd/tap-info.rb b/Library/Homebrew/cmd/tap-info.rb index cb0e0b387..d01ce8a02 100644 --- a/Library/Homebrew/cmd/tap-info.rb +++ b/Library/Homebrew/cmd/tap-info.rb @@ -21,10 +21,11 @@ module Homebrew module_function def tap_info + # TODO: This still returns a non-alphabetised list on APFS. if ARGV.include? "--installed" taps = Tap else - taps = ARGV.named.map do |name| + taps = ARGV.named.sort.map do |name| Tap.fetch(name) end end diff --git a/Library/Homebrew/cmd/tap.rb b/Library/Homebrew/cmd/tap.rb index 2a07c1b2f..fa520e2c5 100644 --- a/Library/Homebrew/cmd/tap.rb +++ b/Library/Homebrew/cmd/tap.rb @@ -54,8 +54,7 @@ module Homebrew quiet: ARGV.quieter? rescue TapRemoteMismatchError => e odie e - rescue TapAlreadyTappedError, TapAlreadyUnshallowError - # Do nothing. + rescue TapAlreadyTappedError, TapAlreadyUnshallowError # rubocop:disable Lint/HandleExceptions end end end diff --git a/Library/Homebrew/cmd/uninstall.rb b/Library/Homebrew/cmd/uninstall.rb index 4839ba1e0..f95b6c7bb 100644 --- a/Library/Homebrew/cmd/uninstall.rb +++ b/Library/Homebrew/cmd/uninstall.rb @@ -131,7 +131,7 @@ module Homebrew class DeveloperDependentsMessage < DependentsMessage def output - opoo <<-EOS.undent + opoo <<~EOS #{list reqs} #{are_required_by_deps}. You can silence this warning with: #{sample_command} @@ -141,7 +141,7 @@ module Homebrew class NondeveloperDependentsMessage < DependentsMessage def output - ofail <<-EOS.undent + ofail <<~EOS Refusing to uninstall #{list reqs} because #{they reqs} #{are_required_by_deps}. You can override this and force removal with: diff --git a/Library/Homebrew/cmd/unlinkapps.rb b/Library/Homebrew/cmd/unlinkapps.rb index 56dba3603..7f401aaeb 100644 --- a/Library/Homebrew/cmd/unlinkapps.rb +++ b/Library/Homebrew/cmd/unlinkapps.rb @@ -20,7 +20,7 @@ module Homebrew module_function def unlinkapps - opoo <<-EOS.undent + opoo <<~EOS `brew unlinkapps` has been deprecated and will eventually be removed! Unfortunately `brew linkapps` cannot behave nicely with e.g. Spotlight using either aliases or symlinks and Homebrew formulae do not build "proper" `.app` bundles that can be relocated. Instead, please consider using `brew cask` and migrate formulae using `.app`s to casks. diff --git a/Library/Homebrew/cmd/update-report.rb b/Library/Homebrew/cmd/update-report.rb index 781ee8808..98823a152 100644 --- a/Library/Homebrew/cmd/update-report.rb +++ b/Library/Homebrew/cmd/update-report.rb @@ -33,7 +33,7 @@ module Homebrew # Use an extra newline and bold to avoid this being missed. ohai "Homebrew has enabled anonymous aggregate user behaviour analytics." - puts <<-EOS.undent + puts <<~EOS #{Tty.bold}Read the analytics documentation (and how to opt-out) here: #{Formatter.url("https://docs.brew.sh/Analytics.html")}#{Tty.reset} @@ -167,7 +167,7 @@ module Homebrew end if @migration_failed - opoo <<-EOS.undent + opoo <<~EOS Failed to migrate #{legacy_cache} to #{HOMEBREW_CACHE}. Please do so manually. EOS @@ -176,7 +176,7 @@ module Homebrew FileUtils.rm_rf legacy_cache if legacy_cache.exist? FileUtils.touch migration_attempted_file - opoo <<-EOS.undent + opoo <<~EOS Failed to delete #{legacy_cache}. Please do so manually. EOS @@ -191,7 +191,7 @@ module Homebrew ohai "Migrating HOMEBREW_REPOSITORY (please wait)..." unless HOMEBREW_PREFIX.writable_real? - ofail <<-EOS.undent + ofail <<~EOS #{HOMEBREW_PREFIX} is not writable. You should change the ownership and permissions of #{HOMEBREW_PREFIX} @@ -205,7 +205,7 @@ module Homebrew new_homebrew_repository = Pathname.new "/usr/local/Homebrew" new_homebrew_repository.rmdir_if_possible if new_homebrew_repository.exist? - ofail <<-EOS.undent + ofail <<~EOS #{new_homebrew_repository} already exists. Please remove it manually or uninstall and reinstall Homebrew into a new location as the migration cannot be done automatically. @@ -258,7 +258,7 @@ module Homebrew end unless unremovable_paths.empty? - ofail <<-EOS.undent + ofail <<~EOS Could not remove old HOMEBREW_REPOSITORY paths! Please do this manually with: sudo rm -rf #{unremovable_paths.join " "} @@ -274,7 +274,7 @@ module Homebrew begin FileUtils.ln_s(src.relative_path_from(dst.parent), dst) rescue Errno::EACCES, Errno::ENOENT - ofail <<-EOS.undent + ofail <<~EOS Could not create symlink at #{dst}! Please do this manually with: sudo ln -sf #{src} #{dst} @@ -285,13 +285,13 @@ module Homebrew link_completions_manpages_and_docs(new_homebrew_repository) ohai "Migrated HOMEBREW_REPOSITORY to #{new_homebrew_repository}!" - puts <<-EOS.undent + puts <<~EOS Homebrew no longer needs to have ownership of /usr/local. If you wish you can return /usr/local to its default ownership with: sudo chown root:wheel #{HOMEBREW_PREFIX} EOS rescue => e - ofail <<-EOS.undent + ofail <<~EOS #{Tty.bold}Failed to migrate HOMEBREW_REPOSITORY to #{new_homebrew_repository}!#{Tty.reset} The error was: #{e} @@ -309,7 +309,7 @@ module Homebrew Utils::Link.link_manpages(repository, command) Utils::Link.link_docs(repository, command) rescue => e - ofail <<-EOS.undent + ofail <<~EOS Failed to link all completions, docs and manpages: #{e} EOS @@ -372,7 +372,7 @@ class Reporter new_version = formula.pkg_version old_version = FormulaVersions.new(formula).formula_at_revision(@initial_revision, &:pkg_version) next if new_version == old_version - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException onoe "#{e.message}\n#{e.backtrace.join "\n"}" if ARGV.homebrew_developer? end @report[:M] << tap.formula_file_to_name(src) @@ -449,7 +449,7 @@ class Reporter next unless (HOMEBREW_PREFIX/"Caskroom"/new_name).exist? new_tap = Tap.fetch(new_tap_name) new_tap.install unless new_tap.installed? - ohai "#{name} has been moved to Homebrew.", <<-EOS.undent + ohai "#{name} has been moved to Homebrew.", <<~EOS To uninstall the cask run: brew cask uninstall --force #{name} EOS @@ -460,7 +460,7 @@ class Reporter unless Formulary.factory(new_full_name).keg_only? system HOMEBREW_BREW_FILE, "link", new_full_name, "--overwrite" end - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException onoe "#{e.message}\n#{e.backtrace.join "\n"}" if ARGV.homebrew_developer? end next @@ -480,14 +480,14 @@ class Reporter system HOMEBREW_BREW_FILE, "prune" ohai "brew cask install #{new_name}" system HOMEBREW_BREW_FILE, "cask", "install", new_name - ohai <<-EOS.undent + ohai <<~EOS #{name} has been moved to Homebrew-Cask. The existing keg has been unlinked. Please uninstall the formula when convenient by running: brew uninstall --force #{name} EOS else - ohai "#{name} has been moved to Homebrew-Cask.", <<-EOS.undent + ohai "#{name} has been moved to Homebrew-Cask.", <<~EOS To uninstall the formula and install the cask run: brew uninstall --force #{name} brew cask install #{new_name} @@ -521,7 +521,7 @@ class Reporter begin f = Formulary.factory(new_full_name) - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException onoe "#{e.message}\n#{e.backtrace.join "\n"}" if ARGV.homebrew_developer? next end @@ -598,7 +598,7 @@ class ReporterHub return if formulae.empty? # Dump formula list. ohai title - puts Formatter.columns(formulae) + puts Formatter.columns(formulae.sort) end def installed?(formula) diff --git a/Library/Homebrew/cmd/upgrade.rb b/Library/Homebrew/cmd/upgrade.rb index 1cdb497cf..de886ff3d 100644 --- a/Library/Homebrew/cmd/upgrade.rb +++ b/Library/Homebrew/cmd/upgrade.rb @@ -26,7 +26,7 @@ module Homebrew Homebrew.perform_preinstall_checks if ARGV.include?("--all") - opoo <<-EOS.undent + opoo <<~EOS We decided to not change the behaviour of `brew upgrade` so `brew upgrade --all` is equivalent to `brew upgrade` without any other arguments (so the `--all` is a no-op and can be removed). @@ -150,6 +150,7 @@ module Homebrew rescue FormulaInstallationAlreadyAttemptedError # We already attempted to upgrade f as part of the dependency tree of # another formula. In that case, don't generate an error, just move on. + return rescue CannotInstallFormulaError => e ofail e rescue BuildError => e diff --git a/Library/Homebrew/cmd/uses.rb b/Library/Homebrew/cmd/uses.rb index 24684c3b6..1688899f9 100644 --- a/Library/Homebrew/cmd/uses.rb +++ b/Library/Homebrew/cmd/uses.rb @@ -74,12 +74,13 @@ module Homebrew end end - dep_formulae = deps.map do |dep| + dep_formulae = deps.flat_map do |dep| begin dep.to_formula rescue + [] end - end.compact + end reqs_by_formula = ([f] + dep_formulae).flat_map do |formula| formula.requirements.map { |req| [formula, req] } @@ -118,12 +119,13 @@ module Homebrew rescue FormulaUnavailableError # Silently ignore this case as we don't care about things used in # taps that aren't currently tapped. + next end end end return if uses.empty? - puts Formatter.columns(uses.map(&:full_name)) + puts Formatter.columns(uses.map(&:full_name).sort) odie "Missing formulae should not have dependents!" if used_formulae_missing end end diff --git a/Library/Homebrew/cmd/vendor-install.sh b/Library/Homebrew/cmd/vendor-install.sh index 6d16a297d..15caca8ef 100644 --- a/Library/Homebrew/cmd/vendor-install.sh +++ b/Library/Homebrew/cmd/vendor-install.sh @@ -21,8 +21,8 @@ then fi elif [[ -n "$HOMEBREW_LINUX" ]] then - ruby_URL="https://homebrew.bintray.com/bottles-portable/portable-ruby-2.3.3.x86_64_linux.bottle.tar.gz" - ruby_SHA="543c18bd33a300e6c16671437b1e0f17b03bb64e6a485fc15ff7de1eb1a0bc2a" + ruby_URL="https://homebrew.bintray.com/bottles-portable/portable-ruby-2.3.3.x86_64_linux.bottle.1.tar.gz" + ruby_SHA="33643b1ca6f860d6df01686636326785763e5e81cf0cef37d8a7ab96a6ca1fa1" fi fetch() { @@ -81,9 +81,9 @@ fetch() { trap - SIGINT fi - if [[ -x "$(which shasum)" ]] + if [[ -x "/usr/bin/shasum" ]] then - sha="$(shasum -a 256 "$CACHED_LOCATION" | cut -d' ' -f1)" + sha="$(/usr/bin/shasum -a 256 "$CACHED_LOCATION" | cut -d' ' -f1)" elif [[ -x "$(which sha256sum)" ]] then sha="$(sha256sum "$CACHED_LOCATION" | cut -d' ' -f1)" diff --git a/Library/Homebrew/compat.rb b/Library/Homebrew/compat.rb index 3c080f616..8b3d72ec7 100644 --- a/Library/Homebrew/compat.rb +++ b/Library/Homebrew/compat.rb @@ -26,3 +26,4 @@ require "compat/ENV/shared" require "compat/ENV/std" require "compat/ENV/super" require "compat/utils/shell" +require "compat/extend/string" diff --git a/Library/Homebrew/compat/extend/string.rb b/Library/Homebrew/compat/extend/string.rb new file mode 100644 index 000000000..6069a6bec --- /dev/null +++ b/Library/Homebrew/compat/extend/string.rb @@ -0,0 +1,18 @@ +class String + def undent + gsub(/^[ \t]{#{(slice(/^[ \t]+/) || '').length}}/, "") + end + alias unindent undent + + # eg: + # if foo then <<-EOS.undent_________________________________________________________72 + # Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + # eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad + # minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip + # ex ea commodo consequat. Duis aute irure dolor in reprehenderit in + # voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + # sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt + # mollit anim id est laborum. + # EOS + alias undent_________________________________________________________72 undent +end diff --git a/Library/Homebrew/compat/formula.rb b/Library/Homebrew/compat/formula.rb index 853a38706..57ab84a76 100644 --- a/Library/Homebrew/compat/formula.rb +++ b/Library/Homebrew/compat/formula.rb @@ -78,4 +78,9 @@ class Formula def startup_plist odeprecated "Formula#startup_plist", "Formula#plist" end + + def rake(*args) + # odeprecated "FileUtils#rake", "system \"rake\"" + system "rake", *args + end end diff --git a/Library/Homebrew/compat/formula_specialties.rb b/Library/Homebrew/compat/formula_specialties.rb index 78966625e..3f8102575 100644 --- a/Library/Homebrew/compat/formula_specialties.rb +++ b/Library/Homebrew/compat/formula_specialties.rb @@ -31,7 +31,7 @@ class AmazonWebServicesFormula < Formula def standard_instructions(home_name, home_value = libexec) odeprecated "AmazonWebServicesFormula#standard_instructions", "Formula#caveats" - <<-EOS.undent + <<~EOS Before you can use these tools you must export some variables to your $SHELL. To export the needed variables, add them to your dotfiles. diff --git a/Library/Homebrew/compat/hbc/cli.rb b/Library/Homebrew/compat/hbc/cli.rb index 0173bce9c..60d298ed6 100644 --- a/Library/Homebrew/compat/hbc/cli.rb +++ b/Library/Homebrew/compat/hbc/cli.rb @@ -5,7 +5,7 @@ module Hbc include Options option "--binarydir=PATH", (lambda do |*| - opoo <<-EOS.undent + opoo <<~EOS Option --binarydir is obsolete! Homebrew-Cask now uses the same location as your Homebrew installation for executable links. EOS diff --git a/Library/Homebrew/compat/requirements.rb b/Library/Homebrew/compat/requirements.rb index 77760d1dc..3886cd7c7 100644 --- a/Library/Homebrew/compat/requirements.rb +++ b/Library/Homebrew/compat/requirements.rb @@ -17,3 +17,4 @@ PythonDependency = PythonRequirement TuntapDependency = TuntapRequirement X11Dependency = X11Requirement ConflictsWithBinaryOsxfuse = NonBinaryOsxfuseRequirement +MinimumMacOSRequirement = MacOSRequirement diff --git a/Library/Homebrew/constants.rb b/Library/Homebrew/constants.rb index b122946c8..956548640 100644 --- a/Library/Homebrew/constants.rb +++ b/Library/Homebrew/constants.rb @@ -2,4 +2,4 @@ # RuboCop version used for `brew style` and `brew cask style` HOMEBREW_RUBOCOP_VERSION = "0.50.0" -HOMEBREW_RUBOCOP_CASK_VERSION = "~> 0.14.2" # has to be updated when RuboCop version changes +HOMEBREW_RUBOCOP_CASK_VERSION = "~> 0.14.4" # has to be updated when RuboCop version changes diff --git a/Library/Homebrew/cxxstdlib.rb b/Library/Homebrew/cxxstdlib.rb index 8a67a9c53..7a833c92c 100644 --- a/Library/Homebrew/cxxstdlib.rb +++ b/Library/Homebrew/cxxstdlib.rb @@ -5,7 +5,7 @@ class CxxStdlib class CompatibilityError < StandardError def initialize(formula, dep, stdlib) - super <<-EOS.undent + super <<~EOS #{formula.full_name} dependency #{dep.name} was built with a different C++ standard library (#{stdlib.type_string} from #{stdlib.compiler}). This may cause problems at runtime. EOS diff --git a/Library/Homebrew/debrew.rb b/Library/Homebrew/debrew.rb index 5bc3d2daa..6206eb8a2 100644 --- a/Library/Homebrew/debrew.rb +++ b/Library/Homebrew/debrew.rb @@ -9,7 +9,7 @@ module Debrew module Raise def raise(*) super - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException e.extend(Ignorable) super(e) unless Debrew.debug(e) == :ignore end @@ -92,7 +92,7 @@ module Debrew yield rescue SystemExit original_raise - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException debug(e) ensure @active = false @@ -119,7 +119,7 @@ module Debrew if e.is_a?(Ignorable) menu.choice(:irb) do puts "When you exit this IRB session, execution will continue." - set_trace_func proc { |event, _, _, id, binding, klass| + set_trace_func proc { |event, _, _, id, binding, klass| # rubocop:disable Metrics/ParameterLists if klass == Raise && id == :raise && event == "return" set_trace_func(nil) synchronize { IRB.start_within(binding) } diff --git a/Library/Homebrew/debrew/irb.rb b/Library/Homebrew/debrew/irb.rb index 069dbe676..eeb3758a9 100644 --- a/Library/Homebrew/debrew/irb.rb +++ b/Library/Homebrew/debrew/irb.rb @@ -4,8 +4,7 @@ module IRB @setup_done = false extend Module.new { - def parse_opts - end + def parse_opts; end def start_within(binding) unless @setup_done diff --git a/Library/Homebrew/dependency.rb b/Library/Homebrew/dependency.rb index 0fbc2625b..7f0e7fbff 100644 --- a/Library/Homebrew/dependency.rb +++ b/Library/Homebrew/dependency.rb @@ -64,7 +64,7 @@ class Dependency end def self._load(marshaled) - new(*Marshal.load(marshaled)) + new(*Marshal.load(marshaled)) # rubocop:disable Security/MarshalLoad end class << self diff --git a/Library/Homebrew/dependency_collector.rb b/Library/Homebrew/dependency_collector.rb index fff80a28c..bc0246dd2 100644 --- a/Library/Homebrew/dependency_collector.rb +++ b/Library/Homebrew/dependency_collector.rb @@ -4,6 +4,7 @@ require "ld64_dependency" require "requirement" require "requirements" require "set" +require "extend/cachable" ## A dependency is a formula that another formula needs to install. ## A requirement is something other than a formula that another formula @@ -16,17 +17,13 @@ require "set" # This class is used by `depends_on` in the formula DSL to turn dependency # specifications into the proper kinds of dependencies and requirements. class DependencyCollector + extend Cachable + # Define the languages that we can handle as external dependencies. LANGUAGE_MODULES = Set[ :lua, :lua51, :perl, :python, :python3, :ruby ].freeze - CACHE = {} - - def self.clear_cache - CACHE.clear - end - attr_reader :deps, :requirements def initialize @@ -45,7 +42,7 @@ class DependencyCollector end def fetch(spec) - CACHE.fetch(cache_key(spec)) { |key| CACHE[key] = build(spec) } + self.class.cache.fetch(cache_key(spec)) { |key| self.class.cache[key] = build(spec) } end def cache_key(spec) @@ -108,7 +105,8 @@ class DependencyCollector case spec when :x11 then X11Requirement.new(spec.to_s, tags) when :xcode then XcodeRequirement.new(tags) - when :macos then MinimumMacOSRequirement.new(tags) + when :linux then LinuxRequirement.new(tags) + when :macos then MacOSRequirement.new(tags) when :mysql then MysqlRequirement.new(tags) when :postgresql then PostgresqlRequirement.new(tags) when :gpg then GPG2Requirement.new(tags) diff --git a/Library/Homebrew/descriptions.rb b/Library/Homebrew/descriptions.rb index ac1d68216..bc1982673 100644 --- a/Library/Homebrew/descriptions.rb +++ b/Library/Homebrew/descriptions.rb @@ -78,10 +78,10 @@ class Descriptions formula_names.each do |name| begin - desc = Formulary.factory(name).desc + @cache[name] = Formulary.factory(name).desc rescue FormulaUnavailableError, *FormulaVersions::IGNORED_EXCEPTIONS + @cache.delete(name) end - @cache[name] = desc end save_cache if options[:save] end diff --git a/Library/Homebrew/dev-cmd/aspell-dictionaries.rb b/Library/Homebrew/dev-cmd/aspell-dictionaries.rb index 955e41b01..ab0e66d2b 100644 --- a/Library/Homebrew/dev-cmd/aspell-dictionaries.rb +++ b/Library/Homebrew/dev-cmd/aspell-dictionaries.rb @@ -27,13 +27,12 @@ module Homebrew end end - languages.inject([]) do |resources, (lang, path)| + languages.each do |lang, path| r = Resource.new(lang) r.owner = Formulary.factory("aspell") r.url "#{dict_url}/#{path}" r.mirror "#{dict_mirror}/#{path}" - resources << r - end.each(&:fetch).each do |r| + r.fetch puts <<-EOS option "with-lang-#{r.name}", "Install #{r.name} dictionary" resource "#{r.name}" do diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index 16ae7cba1..bfe4dbc00 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -53,7 +53,7 @@ module Homebrew module_function def audit - Homebrew.inject_dump_stats!(FormulaAuditor, /^audit_/) if ARGV.switch? "D" + inject_dump_stats!(FormulaAuditor, /^audit_/) if ARGV.switch? "D" Homebrew.auditing = true formula_count = 0 @@ -368,7 +368,7 @@ class FormulaAuditor if valid_versioned_aliases.empty? if formula.tap - problem <<-EOS.undent + problem <<~EOS Formula has other versions so create a versioned alias: cd #{formula.tap.alias_dir} ln -s #{formula.path.to_s.gsub(formula.tap.path, "..")} #{alias_name} @@ -379,7 +379,7 @@ class FormulaAuditor end unless invalid_versioned_aliases.empty? - problem <<-EOS.undent + problem <<~EOS Formula has invalid versioned aliases: #{invalid_versioned_aliases.join("\n ")} EOS @@ -387,8 +387,10 @@ class FormulaAuditor end end - # core aliases + tap alias names + tap alias full name - @@aliases ||= Formula.aliases + Formula.tap_aliases + def self.aliases + # core aliases + tap alias names + tap alias full name + @aliases ||= Formula.aliases + Formula.tap_aliases + end def audit_formula_name return unless @strict @@ -442,7 +444,7 @@ class FormulaAuditor problem "Dependency '#{dep.name}' was renamed; use new name '#{dep_f.name}'." end - if @@aliases.include?(dep.name) && + if self.class.aliases.include?(dep.name) && (dep_f.core_formula? || !dep_f.versioned_formula?) problem "Dependency '#{dep.name}' is an alias; use the canonical name '#{dep.to_formula.full_name}'." end @@ -453,16 +455,16 @@ class FormulaAuditor problem "Dependency '#{dep.name}' may be unnecessary as it is provided by macOS; try to build this formula without it." end - dep.options.reject do |opt| - next true if dep_f.option_defined?(opt) - dep_f.requirements.detect do |r| + dep.options.each do |opt| + next if dep_f.option_defined?(opt) + next if dep_f.requirements.detect do |r| if r.recommended? opt.name == "with-#{r.name}" elsif r.optional? opt.name == "without-#{r.name}" end end - end.each do |opt| + problem "Dependency #{dep} does not define option #{opt.name.inspect}" end @@ -474,7 +476,7 @@ class FormulaAuditor when "gfortran" problem "Use `depends_on :fortran` instead of `depends_on 'gfortran'`" when "ruby" - problem <<-EOS.undent + problem <<~EOS Don't use "ruby" as a dependency. If this formula requires a minimum Ruby version not provided by the system you should use the RubyRequirement: @@ -482,7 +484,7 @@ class FormulaAuditor where "1.8" is the minimum version of Ruby required. EOS when "open-mpi", "mpich" - problem <<-EOS.undent + problem <<~EOS There are multiple conflicting ways to install MPI. Use an MPIRequirement: depends_on :mpi => [<lang list>] Where <lang list> is a comma delimited list that can include: @@ -490,7 +492,7 @@ class FormulaAuditor EOS when *BUILD_TIME_DEPS next if dep.build? || dep.run? - problem <<-EOS.undent + problem <<~EOS #{dep} dependency should be depends_on "#{dep}" => :build Or if it is indeed a runtime dependency @@ -539,7 +541,7 @@ class FormulaAuditor first_word = reason.split[0] if reason =~ /\A[A-Z]/ && !reason.start_with?(*whitelist) - problem <<-EOS.undent + problem <<~EOS '#{first_word}' from the keg_only reason should be '#{first_word.downcase}'. EOS end @@ -590,7 +592,8 @@ class FormulaAuditor return if metadata.nil? problem "GitHub fork (not canonical repository)" if metadata["fork"] - if (metadata["forks_count"] < 20) && (metadata["subscribers_count"] < 20) && + if formula&.tap&.core_tap? && + (metadata["forks_count"] < 20) && (metadata["subscribers_count"] < 20) && (metadata["stargazers_count"] < 50) problem "GitHub repository not notable enough (<20 forks, <20 watchers and <50 stars)" end @@ -817,164 +820,12 @@ class FormulaAuditor problem "\"(#{Regexp.last_match(1)}...#{Regexp.last_match(2)})\" should be \"(#{Regexp.last_match(3).downcase}+...)\"" end - if line =~ /((man)\s*\+\s*(['"])(man[1-8])(['"]))/ - problem "\"#{Regexp.last_match(1)}\" should be \"#{Regexp.last_match(4)}\"" - end - - # Prefer formula path shortcuts in strings - if line =~ %r[(\#\{prefix\}/(bin|include|libexec|lib|sbin|share|Frameworks))] - problem "\"#{Regexp.last_match(1)}\" should be \"\#{#{Regexp.last_match(2).downcase}}\"" - end - - if line =~ %r[((\#\{prefix\}/share/man/|\#\{man\}/)(man[1-8]))] - problem "\"#{Regexp.last_match(1)}\" should be \"\#{#{Regexp.last_match(3)}}\"" - end - - if line =~ %r[((\#\{share\}/(man)))[/'"]] - problem "\"#{Regexp.last_match(1)}\" should be \"\#{#{Regexp.last_match(3)}}\"" - end - - if line =~ %r[(\#\{prefix\}/share/(info|man))] - problem "\"#{Regexp.last_match(1)}\" should be \"\#{#{Regexp.last_match(2)}}\"" - end - - if line =~ /depends_on\s+['"](.+)['"]\s+=>\s+:(lua|perl|python|ruby)(\d*)/ - problem "#{Regexp.last_match(2)} modules should be vendored rather than use deprecated `depends_on \"#{Regexp.last_match(1)}\" => :#{Regexp.last_match(2)}#{Regexp.last_match(3)}`" - end - - if line =~ /depends_on\s+['"](.+)['"]\s+=>\s+(.*)/ - dep = Regexp.last_match(1) - Regexp.last_match(2).split(" ").map do |o| - break if ["if", "unless"].include?(o) - next unless o =~ /^\[?['"](.*)['"]/ - problem "Dependency #{dep} should not use option #{Regexp.last_match(1)}" - end - end - - if line =~ /if\s+ARGV\.include\?\s+'--(HEAD|devel)'/ - problem "Use \"if build.#{Regexp.last_match(1).downcase}?\" instead" - end - problem "Use separate make calls" if line.include?("make && make") - problem "Use spaces instead of tabs for indentation" if line =~ /^[ ]*\t/ - - if line.include?("ENV.java_cache") - problem "In-formula ENV.java_cache usage has been deprecated & should be removed." - end - - # Avoid hard-coding compilers - if line =~ %r{(system|ENV\[.+\]\s?=)\s?['"](/usr/bin/)?(gcc|llvm-gcc|clang)['" ]} - problem "Use \"\#{ENV.cc}\" instead of hard-coding \"#{Regexp.last_match(3)}\"" - end - - if line =~ %r{(system|ENV\[.+\]\s?=)\s?['"](/usr/bin/)?((g|llvm-g|clang)\+\+)['" ]} - problem "Use \"\#{ENV.cxx}\" instead of hard-coding \"#{Regexp.last_match(3)}\"" - end - - if line =~ /system\s+['"](env|export)(\s+|['"])/ - problem "Use ENV instead of invoking '#{Regexp.last_match(1)}' to modify the environment" - end - - if line =~ /version == ['"]HEAD['"]/ - problem "Use 'build.head?' instead of inspecting 'version'" - end - - if line =~ /build\.include\?[\s\(]+['"]\-\-(.*)['"]/ - problem "Reference '#{Regexp.last_match(1)}' without dashes" - end - - if line =~ /build\.include\?[\s\(]+['"]with(out)?-(.*)['"]/ - problem "Use build.with#{Regexp.last_match(1)}? \"#{Regexp.last_match(2)}\" instead of build.include? 'with#{Regexp.last_match(1)}-#{Regexp.last_match(2)}'" - end - - if line =~ /build\.with\?[\s\(]+['"]-?-?with-(.*)['"]/ - problem "Don't duplicate 'with': Use `build.with? \"#{Regexp.last_match(1)}\"` to check for \"--with-#{Regexp.last_match(1)}\"" - end - - if line =~ /build\.without\?[\s\(]+['"]-?-?without-(.*)['"]/ - problem "Don't duplicate 'without': Use `build.without? \"#{Regexp.last_match(1)}\"` to check for \"--without-#{Regexp.last_match(1)}\"" - end - - if line =~ /unless build\.with\?(.*)/ - problem "Use if build.without?#{Regexp.last_match(1)} instead of unless build.with?#{Regexp.last_match(1)}" - end - - if line =~ /unless build\.without\?(.*)/ - problem "Use if build.with?#{Regexp.last_match(1)} instead of unless build.without?#{Regexp.last_match(1)}" - end - - if line =~ /(not\s|!)\s*build\.with?\?/ - problem "Don't negate 'build.with?': use 'build.without?'" - end - - if line =~ /(not\s|!)\s*build\.without?\?/ - problem "Don't negate 'build.without?': use 'build.with?'" - end - - if line =~ /ARGV\.(?!(debug\?|verbose\?|value[\(\s]))/ - problem "Use build instead of ARGV to check options" - end - - if line.include?("MACOS_VERSION") - problem "Use MacOS.version instead of MACOS_VERSION" - end - - if line.include?("MACOS_FULL_VERSION") - problem "Use MacOS.full_version instead of MACOS_FULL_VERSION" - end - - cats = %w[leopard snow_leopard lion mountain_lion].join("|") - if line =~ /MacOS\.(?:#{cats})\?/ - problem "\"#{$&}\" is deprecated, use a comparison to MacOS.version instead" - end - - if line =~ /depends_on [A-Z][\w:]+\.new$/ - problem "`depends_on` can take requirement classes instead of instances" - end - - if line =~ /^def (\w+).*$/ - problem "Define method #{Regexp.last_match(1).inspect} in the class body, not at the top-level" - end - - if line.include?("ENV.fortran") && !formula.requirements.map(&:class).include?(FortranRequirement) - problem "Use `depends_on :fortran` instead of `ENV.fortran`" - end - if line =~ /JAVA_HOME/i && !formula.requirements.map(&:class).include?(JavaRequirement) problem "Use `depends_on :java` to set JAVA_HOME" end - if line =~ /depends_on :(.+) (if.+|unless.+)$/ - conditional_dep_problems(Regexp.last_match(1).to_sym, Regexp.last_match(2), $&) - end - - if line =~ /depends_on ['"](.+)['"] (if.+|unless.+)$/ - conditional_dep_problems(Regexp.last_match(1), Regexp.last_match(2), $&) - end - - if line =~ /(Dir\[("[^\*{},]+")\])/ - problem "#{Regexp.last_match(1)} is unnecessary; just use #{Regexp.last_match(2)}" - end - - if line =~ /system (["'](#{FILEUTILS_METHODS})["' ])/o - system = Regexp.last_match(1) - method = Regexp.last_match(2) - problem "Use the `#{method}` Ruby method instead of `system #{system}`" - end - - if line =~ /assert [^!]+\.include?/ - problem "Use `assert_match` instead of `assert ...include?`" - end - - if line =~ /(assert File\.exist\?|assert \(.*\)\.exist\?)/ - problem "Use `assert_predicate <path_to_file>, :exist?` instead of `#{Regexp.last_match(1)}`" - end - - if line =~ /assert !File\.exist\?/ - problem "Use `refute_predicate <path_to_file>, :exist?` instead of `assert !File.exist?`" - end - return unless @strict problem "`#{Regexp.last_match(1)}` in formulae is deprecated" if line =~ /(env :(std|userpaths))/ @@ -1003,7 +854,7 @@ class FormulaAuditor return unless formula.tap&.official? return unless formula.tap.tap_migrations.key?(formula.name) - problem <<-EOS.undent + problem <<~EOS #{formula.name} seems to be listed in tap_migrations.json! Please remove #{formula.name} from present tap & tap_migrations.json before submitting it to Homebrew/homebrew-#{formula.tap.repo}. @@ -1014,25 +865,13 @@ class FormulaAuditor return unless formula.prefix.directory? return unless Keg.new(formula.prefix).empty_installation? - problem <<-EOS.undent + problem <<~EOS The installation seems to be empty. Please ensure the prefix is set correctly and expected files are installed. The prefix configure/make argument may be case-sensitive. EOS end - def conditional_dep_problems(dep, condition, line) - quoted_dep = quote_dep(dep) - dep = Regexp.escape(dep.to_s) - - case condition - when /if build\.include\? ['"]with-#{dep}['"]$/, /if build\.with\? ['"]#{dep}['"]$/ - problem %Q(Replace #{line.inspect} with "depends_on #{quoted_dep} => :optional") - when /unless build\.include\? ['"]without-#{dep}['"]$/, /unless build\.without\? ['"]#{dep}['"]$/ - problem %Q(Replace #{line.inspect} with "depends_on #{quoted_dep} => :recommended") - end - end - def quote_dep(dep) dep.is_a?(Symbol) ? dep.inspect : "'#{dep}'" end diff --git a/Library/Homebrew/dev-cmd/bottle.rb b/Library/Homebrew/dev-cmd/bottle.rb index 8dfd0d12c..a54211f5c 100644 --- a/Library/Homebrew/dev-cmd/bottle.rb +++ b/Library/Homebrew/dev-cmd/bottle.rb @@ -75,7 +75,7 @@ module Homebrew @put_filenames ||= [] - return if @put_filenames.include? filename + return if @put_filenames.include?(filename) puts Formatter.error(filename.to_s) @put_filenames << filename @@ -84,8 +84,7 @@ module Homebrew result = false keg.each_unique_file_matching(string) do |file| - # skip document file. - next if Metafiles::EXTENSIONS.include? file.extname + next if Metafiles::EXTENSIONS.include?(file.extname) # Skip document files. linked_libraries = Keg.file_linked_libraries(file, string) result ||= !linked_libraries.empty? @@ -156,9 +155,7 @@ module Homebrew return ofail "Formula not installed or up-to-date: #{f.full_name}" end - tap = f.tap - - unless tap + unless tap = f.tap unless ARGV.include?("--force-core-tap") return ofail "Formula not from core or any taps: #{f.full_name}" end @@ -327,7 +324,7 @@ module Homebrew "#{key}: old: #{old_value}, new: #{value}" end - odie <<-EOS.undent + odie <<~EOS --keep-old was passed but there are changes in: #{mismatches.join("\n")} EOS @@ -431,7 +428,7 @@ module Homebrew end unless mismatches.empty? - odie <<-EOS.undent + odie <<~EOS --keep-old was passed but there are changes in: #{mismatches.join("\n")} EOS diff --git a/Library/Homebrew/dev-cmd/bump-formula-pr.rb b/Library/Homebrew/dev-cmd/bump-formula-pr.rb index 87d8274cc..fe7e6be3d 100644 --- a/Library/Homebrew/dev-cmd/bump-formula-pr.rb +++ b/Library/Homebrew/dev-cmd/bump-formula-pr.rb @@ -91,7 +91,7 @@ module Homebrew pull_requests = fetch_pull_requests(formula) return unless pull_requests return if pull_requests.empty? - duplicates_message = <<-EOS.undent + duplicates_message = <<~EOS These open pull requests may be duplicates: #{pull_requests.map { |pr| "#{pr["title"]} #{pr["html_url"]}" }.join("\n")} EOS @@ -101,7 +101,7 @@ module Homebrew elsif !ARGV.force? && ARGV.flag?("--quiet") odie error_message elsif !ARGV.force? - odie <<-EOS.undent + odie <<~EOS #{duplicates_message.chomp} #{error_message} EOS @@ -247,13 +247,13 @@ module Homebrew if new_formula_version < old_formula_version formula.path.atomic_write(backup_file) unless ARGV.dry_run? - odie <<-EOS.undent + odie <<~EOS You probably need to bump this formula manually since changing the version from #{old_formula_version} to #{new_formula_version} would be a downgrade. EOS elsif new_formula_version == old_formula_version formula.path.atomic_write(backup_file) unless ARGV.dry_run? - odie <<-EOS.undent + odie <<~EOS You probably need to bump this formula manually since the new version and old version are both #{new_formula_version}. EOS @@ -312,17 +312,15 @@ module Homebrew remote = Utils.popen_read("hub fork 2>&1")[/remote:? (\S+)/, 1] if remote.to_s.empty? odie "cannot get remote from 'hub'!" if remote.to_s.empty? safe_system "git", "push", "--set-upstream", remote, "#{branch}:#{branch}" - pr_message = <<-EOS.undent + pr_message = <<~EOS #{formula.name} #{new_formula_version}#{devel_message} Created with `brew bump-formula-pr`. EOS user_message = ARGV.value("message") if user_message - pr_message += <<-EOS.undent - + pr_message += <<~EOS --- - #{user_message} EOS end diff --git a/Library/Homebrew/dev-cmd/create.rb b/Library/Homebrew/dev-cmd/create.rb index e423842ba..e5481b532 100644 --- a/Library/Homebrew/dev-cmd/create.rb +++ b/Library/Homebrew/dev-cmd/create.rb @@ -71,7 +71,7 @@ module Homebrew if Formula.aliases.include? fc.name realname = Formulary.canonical_name(fc.name) - raise <<-EOS.undent + raise <<~EOS The formula #{realname} is already aliased to #{fc.name} Please check that you are not creating a duplicate. To force creation use --force. @@ -165,7 +165,7 @@ class FormulaCreator path.write ERB.new(template, nil, ">").result(binding) end - def template; <<-EOS.undent + def template; <<~EOS # Documentation: https://docs.brew.sh/Formula-Cookbook.html # http://www.rubydoc.info/github/Homebrew/brew/master/Formula # PLEASE REMOVE ALL GENERATED COMMENTS BEFORE SUBMITTING YOUR PULL REQUEST! diff --git a/Library/Homebrew/dev-cmd/edit.rb b/Library/Homebrew/dev-cmd/edit.rb index b1e485fe2..0039b4cce 100644 --- a/Library/Homebrew/dev-cmd/edit.rb +++ b/Library/Homebrew/dev-cmd/edit.rb @@ -11,7 +11,7 @@ module Homebrew def edit unless (HOMEBREW_REPOSITORY/".git").directory? - raise <<-EOS.undent + raise <<~EOS Changes will be lost! The first time you `brew update', all local changes will be lost, you should thus `brew update' before you `brew edit'! diff --git a/Library/Homebrew/dev-cmd/man.rb b/Library/Homebrew/dev-cmd/man.rb index 472bb7c2b..b2bb3c8c3 100644 --- a/Library/Homebrew/dev-cmd/man.rb +++ b/Library/Homebrew/dev-cmd/man.rb @@ -48,12 +48,9 @@ module Homebrew def path_glob_commands(glob) Pathname.glob(glob) .sort_by { |source_file| sort_key_for_path(source_file) } - .map do |source_file| - source_file.read.lines - .grep(/^#:/) - .map { |line| line.slice(2..-1) } - .join - end.reject { |s| s.strip.empty? || s.include?("@hide_from_man_page") } + .map(&:read).map(&:lines) + .map { |lines| lines.grep(/^#:/).map { |line| line.slice(2..-1) }.join } + .reject { |s| s.strip.empty? || s.include?("@hide_from_man_page") } end def build_man_page diff --git a/Library/Homebrew/dev-cmd/mirror.rb b/Library/Homebrew/dev-cmd/mirror.rb index 6445bc34c..bf19ee3c5 100644 --- a/Library/Homebrew/dev-cmd/mirror.rb +++ b/Library/Homebrew/dev-cmd/mirror.rb @@ -20,7 +20,7 @@ module Homebrew package_url = "#{bintray_repo_url}/#{bintray_package}" unless system "curl", "--silent", "--fail", "--output", "/dev/null", package_url - package_blob = <<-EOS.undent + package_blob = <<~EOS {"name": "#{bintray_package}", "public_download_numbers": true, "public_stats": true} diff --git a/Library/Homebrew/dev-cmd/pull.rb b/Library/Homebrew/dev-cmd/pull.rb index cd0d6fbd0..7746e4db3 100644 --- a/Library/Homebrew/dev-cmd/pull.rb +++ b/Library/Homebrew/dev-cmd/pull.rb @@ -1,4 +1,4 @@ -#: * `pull` [`--bottle`] [`--bump`] [`--clean`] [`--ignore-whitespace`] [`--resolve`] [`--branch-okay`] [`--no-pbcopy`] [`--no-publish`] [`--warn-on-publish-failure`] <patch-source> [<patch-source>]: +#: * `pull` [`--bottle`] [`--bump`] [`--clean`] [`--ignore-whitespace`] [`--resolve`] [`--branch-okay`] [`--no-pbcopy`] [`--no-publish`] [`--warn-on-publish-failure`] [`--bintray-org=`<bintray-org>] [`--test-bot-user=`<test-bot-user>] <patch-source> [<patch-source>]: #: #: Gets a patch from a GitHub commit or pull request and applies it to Homebrew. #: Optionally, installs the formulae changed by the patch. @@ -41,6 +41,12 @@ #: #: If `--warn-on-publish-failure` was passed, do not exit if there's a #: failure publishing bottles on Bintray. +#: +#: If `--bintray-org=`<bintray-org> is passed, publish at the given Bintray +#: organisation. +#: +#: If `--test-bot-user=`<test-bot-user> is passed, pull the bottle block +#: commit from the specified user on GitHub. require "net/http" require "net/https" @@ -52,6 +58,18 @@ require "tap" require "version" require "pkg_version" +module GitHub + module_function + + # Return the corresponding test-bot user name for the given GitHub organization. + def test_bot_user(user) + test_bot = ARGV.value "test-bot-user" + return test_bot if test_bot + return "BrewTestBot" if user.casecmp("homebrew").zero? + "#{user.capitalize}TestBot" + end +end + module Homebrew module_function @@ -69,11 +87,8 @@ module Homebrew tap = nil ARGV.named.each do |arg| - if arg.to_i.positive? - issue = arg - url = "https://github.com/Homebrew/homebrew-core/pull/#{arg}" - tap = CoreTap.instance - elsif (testing_match = arg.match %r{/job/Homebrew.*Testing/(\d+)/}) + arg = "#{CoreTap.instance.default_remote}/pull/#{arg}" if arg.to_i.positive? + if (testing_match = arg.match %r{/job/Homebrew.*Testing/(\d+)/}) tap = ARGV.value("tap") tap = if tap&.start_with?("homebrew/") Tap.fetch("homebrew", tap.strip_prefix("homebrew/")) @@ -154,8 +169,8 @@ module Homebrew begin f = Formula[name] - # Make sure we catch syntax errors. - rescue Exception + rescue Exception # rubocop:disable Lint/RescueException + # Make sure we catch syntax errors. next end @@ -225,7 +240,7 @@ module Homebrew url else bottle_branch = "pull-bottle-#{issue}" - "https://github.com/BrewTestBot/homebrew-#{tap.repo}/compare/homebrew:master...pr-#{issue}" + "https://github.com/#{GitHub.test_bot_user user}/homebrew-#{tap.repo}/compare/#{user}:master...pr-#{issue}" end curl "--silent", "--fail", "--output", "/dev/null", "--head", bottle_commit_url @@ -257,7 +272,7 @@ module Homebrew str.force_encoding("UTF-8") if str.respond_to?(:force_encoding) end - def publish_changed_formula_bottles(_tap, changed_formulae_names) + def publish_changed_formula_bottles(tap, changed_formulae_names) if ENV["HOMEBREW_DISABLE_LOAD_FORMULA"] raise "Need to load formulae to publish them!" end @@ -268,7 +283,8 @@ module Homebrew changed_formulae_names.each do |name| f = Formula[name] next if f.bottle_unneeded? || f.bottle_disabled? - next unless publish_bottle_file_on_bintray(f, bintray_creds) + bintray_org = ARGV.value("bintray-org") || tap.user.downcase + next unless publish_bottle_file_on_bintray(f, bintray_org, bintray_creds) published << f.full_name end else @@ -420,7 +436,7 @@ module Homebrew end # Publishes the current bottle files for a given formula to Bintray - def publish_bottle_file_on_bintray(f, creds) + def publish_bottle_file_on_bintray(f, bintray_org, creds) repo = Utils::Bottles::Bintray.repository(f.tap) package = Utils::Bottles::Bintray.package(f.name) info = FormulaInfoFromJson.lookup(f.name) @@ -437,7 +453,7 @@ module Homebrew "--user", "#{creds[:user]}:#{creds[:key]}", "--request", "POST", "--header", "Content-Type: application/json", "--data", '{"publish_wait_for_secs": 0}', - "https://api.bintray.com/content/homebrew/#{repo}/#{package}/#{version}/publish" + "https://api.bintray.com/content/#{bintray_org}/#{repo}/#{package}/#{version}/publish" true rescue => e raise unless ARGV.include?("--warn-on-publish-failure") @@ -560,7 +576,7 @@ module Homebrew req = Net::HTTP::Head.new bottle_info.url req.initialize_http_header "User-Agent" => HOMEBREW_USER_AGENT_RUBY res = http.request req - break if res.is_a?(Net::HTTPSuccess) + break if res.is_a?(Net::HTTPSuccess) || res.code == "302" unless res.is_a?(Net::HTTPClientError) raise "Failed to find published #{f} bottle at #{url} (#{res.code} #{res.message})!" diff --git a/Library/Homebrew/dev-cmd/tap-new.rb b/Library/Homebrew/dev-cmd/tap-new.rb index 964ba2f5d..1c3bf20eb 100644 --- a/Library/Homebrew/dev-cmd/tap-new.rb +++ b/Library/Homebrew/dev-cmd/tap-new.rb @@ -24,7 +24,7 @@ module Homebrew (tap.path/"Formula").mkpath - readme = <<-EOS.undent + readme = <<~EOS # #{titleized_user} #{titleized_repo} ## How do I install these formulae? @@ -43,7 +43,7 @@ module Homebrew EOS write_path(tap, "README.md", readme) - travis = <<-EOS.undent + travis = <<~EOS language: ruby os: osx env: OSX=10.12 diff --git a/Library/Homebrew/dev-cmd/test.rb b/Library/Homebrew/dev-cmd/test.rb index ab2b0edb0..6622a8c25 100644 --- a/Library/Homebrew/dev-cmd/test.rb +++ b/Library/Homebrew/dev-cmd/test.rb @@ -84,7 +84,7 @@ module Homebrew rescue ::Test::Unit::AssertionFailedError => e ofail "#{f.full_name}: failed" puts e.message - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException ofail "#{f.full_name}: failed" puts e, e.backtrace ensure diff --git a/Library/Homebrew/dev-cmd/update-test.rb b/Library/Homebrew/dev-cmd/update-test.rb index 1f1cdbeed..ee189ad5e 100644 --- a/Library/Homebrew/dev-cmd/update-test.rb +++ b/Library/Homebrew/dev-cmd/update-test.rb @@ -88,7 +88,7 @@ module Homebrew safe_system "brew", "update", "--verbose" actual_end_commit = Utils.popen_read("git", "rev-parse", branch).chomp if start_commit != end_commit && start_commit == actual_end_commit - raise <<-EOS.undent + raise <<~EOS brew update didn't update #{branch}! Start commit: #{start_commit} Expected end commit: #{end_commit} diff --git a/Library/Homebrew/diagnostic.rb b/Library/Homebrew/diagnostic.rb index 88aa4dbc9..49402bc07 100644 --- a/Library/Homebrew/diagnostic.rb +++ b/Library/Homebrew/diagnostic.rb @@ -92,7 +92,7 @@ module Homebrew def check_for_installed_developer_tools return if DevelopmentTools.installed? - <<-EOS.undent + <<~EOS No developer tools installed. #{DevelopmentTools.installation_instructions} EOS @@ -101,7 +101,7 @@ module Homebrew def check_build_from_source return unless ENV["HOMEBREW_BUILD_FROM_SOURCE"] - <<-EOS.undent + <<~EOS You have HOMEBREW_BUILD_FROM_SOURCE set. This environment variable is intended for use by Homebrew developers. If you are encountering errors, please try unsetting this. Please do not file issues if you encounter @@ -114,7 +114,7 @@ module Homebrew bad_paths = PATH.new(ENV["HOMEBREW_PATH"]).select { |p| p.end_with?("/") } return if bad_paths.empty? - inject_file_list bad_paths, <<-EOS.undent + inject_file_list bad_paths, <<~EOS Some directories in your path end in a slash. Directories in your path should not end in a slash. This can break other doctor checks. The following directories should be edited: @@ -136,7 +136,7 @@ module Homebrew # Only warn if Python lives with Anaconda, since is most problematic case. return unless python_directory == anaconda_directory - <<-EOS.undent + <<~EOS Anaconda is known to frequently break Homebrew builds, including Vim and MacVim, due to bundling many duplicates of system and Homebrew-available tools. @@ -151,11 +151,13 @@ module Homebrew return unless File.directory?(dir) files = Dir.chdir(dir) do - Dir[pattern].select { |f| File.file?(f) && !File.symlink?(f) } - Dir.glob(white_list) - end.map { |file| File.join(dir, file) } + (Dir.glob(pattern) - Dir.glob(white_list)) + .select { |f| File.file?(f) && !File.symlink?(f) } + .map { |f| File.join(dir, f) } + end return if files.empty? - inject_file_list(files, message) + inject_file_list(files.sort, message) end def check_for_stray_dylibs @@ -180,7 +182,7 @@ module Homebrew "sentinel.dylib", # SentinelOne ] - __check_stray_files "/usr/local/lib", "*.dylib", white_list, <<-EOS.undent + __check_stray_files "/usr/local/lib", "*.dylib", white_list, <<~EOS Unbrewed dylibs were found in /usr/local/lib. If you didn't put them there on purpose they could cause problems when building Homebrew formulae, and may need to be deleted. @@ -207,7 +209,7 @@ module Homebrew "libtrustedcomponents.a", # Symantec Endpoint Protection ] - __check_stray_files "/usr/local/lib", "*.a", white_list, <<-EOS.undent + __check_stray_files "/usr/local/lib", "*.a", white_list, <<~EOS Unbrewed static libraries were found in /usr/local/lib. If you didn't put them there on purpose they could cause problems when building Homebrew formulae, and may need to be deleted. @@ -227,7 +229,7 @@ module Homebrew "libublio.pc", # NTFS-3G ] - __check_stray_files "/usr/local/lib/pkgconfig", "*.pc", white_list, <<-EOS.undent + __check_stray_files "/usr/local/lib/pkgconfig", "*.pc", white_list, <<~EOS Unbrewed .pc files were found in /usr/local/lib/pkgconfig. If you didn't put them there on purpose they could cause problems when building Homebrew formulae, and may need to be deleted. @@ -248,7 +250,7 @@ module Homebrew "libublio.la", # NTFS-3G ] - __check_stray_files "/usr/local/lib", "*.la", white_list, <<-EOS.undent + __check_stray_files "/usr/local/lib", "*.la", white_list, <<~EOS Unbrewed .la files were found in /usr/local/lib. If you didn't put them there on purpose they could cause problems when building Homebrew formulae, and may need to be deleted. @@ -267,7 +269,7 @@ module Homebrew "ntfs-3g/**/*.h", # NTFS-3G ] - __check_stray_files "/usr/local/include", "**/*.h", white_list, <<-EOS.undent + __check_stray_files "/usr/local/include", "**/*.h", white_list, <<~EOS Unbrewed header files were found in /usr/local/include. If you didn't put them there on purpose they could cause problems when building Homebrew formulae, and may need to be deleted. @@ -289,7 +291,7 @@ module Homebrew end return if broken_symlinks.empty? - inject_file_list broken_symlinks, <<-EOS.undent + inject_file_list broken_symlinks, <<~EOS Broken symlinks were found. Remove them with `brew prune`: EOS end @@ -298,7 +300,7 @@ module Homebrew world_writable = HOMEBREW_TEMP.stat.mode & 0777 == 0777 return if !world_writable || HOMEBREW_TEMP.sticky? - <<-EOS.undent + <<~EOS #{HOMEBREW_TEMP} is world-writable but does not have the sticky bit set. Please execute `sudo chmod +t #{HOMEBREW_TEMP}` in your Terminal. EOS @@ -307,7 +309,7 @@ module Homebrew def check_access_homebrew_repository return if HOMEBREW_REPOSITORY.writable_real? - <<-EOS.undent + <<~EOS #{HOMEBREW_REPOSITORY} is not writable. You should change the ownership and permissions of #{HOMEBREW_REPOSITORY} @@ -328,7 +330,7 @@ module Homebrew return if not_writable_dirs.empty? - <<-EOS.undent + <<~EOS The following directories are not writable: #{not_writable_dirs.join("\n")} @@ -346,7 +348,7 @@ module Homebrew return unless Language::Python.homebrew_site_packages.exist? return if Language::Python.homebrew_site_packages.writable_real? - <<-EOS.undent + <<~EOS #{Language::Python.homebrew_site_packages} isn't writable. This can happen if you "sudo pip install" software that isn't managed by Homebrew. If you install a formula with Python modules, the install @@ -362,7 +364,7 @@ module Homebrew return unless HOMEBREW_LOCK_DIR.exist? return if HOMEBREW_LOCK_DIR.writable_real? - <<-EOS.undent + <<~EOS #{HOMEBREW_LOCK_DIR} isn't writable. Homebrew writes lock files to this location. @@ -376,7 +378,7 @@ module Homebrew return unless HOMEBREW_LOGS.exist? return if HOMEBREW_LOGS.writable_real? - <<-EOS.undent + <<~EOS #{HOMEBREW_LOGS} isn't writable. Homebrew writes debugging logs to this location. @@ -390,7 +392,7 @@ module Homebrew return unless HOMEBREW_CACHE.exist? return if HOMEBREW_CACHE.writable_real? - <<-EOS.undent + <<~EOS #{HOMEBREW_CACHE} isn't writable. This can happen if you run `brew install` or `brew fetch` as another user. Homebrew caches downloaded files to this location. @@ -405,7 +407,7 @@ module Homebrew return unless HOMEBREW_CELLAR.exist? return if HOMEBREW_CELLAR.writable_real? - <<-EOS.undent + <<~EOS #{HOMEBREW_CELLAR} isn't writable. You should change the ownership and permissions of #{HOMEBREW_CELLAR} @@ -419,7 +421,7 @@ module Homebrew return unless (HOMEBREW_REPOSITORY/"Cellar").exist? return unless (HOMEBREW_PREFIX/"Cellar").exist? - <<-EOS.undent + <<~EOS You have multiple Cellars. You should delete #{HOMEBREW_REPOSITORY}/Cellar: rm -rf #{HOMEBREW_REPOSITORY}/Cellar @@ -427,15 +429,15 @@ module Homebrew end def check_user_path_1 - $seen_prefix_bin = false - $seen_prefix_sbin = false + @seen_prefix_bin = false + @seen_prefix_sbin = false message = "" paths(ENV["HOMEBREW_PATH"]).each do |p| case p when "/usr/bin" - unless $seen_prefix_bin + unless @seen_prefix_bin # only show the doctor message if there are any conflicts # rationale: a default install should not trigger any brew doctor messages conflicts = Dir["#{HOMEBREW_PREFIX}/bin/*"] @@ -443,13 +445,13 @@ module Homebrew .select { |bn| File.exist? "/usr/bin/#{bn}" } unless conflicts.empty? - message = inject_file_list conflicts, <<-EOS.undent + message = inject_file_list conflicts, <<~EOS /usr/bin occurs before #{HOMEBREW_PREFIX}/bin This means that system-provided programs will be used instead of those provided by Homebrew. The following tools exist at both paths: EOS - message += <<-EOS.undent + message += <<~EOS Consider setting your PATH so that #{HOMEBREW_PREFIX}/bin occurs before /usr/bin. Here is a one-liner: @@ -458,9 +460,9 @@ module Homebrew end end when "#{HOMEBREW_PREFIX}/bin" - $seen_prefix_bin = true + @seen_prefix_bin = true when "#{HOMEBREW_PREFIX}/sbin" - $seen_prefix_sbin = true + @seen_prefix_sbin = true end end @@ -468,9 +470,9 @@ module Homebrew end def check_user_path_2 - return if $seen_prefix_bin + return if @seen_prefix_bin - <<-EOS.undent + <<~EOS Homebrew's bin was not found in your PATH. Consider setting the PATH for example like so #{Utils::Shell.prepend_path_in_profile("#{HOMEBREW_PREFIX}/bin")} @@ -478,13 +480,13 @@ module Homebrew end def check_user_path_3 - return if $seen_prefix_sbin + return if @seen_prefix_sbin # Don't complain about sbin not being in the path if it doesn't exist sbin = HOMEBREW_PREFIX/"sbin" return unless sbin.directory? && !sbin.children.empty? - <<-EOS.undent + <<~EOS Homebrew's sbin was not found in your PATH but you have installed formulae that put executables in #{HOMEBREW_PREFIX}/sbin. Consider setting the PATH for example like so @@ -498,7 +500,7 @@ module Homebrew end return unless curlrc_found - <<-EOS.undent + <<~EOS You have a curlrc file If you have trouble downloading packages with Homebrew, then maybe this is the problem? If the following command doesn't work, then try removing @@ -524,7 +526,7 @@ module Homebrew end return if gettext&.linked_keg&.directory? && homebrew_owned - inject_file_list @found, <<-EOS.undent + inject_file_list @found, <<~EOS gettext files detected at a system prefix. These files can cause compilation and link failures, especially if they are compiled with improper architectures. Consider removing these files: @@ -542,13 +544,13 @@ module Homebrew end if libiconv&.linked_keg&.directory? unless libiconv.keg_only? - <<-EOS.undent + <<~EOS A libiconv formula is installed and linked. This will break stuff. For serious. Unlink it. EOS end else - inject_file_list @found, <<-EOS.undent + inject_file_list @found, <<~EOS libiconv files detected at a system prefix other than /usr. Homebrew doesn't provide a libiconv formula, and expects to link against the system version in /usr. libiconv in other prefixes can cause @@ -586,7 +588,7 @@ module Homebrew return if scripts.empty? - inject_file_list scripts, <<-EOS.undent + inject_file_list scripts, <<~EOS "config" scripts exist outside your system or Homebrew directories. `./configure` scripts often look for *-config scripts to determine if software packages are installed, and what additional flags to use when @@ -603,13 +605,13 @@ module Homebrew return if dyld_vars.empty? values = dyld_vars.map { |var| "#{var}: #{ENV.fetch(var)}" } - message = inject_file_list values, <<-EOS.undent + message = inject_file_list values, <<~EOS Setting DYLD_* vars can break dynamic linking. Set variables: EOS if dyld_vars.include? "DYLD_INSERT_LIBRARIES" - message += <<-EOS.undent + message += <<~EOS Setting DYLD_INSERT_LIBRARIES can cause Go builds to fail. Having this set is common if you use this software: @@ -622,7 +624,7 @@ module Homebrew def check_ssl_cert_file return unless ENV.key?("SSL_CERT_FILE") - <<-EOS.undent + <<~EOS Setting SSL_CERT_FILE can break downloading files; if that happens you should unset it before running Homebrew. @@ -636,7 +638,7 @@ module Homebrew return unless HOMEBREW_CELLAR.exist? return unless HOMEBREW_CELLAR.symlink? - <<-EOS.undent + <<~EOS Symlinked Cellars can cause problems. Your Homebrew Cellar is a symlink: #{HOMEBREW_CELLAR} which resolves to: #{HOMEBREW_CELLAR.realpath} @@ -673,7 +675,7 @@ module Homebrew return if where_cellar == where_tmp - <<-EOS.undent + <<~EOS Your Cellar and TEMP directories are on different volumes. macOS won't move relative symlinks across volumes unless the target file already exists. Brews known to be affected by this are Git and Narwhal. @@ -690,7 +692,7 @@ module Homebrew git = Formula["git"] git_upgrade_cmd = git.any_version_installed? ? "upgrade" : "install" - <<-EOS.undent + <<~EOS An outdated version (#{Utils.git_version}) of Git was detected in your PATH. Git 1.8.5 or newer is required to perform checkouts over HTTPS from GitHub and to support the 'git -C <path>' option. @@ -702,7 +704,7 @@ module Homebrew def check_for_git return if Utils.git_available? - <<-EOS.undent + <<~EOS Git could not be found in your PATH. Homebrew uses Git for several internal functions, and some formulae use Git checkouts instead of stable tarballs. You may want to install Git: @@ -716,7 +718,7 @@ module Homebrew autocrlf = HOMEBREW_REPOSITORY.cd { `git config --get core.autocrlf`.chomp } return unless autocrlf == "true" - <<-EOS.undent + <<~EOS Suspicious Git newline settings found. The detected Git newline settings will cause checkout problems: @@ -734,7 +736,7 @@ module Homebrew origin = HOMEBREW_REPOSITORY.git_origin if origin.nil? - <<-EOS.undent + <<~EOS Missing Homebrew/brew git origin remote. Without a correctly configured origin, Homebrew won't update @@ -742,7 +744,7 @@ module Homebrew git -C "#{HOMEBREW_REPOSITORY}" remote add origin #{Formatter.url("https://github.com/Homebrew/brew.git")} EOS elsif origin !~ %r{Homebrew/brew(\.git|/)?$} - <<-EOS.undent + <<~EOS Suspicious Homebrew/brew git origin remote found. With a non-standard origin, Homebrew won't pull updates from @@ -763,7 +765,7 @@ module Homebrew origin = coretap_path.git_origin if origin.nil? - <<-EOS.undent + <<~EOS Missing #{CoreTap.instance} git origin remote. Without a correctly configured origin, Homebrew won't update @@ -773,7 +775,7 @@ module Homebrew elsif origin !~ %r{Homebrew/homebrew-core(\.git|/)?$} return if ENV["CI"] && origin.include?("Homebrew/homebrew-test-bot") - <<-EOS.undent + <<~EOS Suspicious #{CoreTap.instance} git origin remote found. With a non-standard origin, Homebrew won't pull updates from @@ -785,6 +787,18 @@ module Homebrew git -C "#{coretap_path}" remote set-url origin #{Formatter.url("https://github.com/Homebrew/homebrew-core.git")} EOS end + + return if ENV["CI"] || ENV["JENKINS_HOME"] + + branch = coretap_path.git_branch + return if branch.nil? || branch =~ /master/ + + <<~EOS + Homebrew/homebrew-core is not on the master branch + + Check out the master branch by running: + git -C "$(brew --repo homebrew/core)" checkout master + EOS end def __check_linked_brew(f) @@ -802,12 +816,12 @@ module Homebrew def check_for_linked_keg_only_brews return unless HOMEBREW_CELLAR.exist? - linked = Formula.installed.select do |f| + linked = Formula.installed.sort.select do |f| f.keg_only? && __check_linked_brew(f) end return if linked.empty? - inject_file_list linked.map(&:full_name), <<-EOS.undent + inject_file_list linked.map(&:full_name), <<~EOS Some keg-only formula are linked into the Cellar. Linking a keg-only formula, such as gettext, into the cellar with `brew link <formula>` will cause other formulae to detect them during @@ -833,7 +847,7 @@ module Homebrew .select { |framework| File.exist? framework } return if frameworks_found.empty? - inject_file_list frameworks_found, <<-EOS.undent + inject_file_list frameworks_found, <<~EOS Some frameworks can be picked up by CMake's build system and likely cause the build to fail. To compile CMake, you may wish to move these out of the way: @@ -844,7 +858,7 @@ module Homebrew tmpdir = ENV["TMPDIR"] return if tmpdir.nil? || File.directory?(tmpdir) - <<-EOS.undent + <<~EOS TMPDIR #{tmpdir.inspect} doesn't exist. EOS end @@ -857,7 +871,7 @@ module Homebrew end return if missing.empty? - <<-EOS.undent + <<~EOS Some installed formula are missing dependencies. You should `brew install` the missing dependencies: brew install #{missing.sort_by(&:full_name) * " "} @@ -872,7 +886,7 @@ module Homebrew return if `git status --untracked-files=all --porcelain -- Library/Homebrew/ 2>/dev/null`.chomp.empty? end - <<-EOS.undent + <<~EOS You have uncommitted modifications to Homebrew If this is a surprise to you, then you should stash these modifications. Stashing returns Homebrew to a pristine state but can be undone @@ -884,7 +898,7 @@ module Homebrew def check_for_enthought_python return unless which "enpkg" - <<-EOS.undent + <<~EOS Enthought Python was found in your PATH. This can cause build problems, as this software installs its own copies of iconv and libxml2 into directories that are picked up by @@ -895,7 +909,7 @@ module Homebrew def check_for_library_python return unless File.exist?("/Library/Frameworks/Python.framework") - <<-EOS.undent + <<~EOS Python is installed at /Library/Frameworks/Python.framework Homebrew only supports building against the System-provided Python or a @@ -908,12 +922,12 @@ module Homebrew message = "" ["", "3"].map do |suffix| next unless paths.include?((HOMEBREW_PREFIX/"share/python#{suffix}").to_s) - message += <<-EOS.undent - #{HOMEBREW_PREFIX}/share/python#{suffix} is not needed in PATH. + message += <<~EOS + #{HOMEBREW_PREFIX}/share/python#{suffix} is not needed in PATH. EOS end unless message.empty? - message += <<-EOS.undent + message += <<~EOS Formerly homebrew put Python scripts you installed via `pip` or `pip3` (or `easy_install`) into that directory above but now it can be removed @@ -935,7 +949,7 @@ module Homebrew return if Regexp.last_match(1).nil? return if Regexp.last_match(1) == "2" - <<-EOS.undent + <<~EOS python is symlinked to python#{Regexp.last_match(1)} This will confuse build scripts and in general lead to subtle breakage. EOS @@ -948,10 +962,11 @@ module Homebrew gnubin = %W[#{coreutils.opt_libexec}/gnubin #{coreutils.libexec}/gnubin] return if (paths & gnubin).empty? - <<-EOS.undent + <<~EOS Putting non-prefixed coreutils in your path can cause gmp builds to fail. EOS rescue FormulaUnavailableError + return end def check_for_non_prefixed_findutils @@ -962,16 +977,17 @@ module Homebrew default_names = Tab.for_name("findutils").with? "default-names" return if !default_names && (paths & gnubin).empty? - <<-EOS.undent + <<~EOS Putting non-prefixed findutils in your path can cause python builds to fail. EOS rescue FormulaUnavailableError + return end def check_for_pydistutils_cfg_in_home return unless File.exist? "#{ENV["HOME"]}/.pydistutils.cfg" - <<-EOS.undent + <<~EOS A .pydistutils.cfg file was found in $HOME, which may cause Python builds to fail. See: #{Formatter.url("https://bugs.python.org/issue6138")} @@ -993,7 +1009,7 @@ module Homebrew end.map(&:basename) return if unlinked.empty? - inject_file_list unlinked, <<-EOS.undent + inject_file_list unlinked, <<~EOS You have unlinked kegs in your Cellar Leaving kegs unlinked can lead to build-trouble and cause brews that depend on those kegs to fail to run properly once built. Run `brew link` on these: @@ -1003,7 +1019,7 @@ module Homebrew def check_for_old_env_vars return unless ENV["HOMEBREW_KEEP_INFO"] - <<-EOS.undent + <<~EOS `HOMEBREW_KEEP_INFO` is no longer used info files are no longer deleted by default; you may remove this environment variable. @@ -1017,7 +1033,7 @@ module Homebrew return unless Language::Python.in_sys_path?("python", homebrew_site_packages) user_site_packages = Language::Python.user_site_packages "python" - <<-EOS.undent + <<~EOS Your default Python does not recognize the Homebrew site-packages directory as a special site-packages directory, which means that .pth files will not be followed. This means you will not be able to import @@ -1047,8 +1063,7 @@ module Homebrew message = "You have external commands with conflicting names.\n" cmd_map.each do |cmd_name, cmd_paths| - message += inject_file_list cmd_paths, <<-EOS.undent - + message += inject_file_list cmd_paths, <<~EOS Found command `#{cmd_name}` in following places: EOS end @@ -1071,7 +1086,7 @@ module Homebrew end return if bad_tap_files.empty? bad_tap_files.keys.map do |tap| - <<-EOS.undent + <<~EOS Found Ruby file outside #{tap} tap formula directory (#{tap.formula_dir}): #{bad_tap_files[tap].join("\n ")} diff --git a/Library/Homebrew/download_strategy.rb b/Library/Homebrew/download_strategy.rb index 7012fccc8..f9a359450 100644 --- a/Library/Homebrew/download_strategy.rb +++ b/Library/Homebrew/download_strategy.rb @@ -18,8 +18,7 @@ class AbstractDownloadStrategy end # Download and cache the resource as {#cached_location}. - def fetch - end + def fetch; end # Suppress output def shutup! @@ -37,13 +36,11 @@ class AbstractDownloadStrategy # Unpack {#cached_location} into the current working directory, and possibly # chdir into the newly-unpacked directory. # Unlike {Resource#stage}, this does not take a block. - def stage - end + def stage; end # @!attribute [r] cached_location # The path to the cached file or directory associated with the resource. - def cached_location - end + def cached_location; end # @!attribute [r] # return most recent modified time for all files in the current working directory after stage. @@ -162,7 +159,7 @@ class VCSDownloadStrategy < AbstractDownloadStrategy return unless @ref_type == :tag return unless @revision && current_revision return if current_revision == @revision - raise <<-EOS.undent + raise <<~EOS #{@ref} tag should be #{@revision} but is actually #{current_revision} EOS @@ -204,14 +201,11 @@ class VCSDownloadStrategy < AbstractDownloadStrategy true end - def clone_repo - end + def clone_repo; end - def update - end + def update; end - def current_revision - end + def current_revision; end def extract_ref(specs) key = REF_TYPES.find { |type| specs.key?(type) } @@ -559,9 +553,9 @@ class GitHubPrivateRepositoryDownloadStrategy < CurlDownloadStrategy rescue GitHub::HTTPNotFoundError # We only handle HTTPNotFoundError here, # becase AuthenticationFailedError is handled within util/github. - message = <<-EOS.undent - HOMEBREW_GITHUB_API_TOKEN can not access the repository: #{@owner}/#{@repo} - This token may not have permission to access the repository or the url of formula may be incorrect. + message = <<~EOS + HOMEBREW_GITHUB_API_TOKEN can not access the repository: #{@owner}/#{@repo} + This token may not have permission to access the repository or the url of formula may be incorrect. EOS raise CurlDownloadStrategyError, message end diff --git a/Library/Homebrew/exceptions.rb b/Library/Homebrew/exceptions.rb index 22a7fe023..7705f9d49 100644 --- a/Library/Homebrew/exceptions.rb +++ b/Library/Homebrew/exceptions.rb @@ -185,7 +185,7 @@ class TapFormulaAmbiguityError < RuntimeError "#{Tap.fetch(match[:user], match[:repo])}/#{path.basename(".rb")}" end - super <<-EOS.undent + super <<~EOS Formulae found in multiple taps: #{formulae.map { |f| "\n * #{f}" }.join} Please use the fully-qualified name e.g. #{formulae.first} to refer the formula. @@ -205,7 +205,7 @@ class TapFormulaWithOldnameAmbiguityError < RuntimeError "#{Regexp.last_match(1)}/#{Regexp.last_match(2)}" end - super <<-EOS.undent + super <<~EOS Formulae with '#{name}' old name found in multiple taps: #{taps.map { |t| "\n * #{t}" }.join} Please use the fully-qualified name e.g. #{taps.first}/#{name} to refer the formula or use its new name. @@ -219,7 +219,7 @@ class TapUnavailableError < RuntimeError def initialize(name) @name = name - super <<-EOS.undent + super <<~EOS No available tap #{name}. EOS end @@ -235,7 +235,7 @@ class TapRemoteMismatchError < RuntimeError @expected_remote = expected_remote @actual_remote = actual_remote - super <<-EOS.undent + super <<~EOS Tap #{name} remote mismatch. #{expected_remote} != #{actual_remote} EOS @@ -248,7 +248,7 @@ class TapAlreadyTappedError < RuntimeError def initialize(name) @name = name - super <<-EOS.undent + super <<~EOS Tap #{name} already tapped. EOS end @@ -260,7 +260,7 @@ class TapAlreadyUnshallowError < RuntimeError def initialize(name) @name = name - super <<-EOS.undent + super <<~EOS Tap #{name} already a full clone. EOS end @@ -279,7 +279,7 @@ end class OperationInProgressError < RuntimeError def initialize(name) - message = <<-EOS.undent + message = <<~EOS Operation already in progress for #{name} Another active Homebrew process is already using #{name}. Please wait for it to finish or terminate it to continue. @@ -327,7 +327,7 @@ class FormulaConflictError < RuntimeError message = [] message << "Cannot install #{formula.full_name} because conflicting formulae are installed." message.concat conflicts.map { |c| conflict_message(c) } << "" - message << <<-EOS.undent + message << <<~EOS Please `brew unlink #{conflicts.map(&:name) * " "}` before continuing. Unlinking removes a formula's symlinks from #{HOMEBREW_PREFIX}. You can @@ -341,7 +341,7 @@ end class FormulaAmbiguousPythonError < RuntimeError def initialize(formula) - super <<-EOS.undent + super <<~EOS The version of python to use with the virtualenv in the `#{formula.full_name}` formula cannot be guessed automatically. If the simultaneous use of python and python3 is intentional, please add `:using => "python"` or `:using => "python3"` to @@ -398,18 +398,18 @@ class BuildError < RuntimeError if formula.tap.official? puts Formatter.error(Formatter.url(OS::ISSUES_URL), label: "READ THIS") elsif issues_url = formula.tap.issues_url - puts <<-EOS.undent + puts <<~EOS If reporting this issue please do so at (not Homebrew/brew or Homebrew/core): #{Formatter.url(issues_url)} EOS else - puts <<-EOS.undent + puts <<~EOS If reporting this issue please do so to (not Homebrew/brew or Homebrew/core): #{formula.tap} EOS end else - puts <<-EOS.undent + puts <<~EOS Do not report this issue to Homebrew/brew or Homebrew/core! EOS end @@ -445,7 +445,7 @@ class BuildToolsError < RuntimeError package_text = "a binary package" end - super <<-EOS.undent + super <<~EOS The following #{formula_text}: #{formulae.join(", ")} cannot be installed as #{package_text} and must be built from source. @@ -467,7 +467,7 @@ class BuildFlagsError < RuntimeError require_text = "requires" end - super <<-EOS.undent + super <<~EOS The following #{flag_text}: #{flags.join(", ")} #{require_text} building tools, but none are installed. @@ -481,7 +481,7 @@ end # the compilers available on the user's system class CompilerSelectionError < RuntimeError def initialize(formula) - super <<-EOS.undent + super <<~EOS #{formula.full_name} cannot be built with any available compilers. #{DevelopmentTools.custom_installation_instructions} EOS @@ -491,7 +491,7 @@ end # Raised in Resource.fetch class DownloadError < RuntimeError def initialize(resource, cause) - super <<-EOS.undent + super <<~EOS Failed to download resource #{resource.download_name.inspect} #{cause.message} EOS @@ -530,7 +530,7 @@ class ChecksumMismatchError < RuntimeError @expected = expected @hash_type = expected.hash_type.to_s.upcase - super <<-EOS.undent + super <<~EOS #{@hash_type} mismatch Expected: #{expected} Actual: #{actual} @@ -557,7 +557,7 @@ class MissingApplyError < RuntimeError; end class BottleFormulaUnavailableError < RuntimeError def initialize(bottle_path, formula_path) - super <<-EOS.undent + super <<~EOS This bottle does not contain the formula file: #{bottle_path} #{formula_path} diff --git a/Library/Homebrew/extend/ARGV.rb b/Library/Homebrew/extend/ARGV.rb index 63a0f3e40..d9da014f0 100644 --- a/Library/Homebrew/extend/ARGV.rb +++ b/Library/Homebrew/extend/ARGV.rb @@ -124,7 +124,7 @@ module HomebrewArgvExtension Keg.new(prefix) end rescue FormulaUnavailableError - raise <<-EOS.undent + raise <<~EOS Multiple kegs installed to #{rack} However we don't know which one you refer to. Please delete (with rm -rf!) all but one and then try again. diff --git a/Library/Homebrew/extend/ENV/shared.rb b/Library/Homebrew/extend/ENV/shared.rb index 15488ee19..5a6b779d0 100644 --- a/Library/Homebrew/extend/ENV/shared.rb +++ b/Library/Homebrew/extend/ENV/shared.rb @@ -233,7 +233,7 @@ module SharedEnvExtension if ARGV.include? "--default-fortran-flags" flags = FC_FLAG_VARS.reject { |key| self[key] } elsif values_at(*FC_FLAG_VARS).compact.empty? - opoo <<-EOS.undent + opoo <<~EOS No Fortran optimization information was provided. You may want to consider setting FCFLAGS and FFLAGS or pass the `--default-fortran-flags` option to `brew install` if your compiler is compatible with GCC. @@ -286,15 +286,15 @@ module SharedEnvExtension begin gcc_formula = gcc_version_formula(name) rescue FormulaUnavailableError => e - raise <<-EOS.undent - Homebrew GCC requested, but formula #{e.name} not found! + raise <<~EOS + Homebrew GCC requested, but formula #{e.name} not found! EOS end return if gcc_formula.opt_prefix.exist? - raise <<-EOS.undent - The requested Homebrew GCC was not installed. You must: - brew install #{gcc_formula.full_name} + raise <<~EOS + The requested Homebrew GCC was not installed. You must: + brew install #{gcc_formula.full_name} EOS end diff --git a/Library/Homebrew/extend/ENV/super.rb b/Library/Homebrew/extend/ENV/super.rb index b518c22a1..b4f0dfcac 100644 --- a/Library/Homebrew/extend/ENV/super.rb +++ b/Library/Homebrew/extend/ENV/super.rb @@ -24,8 +24,7 @@ module Superenv end # @private - def self.bin - end + def self.bin; end def reset super @@ -324,11 +323,9 @@ module Superenv end end - def set_x11_env_if_installed - end + def set_x11_env_if_installed; end - def set_cpu_flags(*) - end + def set_cpu_flags(_, _ = "", _ = {}); end end require "extend/os/extend/ENV/super" diff --git a/Library/Homebrew/extend/cachable.rb b/Library/Homebrew/extend/cachable.rb new file mode 100644 index 000000000..69d86ccb7 --- /dev/null +++ b/Library/Homebrew/extend/cachable.rb @@ -0,0 +1,9 @@ +module Cachable + def cache + @cache ||= {} + end + + def clear_cache + cache.clear + end +end diff --git a/Library/Homebrew/extend/fileutils.rb b/Library/Homebrew/extend/fileutils.rb index ed5bfe6c3..34ef3869f 100644 --- a/Library/Homebrew/extend/fileutils.rb +++ b/Library/Homebrew/extend/fileutils.rb @@ -101,11 +101,6 @@ module FileUtils system Formulary.factory("scons").opt_bin/"scons", *args end - # Run the `rake` from the `ruby` Homebrew is using rather than whatever is in the `PATH`. - def rake(*args) - system RUBY_BIN/"rake", *args - end - # Run `make` 3.81 or newer. # Uses the system make on Leopard and newer, and the # path to the actually-installed make on Tiger or older. diff --git a/Library/Homebrew/extend/git_repository.rb b/Library/Homebrew/extend/git_repository.rb index c15988550..6b89d175c 100644 --- a/Library/Homebrew/extend/git_repository.rb +++ b/Library/Homebrew/extend/git_repository.rb @@ -36,6 +36,15 @@ module GitRepositoryExtension end end + def git_branch + return unless git? && Utils.git_available? + cd do + Utils.popen_read( + "git", "rev-parse", "--abbrev-ref", "HEAD" + ).chuzzle + end + end + def git_last_commit_date return unless git? && Utils.git_available? cd do diff --git a/Library/Homebrew/extend/os/caveats.rb b/Library/Homebrew/extend/os/caveats.rb new file mode 100644 index 000000000..e67138087 --- /dev/null +++ b/Library/Homebrew/extend/os/caveats.rb @@ -0,0 +1 @@ +require "extend/os/mac/caveats" if OS.mac? diff --git a/Library/Homebrew/extend/os/linux/requirements/osxfuse_requirement.rb b/Library/Homebrew/extend/os/linux/requirements/osxfuse_requirement.rb index 3fd847bc4..3553ada74 100644 --- a/Library/Homebrew/extend/os/linux/requirements/osxfuse_requirement.rb +++ b/Library/Homebrew/extend/os/linux/requirements/osxfuse_requirement.rb @@ -18,7 +18,7 @@ class OsxfuseRequirement < Requirement def message msg = "libfuse is required to install this formula.\n" if libfuse_formula_exists? - msg + <<-EOS.undent + msg + <<~EOS Run "brew install libfuse" to install it. EOS else diff --git a/Library/Homebrew/extend/os/mac/caveats.rb b/Library/Homebrew/extend/os/mac/caveats.rb new file mode 100644 index 000000000..d912a8307 --- /dev/null +++ b/Library/Homebrew/extend/os/mac/caveats.rb @@ -0,0 +1,45 @@ +class Caveats + def plist_caveats + s = [] + if f.plist || (keg&.plist_installed?) + plist_domain = f.plist_path.basename(".plist") + + # we readlink because this path probably doesn't exist since caveats + # occurs before the link step of installation + # Yosemite security measures mildly tighter rules: + # https://github.com/Homebrew/legacy-homebrew/issues/33815 + if !plist_path.file? || !plist_path.symlink? + if f.plist_startup + s << "To have launchd start #{f.full_name} now and restart at startup:" + s << " sudo brew services start #{f.full_name}" + else + s << "To have launchd start #{f.full_name} now and restart at login:" + s << " brew services start #{f.full_name}" + end + # For startup plists, we cannot tell whether it's running on launchd, + # as it requires for `sudo launchctl list` to get real result. + elsif f.plist_startup + s << "To restart #{f.full_name} after an upgrade:" + s << " sudo brew services restart #{f.full_name}" + elsif Kernel.system "/bin/launchctl list #{plist_domain} &>/dev/null" + s << "To restart #{f.full_name} after an upgrade:" + s << " brew services restart #{f.full_name}" + else + s << "To start #{f.full_name}:" + s << " brew services start #{f.full_name}" + end + + if f.plist_manual + s << "Or, if you don't want/need a background service you can just run:" + s << " #{f.plist_manual}" + end + + # pbpaste is the system clipboard tool on macOS and fails with `tmux` by default + # check if this is being run under `tmux` to avoid failing + if ENV["TMUX"] && !quiet_system("/usr/bin/pbpaste") + s << "" << "WARNING: brew services will fail when run under tmux." + end + end + s.join("\n") + "\n" unless s.empty? + end +end diff --git a/Library/Homebrew/extend/os/mac/development_tools.rb b/Library/Homebrew/extend/os/mac/development_tools.rb index 1931b398d..d37e778ca 100644 --- a/Library/Homebrew/extend/os/mac/development_tools.rb +++ b/Library/Homebrew/extend/os/mac/development_tools.rb @@ -24,18 +24,18 @@ class DevelopmentTools def installation_instructions if MacOS.version >= "10.9" - <<-EOS.undent + <<~EOS Install the Command Line Tools: xcode-select --install EOS elsif MacOS.version == "10.8" || MacOS.version == "10.7" - <<-EOS.undent + <<~EOS Install the Command Line Tools from https://developer.apple.com/download/more/ or via Xcode's preferences. EOS else - <<-EOS.undent + <<~EOS Install Xcode from https://developer.apple.com/download/more/ EOS @@ -44,19 +44,19 @@ class DevelopmentTools def custom_installation_instructions if MacOS.version > :leopard - <<-EOS.undent + <<~EOS Install GNU's GCC brew install gcc EOS elsif MacOS.version > :tiger - <<-EOS.undent + <<~EOS Install GNU's GCC brew install gcc@4.6 EOS else # Tiger doesn't ship with apple-gcc42, and this is required to build # some software that doesn't build properly with FSF GCC. - <<-EOS.undent + <<~EOS Install Apple's GCC brew install apple-gcc42 or GNU's GCC diff --git a/Library/Homebrew/extend/os/mac/diagnostic.rb b/Library/Homebrew/extend/os/mac/diagnostic.rb index 9f7b18b49..be0ce9351 100644 --- a/Library/Homebrew/extend/os/mac/diagnostic.rb +++ b/Library/Homebrew/extend/os/mac/diagnostic.rb @@ -41,7 +41,7 @@ module Homebrew return end - <<-EOS.undent + <<~EOS You are using macOS #{MacOS.version}. #{who} do not provide support for this #{what}. You may encounter build failures or other breakages. @@ -59,7 +59,7 @@ module Homebrew # Homebrew/brew is currently using. return if ENV["TRAVIS"] - message = <<-EOS.undent + message = <<~EOS Your Xcode (#{MacOS::Xcode.version}) is outdated. Please update to Xcode #{MacOS::Xcode.latest_version} (or delete it). #{MacOS::Xcode.update_instructions} @@ -67,7 +67,7 @@ module Homebrew if OS::Mac.prerelease? current_path = Utils.popen_read("/usr/bin/xcode-select", "-p") - message += <<-EOS.undent + message += <<~EOS If #{MacOS::Xcode.latest_version} is installed, you may need to: sudo xcode-select --switch /Applications/Xcode.app Current developer directory is: @@ -87,7 +87,7 @@ module Homebrew # Homebrew/brew is currently using. return if ENV["TRAVIS"] - <<-EOS.undent + <<~EOS A newer Command Line Tools release is available. #{MacOS::CLT.update_instructions} EOS @@ -99,7 +99,7 @@ module Homebrew return unless MacOS.version == :el_capitan return unless MacOS::Xcode.version >= "8" - <<-EOS.undent + <<~EOS You have Xcode 8 installed without the CLT; this causes certain builds to fail on OS X El Capitan (10.11). Please install the CLT via: @@ -111,7 +111,7 @@ module Homebrew return unless MacOS::Xcode.installed? return unless MacOS::Xcode.below_minimum_version? - <<-EOS.undent + <<~EOS Your Xcode (#{MacOS::Xcode.version}) is too outdated. Please update to Xcode #{MacOS::Xcode.latest_version} (or delete it). #{MacOS::Xcode.update_instructions} @@ -122,7 +122,7 @@ module Homebrew return unless MacOS::CLT.installed? return unless MacOS::CLT.below_minimum_version? - <<-EOS.undent + <<~EOS Your Command Line Tools are too outdated. #{MacOS::CLT.update_instructions} EOS @@ -140,7 +140,7 @@ module Homebrew "Please install Xcode #{MacOS::Xcode.latest_version}." end - <<-EOS.undent + <<~EOS You seem to have osx-gcc-installer installed. Homebrew doesn't support osx-gcc-installer. It causes many builds to fail and is an unlicensed distribution of really old Xcode files. @@ -154,7 +154,7 @@ module Homebrew uninstaller = Pathname.new("/Developer/Library/uninstall-developer-folder") return unless ((MacOS::Xcode.version || "0") >= "4.3") && uninstaller.exist? - <<-EOS.undent + <<~EOS You have leftover files from an older version of Xcode. You should delete them using: #{uninstaller} @@ -170,7 +170,7 @@ module Homebrew return if libs.empty? return if libs.include? "/usr/lib/libxcselect.dylib" - <<-EOS.undent + <<~EOS You have an outdated version of /usr/bin/install_name_tool installed. This will cause binary package installations to fail. This can happen if you install osx-gcc-installer or RailsInstaller. @@ -183,7 +183,7 @@ module Homebrew ponk = MacOS.macports_or_fink return if ponk.empty? - <<-EOS.undent + <<~EOS You have MacPorts or Fink installed: #{ponk.join(", ")} @@ -199,7 +199,7 @@ module Homebrew return if RUBY_VERSION == ruby_version return if ARGV.homebrew_developer? && OS::Mac.prerelease? - <<-EOS.undent + <<~EOS Ruby version #{RUBY_VERSION} is unsupported on #{MacOS.version}. Homebrew is developed and tested on Ruby #{ruby_version}, and may not work correctly on other Rubies. Patches are accepted as long as they don't cause breakage @@ -212,7 +212,7 @@ module Homebrew return if prefix.nil? return unless prefix.to_s.include?(" ") - <<-EOS.undent + <<~EOS Xcode is installed to a directory with a space in the name. This will cause some formulae to fail to build. EOS @@ -222,7 +222,7 @@ module Homebrew prefix = MacOS::Xcode.prefix return if prefix.nil? || prefix.exist? - <<-EOS.undent + <<~EOS The directory Xcode is reportedly installed to doesn't exist: #{prefix} You may need to `xcode-select` the proper path if you have moved Xcode. @@ -236,7 +236,7 @@ module Homebrew path = MacOS::Xcode.bundle_path path = "/Developer" if path.nil? || !path.directory? - <<-EOS.undent + <<~EOS Your Xcode is configured with an invalid path. You should change it to the correct path: sudo xcode-select -switch #{path} @@ -247,7 +247,7 @@ module Homebrew return unless MacOS.version <= "10.8" return if Formula["curl"].installed? - <<-EOS.undent + <<~EOS The system curl on 10.8 and below is often incapable of supporting modern secure connections & will fail on fetching formulae. @@ -261,7 +261,7 @@ module Homebrew return unless MacOS.version >= :yosemite return if ENV["SSL_CERT_DIR"].nil? - <<-EOS.undent + <<~EOS SSL_CERT_DIR support was removed from Apple's curl. If fetching formulae fails you should: unset SSL_CERT_DIR @@ -274,7 +274,7 @@ module Homebrew # license or no "xc*" tool will work. return unless `/usr/bin/xcrun clang 2>&1` =~ /license/ && !$CHILD_STATUS.success? - <<-EOS.undent + <<~EOS You have not agreed to the Xcode license. Builds will fail! Agree to the license by opening Xcode.app or running: sudo xcodebuild -license @@ -289,7 +289,7 @@ module Homebrew latest_version = Version.create(MacOS::XQuartz.latest_version) return if installed_version >= latest_version - <<-EOS.undent + <<~EOS Your XQuartz (#{installed_version}) is outdated. Please install XQuartz #{latest_version} (or delete the current version). XQuartz can be updated using Homebrew-Cask by running @@ -301,7 +301,7 @@ module Homebrew return unless MacOS::XQuartz.version return unless MacOS::XQuartz.version.include? "beta" - <<-EOS.undent + <<~EOS The following beta release of XQuartz is installed: #{MacOS::XQuartz.version} XQuartz beta releases include address sanitization, and do not work with @@ -337,7 +337,7 @@ module Homebrew end case_sensitive_vols.uniq! - <<-EOS.undent + <<~EOS The filesystem on #{case_sensitive_vols.join(",")} appears to be case-sensitive. The default macOS filesystem is case-insensitive. Please report any apparent problems. EOS @@ -346,7 +346,7 @@ module Homebrew def check_homebrew_prefix return if HOMEBREW_PREFIX.to_s == "/usr/local" - <<-EOS.undent + <<~EOS Your Homebrew's prefix is not /usr/local. You can install Homebrew anywhere you want but some bottles (binary packages) can only be used with a /usr/local prefix and some formulae (packages) @@ -360,7 +360,7 @@ module Homebrew mono_config = Pathname.new("/usr/bin/pkg-config") if mono_config.exist? && mono_config.realpath.to_s.include?("Mono.framework") - <<-EOS.undent + <<~EOS You have a non-Homebrew 'pkg-config' in your PATH: /usr/bin/pkg-config => #{mono_config.realpath} @@ -371,7 +371,7 @@ module Homebrew `sudo rm /usr/bin/pkg-config` and upgrade to the latest version of Mono. EOS elsif binary.to_s != "#{HOMEBREW_PREFIX}/bin/pkg-config" - <<-EOS.undent + <<~EOS You have a non-Homebrew 'pkg-config' in your PATH: #{binary} diff --git a/Library/Homebrew/extend/os/mac/formula_cellar_checks.rb b/Library/Homebrew/extend/os/mac/formula_cellar_checks.rb index 32e5774f6..901d8945f 100644 --- a/Library/Homebrew/extend/os/mac/formula_cellar_checks.rb +++ b/Library/Homebrew/extend/os/mac/formula_cellar_checks.rb @@ -19,7 +19,7 @@ module FormulaCellarChecks return if files.empty? - <<-EOS.undent + <<~EOS Header files that shadow system header files were installed to "#{formula.include}" The offending files are: #{files * "\n "} @@ -35,7 +35,7 @@ module FormulaCellarChecks end return if system_openssl.empty? - <<-EOS.undent + <<~EOS object files were linked against system openssl These object files were linked against the deprecated system OpenSSL or the system's private LibreSSL. @@ -52,7 +52,7 @@ module FormulaCellarChecks end return if framework_links.empty? - <<-EOS.undent + <<~EOS python modules have explicit framework links These python extension modules were linked directly to a Python framework binary. They should be linked with -undefined dynamic_lookup @@ -67,13 +67,13 @@ module FormulaCellarChecks checker = LinkageChecker.new(keg, formula) return unless checker.broken_dylibs? - output = <<-EOS.undent + output = <<~EOS #{formula} has broken dynamic library links: #{checker.broken_dylibs.to_a * "\n "} EOS tab = Tab.for_keg(keg) if tab.poured_from_bottle - output += <<-EOS.undent + output += <<~EOS Rebuild this from source with: brew reinstall --build-from-source #{formula} If that's successful, file an issue#{formula.tap ? " here:\n #{formula.tap.issues_url}" : "."} diff --git a/Library/Homebrew/extend/os/mac/missing_formula.rb b/Library/Homebrew/extend/os/mac/missing_formula.rb index bcf0eb25d..ea6d50112 100644 --- a/Library/Homebrew/extend/os/mac/missing_formula.rb +++ b/Library/Homebrew/extend/os/mac/missing_formula.rb @@ -5,12 +5,12 @@ module Homebrew case name.downcase when "xcode" if MacOS.version >= :lion - <<-EOS.undent - Xcode can be installed from the App Store. + <<~EOS + Xcode can be installed from the App Store. EOS else - <<-EOS.undent - Xcode can be installed from #{Formatter.url("https://developer.apple.com/download/more/")}. + <<~EOS + Xcode can be installed from #{Formatter.url("https://developer.apple.com/download/more/")}. EOS end else diff --git a/Library/Homebrew/extend/os/mac/requirements/osxfuse_requirement.rb b/Library/Homebrew/extend/os/mac/requirements/osxfuse_requirement.rb index 8c898a272..3f10a951a 100644 --- a/Library/Homebrew/extend/os/mac/requirements/osxfuse_requirement.rb +++ b/Library/Homebrew/extend/os/mac/requirements/osxfuse_requirement.rb @@ -26,7 +26,7 @@ class NonBinaryOsxfuseRequirement < Requirement satisfy(build_env: false) { HOMEBREW_PREFIX.to_s != "/usr/local" || !OsxfuseRequirement.binary_osxfuse_installed? } def message - <<-EOS.undent + <<~EOS osxfuse is already installed from the binary distribution and conflicts with this formula. EOS diff --git a/Library/Homebrew/extend/pathname.rb b/Library/Homebrew/extend/pathname.rb index e1acd1f77..b4c7ca959 100644 --- a/Library/Homebrew/extend/pathname.rb +++ b/Library/Homebrew/extend/pathname.rb @@ -186,7 +186,7 @@ class Pathname begin tf.chown(uid, gid) tf.chmod(old_stat.mode) - rescue Errno::EPERM + rescue Errno::EPERM # rubocop:disable Lint/HandleExceptions end File.rename(tf.path, self) @@ -403,7 +403,7 @@ class Pathname mkpath targets.each do |target| target = Pathname.new(target) # allow pathnames or strings - join(target.basename).write <<-EOS.undent + join(target.basename).write <<~EOS #!/bin/bash exec "#{target}" "$@" EOS @@ -415,9 +415,9 @@ class Pathname env_export = "" env.each { |key, value| env_export += "#{key}=\"#{value}\" " } dirname.mkpath - write <<-EOS.undent - #!/bin/bash - #{env_export}exec "#{target}" "$@" + write <<~EOS + #!/bin/bash + #{env_export}exec "#{target}" "$@" EOS end @@ -435,7 +435,7 @@ class Pathname # Writes an exec script that invokes a java jar def write_jar_script(target_jar, script_name, java_opts = "") mkpath - join(script_name).write <<-EOS.undent + join(script_name).write <<~EOS #!/bin/bash exec java #{java_opts} -jar #{target_jar} "$@" EOS diff --git a/Library/Homebrew/extend/string.rb b/Library/Homebrew/extend/string.rb index b96f12994..c94bfc834 100644 --- a/Library/Homebrew/extend/string.rb +++ b/Library/Homebrew/extend/string.rb @@ -2,23 +2,6 @@ require_relative "../vendor/backports/string" class String - def undent - gsub(/^[ \t]{#{(slice(/^[ \t]+/) || '').length}}/, "") - end - alias unindent undent - - # eg: - # if foo then <<-EOS.undent_________________________________________________________72 - # Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do - # eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad - # minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip - # ex ea commodo consequat. Duis aute irure dolor in reprehenderit in - # voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur - # sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt - # mollit anim id est laborum. - # EOS - alias undent_________________________________________________________72 undent - # String.chomp, but if result is empty: returns nil instead. # Allows `chuzzle || foo` short-circuits. def chuzzle diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index d999b9c5f..1765f20c1 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -839,7 +839,7 @@ class Formula # This method can be overridden to provide a plist. # For more examples read Apple's handy manpage: # https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man5/plist.5.html - # <pre>def plist; <<-EOS.undent + # <pre>def plist; <<~EOS # <?xml version="1.0" encoding="UTF-8"?> # <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> # <plist version="1.0"> @@ -986,13 +986,13 @@ class Formula # to installation through a different package manager on a different OS. # @return [String] # <pre>def caveats - # <<-EOS.undent + # <<~EOS # Are optional. Something the user should know? # EOS # end</pre> # # <pre>def caveats - # s = <<-EOS.undent + # s = <<~EOS # Print some important notice to the user when `brew info <formula>` is # called or when brewing a formula. # This is optional. You can use all the vars like #{version} here. @@ -1041,14 +1041,14 @@ class Formula # keg's formula is deleted. begin keg = Keg.for(path) - rescue NotAKegError, Errno::ENOENT + rescue NotAKegError, Errno::ENOENT # rubocop:disable Lint/HandleExceptions # file doesn't belong to any keg. else tab_tap = Tab.for_keg(keg).tap return false if tab_tap.nil? # this keg doesn't below to any core/tap formula, most likely coming from a DIY install. begin Formulary.factory(keg.name) - rescue FormulaUnavailableError + rescue FormulaUnavailableError # rubocop:disable Lint/HandleExceptions # formula for this keg is deleted, so defer to whitelist rescue TapFormulaAmbiguityError, TapFormulaWithOldnameAmbiguityError return false # this keg belongs to another formula @@ -1379,12 +1379,13 @@ class Formula # An array of all installed {Formula} # @private def self.installed - @installed ||= racks.map do |rack| + @installed ||= racks.flat_map do |rack| begin Formulary.from_rack(rack) rescue FormulaUnavailableError, TapFormulaAmbiguityError, TapFormulaWithOldnameAmbiguityError + [] end - end.compact.uniq(&:name) + end.uniq(&:name) end def self.installed_with_alias_path(alias_path) @@ -1642,7 +1643,7 @@ class Formula with_logging("test") do test end - rescue Exception + rescue Exception # rubocop:disable Lint/RescueException staging.retain! if ARGV.debug? raise end @@ -1667,8 +1668,7 @@ class Formula end # @private - def test - end + def test; end # @private def test_fixtures(file) @@ -1683,8 +1683,7 @@ class Formula # system "./configure", "--prefix=#{prefix}" # system "make", "install" # end</pre> - def install - end + def install; end protected @@ -1692,7 +1691,7 @@ class Formula # keep Homebrew's site-packages in sys.path when using system Python user_site_packages = home/"Library/Python/2.7/lib/python/site-packages" user_site_packages.mkpath - (user_site_packages/"homebrew.pth").write <<-EOS.undent + (user_site_packages/"homebrew.pth").write <<~EOS import site; site.addsitedir("#{HOMEBREW_PREFIX}/lib/python2.7/site-packages") import sys, os; sys.path = (os.environ["PYTHONPATH"].split(os.pathsep) if "PYTHONPATH" in os.environ else []) + ["#{HOMEBREW_PREFIX}/lib/python2.7/site-packages"] + sys.path EOS @@ -1932,28 +1931,28 @@ class Formula end end - def self.method_added(method) - case method - when :brew - raise "You cannot override Formula#brew in class #{name}" - when :test - define_method(:test_defined?) { true } - when :options - instance = allocate + # The methods below define the formula DSL. + class << self + include BuildEnvironment::DSL - specs.each do |spec| - instance.options.each do |opt, desc| - spec.option(opt[/^--(.+)$/, 1], desc) + def method_added(method) + case method + when :brew + raise "You cannot override Formula#brew in class #{name}" + when :test + define_method(:test_defined?) { true } + when :options + instance = allocate + + specs.each do |spec| + instance.options.each do |opt, desc| + spec.option(opt[/^--(.+)$/, 1], desc) + end end - end - remove_method(:options) + remove_method(:options) + end end - end - - # The methods below define the formula DSL. - class << self - include BuildEnvironment::DSL # The reason for why this software is not linked (by default) to # {::HOMEBREW_PREFIX}. @@ -2395,7 +2394,7 @@ class Formula # and building the software was ok. # <pre>system bin/"foobar", "--version"</pre> # - # <pre>(testpath/"test.file").write <<-EOS.undent + # <pre>(testpath/"test.file").write <<~EOS # writing some test file, if you need to # EOS # assert_equal "OK", shell_output("test_command test.file").strip</pre> diff --git a/Library/Homebrew/formula_cellar_checks.rb b/Library/Homebrew/formula_cellar_checks.rb index 6c433e420..471a5ea2f 100644 --- a/Library/Homebrew/formula_cellar_checks.rb +++ b/Library/Homebrew/formula_cellar_checks.rb @@ -12,7 +12,7 @@ module FormulaCellarChecks prefix_bin = prefix_bin.realpath return if ORIGINAL_PATHS.include? prefix_bin - <<-EOS.undent + <<~EOS #{prefix_bin} is not in your PATH You can amend this by altering your #{Utils::Shell.profile} file EOS @@ -22,7 +22,7 @@ module FormulaCellarChecks # Check for man pages that aren't in share/man return unless (formula.prefix/"man").directory? - <<-EOS.undent + <<~EOS A top-level "man" directory was found Homebrew requires that man pages live under share. This can often be fixed by passing "--mandir=\#{man}" to configure. @@ -33,7 +33,7 @@ module FormulaCellarChecks # Check for info pages that aren't in share/info return unless (formula.prefix/"info").directory? - <<-EOS.undent + <<~EOS A top-level "info" directory was found Homebrew suggests that info pages live under share. This can often be fixed by passing "--infodir=\#{info}" to configure. @@ -45,7 +45,7 @@ module FormulaCellarChecks jars = formula.lib.children.select { |g| g.extname == ".jar" } return if jars.empty? - <<-EOS.undent + <<~EOS JARs were installed to "#{formula.lib}" Installing JARs to "lib" can cause conflicts between packages. For Java software, it is typically better for the formula to @@ -67,7 +67,7 @@ module FormulaCellarChecks end return if non_libraries.empty? - <<-EOS.undent + <<~EOS Non-libraries were installed to "#{formula.lib}" Installing non-libraries to "lib" is discouraged. The offending files are: @@ -81,7 +81,7 @@ module FormulaCellarChecks non_exes = bin.children.select { |g| g.directory? || !g.executable? } return if non_exes.empty? - <<-EOS.undent + <<~EOS Non-executables were installed to "#{bin}" The offending files are: #{non_exes * "\n "} @@ -94,7 +94,7 @@ module FormulaCellarChecks generics = bin.children.select { |g| generic_names.include? g.basename.to_s } return if generics.empty? - <<-EOS.undent + <<~EOS Generic binaries were installed to "#{bin}" Binaries with generic names are likely to conflict with other software, and suggest that this software should be installed to "libexec" and then @@ -109,7 +109,7 @@ module FormulaCellarChecks pth_found = Dir["#{lib}/python{2.7,3}*/site-packages/easy-install.pth"].map { |f| File.dirname(f) } return if pth_found.empty? - <<-EOS.undent + <<~EOS easy-install.pth files were found These .pth files are likely to cause link conflicts. Please invoke setup.py using Language::Python.setup_install_args. @@ -128,7 +128,7 @@ module FormulaCellarChecks end return unless bad_dir_name - <<-EOS + <<~EOS Emacs Lisp files were installed into the wrong site-lisp subdirectory. They should be installed into: #{share}/emacs/site-lisp/#{name} @@ -142,7 +142,7 @@ module FormulaCellarChecks elisps = (share/"emacs/site-lisp").children.select { |file| %w[.el .elc].include? file.extname } return if elisps.empty? - <<-EOS.undent + <<~EOS Emacs Lisp files were linked directly to #{HOMEBREW_PREFIX}/share/emacs/site-lisp This may cause conflicts with other packages. They should instead be installed into: diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb index 56238ad73..42abe5171 100644 --- a/Library/Homebrew/formula_installer.rb +++ b/Library/Homebrew/formula_installer.rb @@ -58,13 +58,14 @@ class FormulaInstaller @options = Options.new @invalid_option_names = [] @requirement_messages = [] - - @@attempted ||= Set.new - @poured_bottle = false @pour_failed = false end + def self.attempted + @attempted ||= Set.new + end + # When no build tools are available and build flags are passed through ARGV, # it's necessary to interrupt the user before any sort of installation # can proceed. Only invoked when the user has no developer tools. @@ -92,7 +93,7 @@ class FormulaInstaller return false if formula.bottle_disabled? unless formula.pour_bottle? if install_bottle_options[:warn] && formula.pour_bottle_check_unsatisfied_reason - opoo <<-EOS.undent + opoo <<~EOS Building #{formula.full_name} from source: #{formula.pour_bottle_check_unsatisfied_reason} EOS @@ -103,7 +104,7 @@ class FormulaInstaller bottle = formula.bottle_specification unless bottle.compatible_cellar? if install_bottle_options[:warn] - opoo <<-EOS.undent + opoo <<~EOS Building #{formula.full_name} from source: The bottle needs a #{bottle.cellar} Cellar (yours is #{HOMEBREW_CELLAR}). EOS @@ -145,7 +146,7 @@ class FormulaInstaller end def check_install_sanity - raise FormulaInstallationAlreadyAttemptedError, formula if @@attempted.include?(formula) + raise FormulaInstallationAlreadyAttemptedError, formula if self.class.attempted.include?(formula) return if ignore_deps? @@ -164,14 +165,14 @@ class FormulaInstaller end unless recursive_dependencies.empty? - raise CannotInstallFormulaError, <<-EOS.undent + raise CannotInstallFormulaError, <<~EOS #{formula.full_name} contains a recursive dependency on itself: #{recursive_dependencies.join("\n ")} EOS end if recursive_formulae.flat_map(&:recursive_dependencies).map(&:to_s).include?(formula.name) - raise CannotInstallFormulaError, <<-EOS.undent + raise CannotInstallFormulaError, <<~EOS #{formula.full_name} contains a recursive dependency on itself! EOS end @@ -187,7 +188,7 @@ class FormulaInstaller version_conflicts += version_hash[unversioned_name] end unless version_conflicts.empty? - raise CannotInstallFormulaError, <<-EOS.undent + raise CannotInstallFormulaError, <<~EOS #{formula.full_name} contains conflicting version recursive dependencies: #{version_conflicts.to_a.join ", "} View these with `brew deps --tree #{formula.full_name}`. @@ -220,16 +221,16 @@ class FormulaInstaller # function but after instantiating this class so that it can avoid having to # relink the active keg if possible (because it is slow). if formula.linked_keg.directory? - message = <<-EOS.undent + message = <<~EOS #{formula.name} #{formula.linked_version} is already installed EOS message += if formula.outdated? && !formula.head? - <<-EOS.undent + <<~EOS To upgrade to #{formula.pkg_version}, run `brew upgrade #{formula.name}` EOS else # some other version is already installed *and* linked - <<-EOS.undent + <<~EOS To install #{formula.pkg_version}, first run `brew unlink #{formula.name}` EOS end @@ -287,12 +288,12 @@ class FormulaInstaller end end - @@attempted << formula + self.class.attempted << formula if pour_bottle?(warn: true) begin pour - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException # any exceptions must leave us with nothing installed ignore_interrupts do formula.prefix.rmtree if formula.prefix.directory? @@ -354,7 +355,7 @@ class FormulaInstaller rescue FormulaUnavailableError => e # If the formula name doesn't exist any more then complain but don't # stop installation from continuing. - opoo <<-EOS.undent + opoo <<~EOS #{formula}: #{e.message} 'conflicts_with \"#{c.name}\"' should be removed from #{formula.path.basename}. EOS @@ -567,7 +568,7 @@ class FormulaInstaller oh1 "Installing #{formula.full_name} dependency: #{Formatter.identifier(dep.name)}" fi.install fi.finish - rescue Exception + rescue Exception # rubocop:disable Lint/RescueException ignore_interrupts do tmp_keg.rename(installed_keg) if tmp_keg && !installed_keg.directory? linked_keg.link if keg_was_linked @@ -723,7 +724,7 @@ class FormulaInstaller if !formula.prefix.directory? || Keg.new(formula.prefix).empty_installation? raise "Empty installation" end - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException e.options = display_options(formula) if e.is_a?(BuildError) ignore_interrupts do # any exceptions must leave us with nothing installed @@ -784,7 +785,7 @@ class FormulaInstaller puts " brew link #{formula.name}" @show_summary_heading = true Homebrew.failed = true - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException onoe "An unexpected error occurred during the `brew link` step" puts "The formula built, but is not symlinked into #{HOMEBREW_PREFIX}" puts e @@ -815,7 +816,7 @@ class FormulaInstaller formula.plist_path.chmod 0644 log = formula.var/"log" log.mkpath if formula.plist.include? log.to_s - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException onoe "Failed to install plist file" ohai e, e.backtrace if debug? Homebrew.failed = true @@ -823,7 +824,7 @@ class FormulaInstaller def fix_dynamic_linkage(keg) keg.fix_dynamic_linkage - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException onoe "Failed to fix install linkage" puts "The formula built, but you may encounter issues using it or linking other" puts "formula against it." @@ -835,7 +836,7 @@ class FormulaInstaller def clean ohai "Cleaning" if verbose? Cleaner.new(formula).clean - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException opoo "The cleaning step did not complete successfully" puts "Still, the installation was successful, so we will link it into your prefix" ohai e, e.backtrace if debug? @@ -845,7 +846,7 @@ class FormulaInstaller def post_install Homebrew.run_post_install(formula) - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException opoo "The post-install step did not complete successfully" puts "You can try again using `brew postinstall #{formula.full_name}`" ohai e, e.backtrace if debug? @@ -905,27 +906,31 @@ class FormulaInstaller super end + def self.locked + @locked ||= [] + end + private attr_predicate :hold_locks? def lock - return unless (@@locked ||= []).empty? + return unless self.class.locked.empty? unless ignore_deps? formula.recursive_dependencies.each do |dep| - @@locked << dep.to_formula + self.class.locked << dep.to_formula end end - @@locked.unshift(formula) - @@locked.uniq! - @@locked.each(&:lock) + self.class.locked.unshift(formula) + self.class.locked.uniq! + self.class.locked.each(&:lock) @hold_locks = true end def unlock return unless hold_locks? - @@locked.each(&:unlock) - @@locked.clear + self.class.locked.each(&:unlock) + self.class.locked.clear @hold_locks = false end diff --git a/Library/Homebrew/formula_support.rb b/Library/Homebrew/formula_support.rb index 2c9c19187..53fd61db8 100644 --- a/Library/Homebrew/formula_support.rb +++ b/Library/Homebrew/formula_support.rb @@ -33,33 +33,33 @@ class KegOnlyReason def to_s return @explanation unless @explanation.empty? case @reason - when :versioned_formula then <<-EOS.undent + when :versioned_formula then <<~EOS this is an alternate version of another formula EOS - when :provided_by_macos, :provided_by_osx then <<-EOS.undent + when :provided_by_macos, :provided_by_osx then <<~EOS macOS already provides this software and installing another version in parallel can cause all kinds of trouble EOS - when :shadowed_by_macos, :shadowed_by_osx then <<-EOS.undent + when :shadowed_by_macos, :shadowed_by_osx then <<~EOS macOS provides similar software and installing this software in parallel can cause all kinds of trouble EOS - when :provided_pre_mountain_lion then <<-EOS.undent + when :provided_pre_mountain_lion then <<~EOS macOS already provides this software in versions before Mountain Lion EOS - when :provided_pre_mavericks then <<-EOS.undent + when :provided_pre_mavericks then <<~EOS macOS already provides this software in versions before Mavericks EOS - when :provided_pre_el_capitan then <<-EOS.undent + when :provided_pre_el_capitan then <<~EOS macOS already provides this software in versions before El Capitan EOS - when :provided_pre_high_sierra then <<-EOS.undent + when :provided_pre_high_sierra then <<~EOS macOS already provides this software in versions before High Sierra EOS - when :provided_until_xcode43 then <<-EOS.undent + when :provided_until_xcode43 then <<~EOS Xcode provides this software prior to version 4.3 EOS - when :provided_until_xcode5 then <<-EOS.undent + when :provided_until_xcode5 then <<~EOS Xcode provides this software prior to version 5 EOS else diff --git a/Library/Homebrew/formula_versions.rb b/Library/Homebrew/formula_versions.rb index bb6803567..c10c69e67 100644 --- a/Library/Homebrew/formula_versions.rb +++ b/Library/Homebrew/formula_versions.rb @@ -44,7 +44,7 @@ class FormulaVersions # continue walking the history ohai "#{e} in #{name} at revision #{rev}", e.backtrace if ARGV.debug? rescue FormulaUnavailableError - # Suppress this error + return ensure Homebrew.raise_deprecation_exceptions = false end diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb index 0eb34ee2a..7eb85ed97 100644 --- a/Library/Homebrew/formulary.rb +++ b/Library/Homebrew/formulary.rb @@ -1,18 +1,19 @@ require "digest/md5" require "tap" +require "extend/cachable" # The Formulary is responsible for creating instances of Formula. # It is not meant to be used directly from formulae. module Formulary - FORMULAE = {} + extend Cachable def self.formula_class_defined?(path) - FORMULAE.key?(path) + cache.key?(path) end def self.formula_class_get(path) - FORMULAE.fetch(path) + cache.fetch(path) end def self.load_formula(name, path, contents, namespace) @@ -44,7 +45,7 @@ module Formulary contents = path.open("r") { |f| ensure_utf8_encoding(f).read } namespace = "FormulaNamespace#{Digest::MD5.hexdigest(path.to_s)}" klass = load_formula(name, path, contents, namespace) - FORMULAE[path] = klass + cache[path] = klass end if IO.method_defined?(:set_encoding) @@ -127,7 +128,7 @@ module Formulary formula = begin Formulary.from_contents name, @bottle_filename, contents, spec rescue FormulaUnreadableError => e - opoo <<-EOS.undent + opoo <<~EOS Unreadable formula in #{@bottle_filename}: #{e} EOS @@ -442,7 +443,7 @@ module Formulary if possible_pinned_tap_formulae.size == 1 selected_formula = factory(possible_pinned_tap_formulae.first, spec) if core_path(ref).file? - opoo <<-EOS.undent + opoo <<~EOS #{ref} is provided by core, but is now shadowed by #{selected_formula.full_name}. To refer to the core formula, use Homebrew/core/#{ref} instead. EOS diff --git a/Library/Homebrew/gpg.rb b/Library/Homebrew/gpg.rb index de2089dda..83b525b44 100644 --- a/Library/Homebrew/gpg.rb +++ b/Library/Homebrew/gpg.rb @@ -11,18 +11,12 @@ class Gpg end end - def self.gpg - find_gpg("gpg") + def self.executable + find_gpg("gpg") || find_gpg("gpg2") end - def self.gpg2 - find_gpg("gpg2") - end - - GPG_EXECUTABLE = gpg || gpg2 - def self.available? - File.executable?(GPG_EXECUTABLE.to_s) + File.executable?(executable.to_s) end def self.version @@ -32,7 +26,7 @@ class Gpg def self.create_test_key(path) odie "No GPG present to test against!" unless available? - (path/"batch.gpg").write <<-EOS.undent + (path/"batch.gpg").write <<~EOS Key-Type: RSA Key-Length: 2048 Subkey-Type: RSA @@ -43,12 +37,12 @@ class Gpg %no-protection %commit EOS - system GPG_EXECUTABLE, "--batch", "--gen-key", "batch.gpg" + system executable, "--batch", "--gen-key", "batch.gpg" end def self.cleanup_test_processes! odie "No GPG present to test against!" unless available? - gpgconf = Pathname.new(GPG_EXECUTABLE).parent/"gpgconf" + gpgconf = Pathname.new(executable).parent/"gpgconf" system gpgconf, "--kill", "gpg-agent" system gpgconf, "--homedir", "keyrings/live", "--kill", diff --git a/Library/Homebrew/keg.rb b/Library/Homebrew/keg.rb index 677a97c85..bb9778c81 100644 --- a/Library/Homebrew/keg.rb +++ b/Library/Homebrew/keg.rb @@ -6,7 +6,7 @@ require "ostruct" class Keg class AlreadyLinkedError < RuntimeError def initialize(keg) - super <<-EOS.undent + super <<~EOS Cannot link #{keg.name} Another version is already linked: #{keg.linked_keg_record.resolved_path} EOS @@ -32,9 +32,9 @@ class Keg rescue NotAKegError, Errno::ENOENT "already exists. You may want to remove it:\n rm '#{dst}'\n" else - <<-EOS.undent - is a symlink belonging to #{conflict.name}. You can unlink it: - brew unlink #{conflict.name} + <<~EOS + is a symlink belonging to #{conflict.name}. You can unlink it: + brew unlink #{conflict.name} EOS end @@ -42,7 +42,7 @@ class Keg s = [] s << "Could not symlink #{src}" s << "Target #{dst}" << suggestion - s << <<-EOS.undent + s << <<~EOS To force the link and overwrite all conflicting files: brew link --overwrite #{keg.name} @@ -54,7 +54,7 @@ class Keg end class DirectoryNotWritableError < LinkError - def to_s; <<-EOS.undent + def to_s; <<~EOS Could not symlink #{src} #{dst.dirname} is not writable. EOS diff --git a/Library/Homebrew/language/python.rb b/Library/Homebrew/language/python.rb index bfec556d0..931cc59fc 100644 --- a/Library/Homebrew/language/python.rb +++ b/Library/Homebrew/language/python.rb @@ -46,7 +46,7 @@ module Language end def self.in_sys_path?(python, path) - script = <<-EOS.undent + script = <<~EOS import os, sys [os.path.realpath(p) for p in sys.path].index(os.path.realpath("#{path}")) EOS @@ -54,7 +54,7 @@ module Language end def self.setup_install_args(prefix) - shim = <<-EOS.undent + shim = <<~EOS import setuptools, tokenize __file__ = 'setup.py' exec(compile(getattr(tokenize, 'open', open)(__file__).read() diff --git a/Library/Homebrew/migrator.rb b/Library/Homebrew/migrator.rb index 7ecdafe2f..8664d474b 100644 --- a/Library/Homebrew/migrator.rb +++ b/Library/Homebrew/migrator.rb @@ -6,7 +6,7 @@ require "tab" class Migrator class MigrationNeededError < RuntimeError def initialize(formula) - super <<-EOS.undent + super <<~EOS #{formula.oldname} was renamed to #{formula.name} and needs to be migrated. Please run `brew migrate #{formula.oldname}` EOS @@ -33,10 +33,9 @@ class Migrator "Please try to use fully-qualified #{tap}/#{formula.oldname} to refer the formula.\n" end - super <<-EOS.undent - #{formula.name} from #{formula.tap} is given, but old name #{formula.oldname} was installed from #{tap ? tap : "path or url"}. - - #{msg}To force migrate use `brew migrate --force #{formula.oldname}`. + super <<~EOS + #{formula.name} from #{formula.tap} is given, but old name #{formula.oldname} was installed from #{tap ? tap : "path or url"}. + #{msg}To force migrate use `brew migrate --force #{formula.oldname}`. EOS end end @@ -100,7 +99,7 @@ class Migrator begin migrator = Migrator.new(formula) migrator.migrate - rescue Exception => e + rescue => e onoe e end end @@ -196,7 +195,7 @@ class Migrator update_tabs rescue Interrupt ignore_interrupts { backup_oldname } - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException onoe "Error occurred while migrating." puts e puts e.backtrace if ARGV.debug? @@ -304,7 +303,7 @@ class Migrator puts puts "You can try again using:" puts " brew link #{formula.name}" - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException onoe "An unexpected error occurred during linking" puts e puts e.backtrace if ARGV.debug? diff --git a/Library/Homebrew/missing_formula.rb b/Library/Homebrew/missing_formula.rb index a3d182a2b..97ed5749a 100644 --- a/Library/Homebrew/missing_formula.rb +++ b/Library/Homebrew/missing_formula.rb @@ -12,10 +12,10 @@ module Homebrew def blacklisted_reason(name) case name.downcase - when "gem", /^rubygems?$/ then <<-EOS.undent + when "gem", /^rubygems?$/ then <<~EOS Homebrew provides gem via: `brew install ruby`. EOS - when "tex", "tex-live", "texlive", "latex" then <<-EOS.undent + when "tex", "tex-live", "texlive", "latex" then <<~EOS Installing TeX from source is weird and gross, requires a lot of patches, and only builds 32-bit (and thus can't use Homebrew dependencies) @@ -24,42 +24,42 @@ module Homebrew You can install it with Homebrew-Cask: brew cask install mactex EOS - when "pip" then <<-EOS.undent + when "pip" then <<~EOS Homebrew provides pip via: `brew install python`. However you will then have two Pythons installed on your Mac, so alternatively you can install pip via the instructions at: #{Formatter.url("https://pip.readthedocs.io/en/stable/installing/")} EOS - when "pil" then <<-EOS.undent + when "pil" then <<~EOS Instead of PIL, consider `pip2 install pillow`. EOS - when "macruby" then <<-EOS.undent + when "macruby" then <<~EOS MacRuby is not packaged and is on an indefinite development hiatus. You can read more about it at: #{Formatter.url("https://github.com/MacRuby/MacRuby")} EOS when /(lib)?lzma/ "lzma is now part of the xz formula." - when "gtest", "googletest", "google-test" then <<-EOS.undent + when "gtest", "googletest", "google-test" then <<~EOS Installing gtest system-wide is not recommended; it should be vendored in your projects that use it. EOS - when "gmock", "googlemock", "google-mock" then <<-EOS.undent + when "gmock", "googlemock", "google-mock" then <<~EOS Installing gmock system-wide is not recommended; it should be vendored in your projects that use it. EOS - when "sshpass" then <<-EOS.undent + when "sshpass" then <<~EOS We won't add sshpass because it makes it too easy for novice SSH users to ruin SSH's security. EOS - when "gsutil" then <<-EOS.undent + when "gsutil" then <<~EOS Install gsutil with `pip2 install gsutil` EOS - when "gfortran" then <<-EOS.undent + when "gfortran" then <<~EOS GNU Fortran is now provided as part of GCC, and can be installed with: brew install gcc EOS - when "play" then <<-EOS.undent + when "play" then <<~EOS Play 2.3 replaces the play command with activator: brew install typesafe-activator @@ -67,7 +67,7 @@ module Homebrew #{Formatter.url("https://www.playframework.com/documentation/2.3.x/Migration23")} #{Formatter.url("https://www.playframework.com/documentation/2.3.x/Highlights23")} EOS - when "haskell-platform" then <<-EOS.undent + when "haskell-platform" then <<~EOS We no longer package haskell-platform. Consider installing ghc and cabal-install instead: brew install ghc cabal-install @@ -75,10 +75,10 @@ module Homebrew You can install with Homebrew-Cask: brew cask install haskell-platform EOS - when "mysqldump-secure" then <<-EOS.undent + when "mysqldump-secure" then <<~EOS The creator of mysqldump-secure tried to game our popularity metrics. EOS - when "ngrok" then <<-EOS.undent + when "ngrok" then <<~EOS Upstream sunsetted 1.x in March 2016 and 2.x is not open-source. If you wish to use the 2.x release you can install with Homebrew-Cask: @@ -98,12 +98,12 @@ module Homebrew new_tap_user, new_tap_repo, = new_tap.split("/") new_tap_name = "#{new_tap_user}/#{new_tap_repo}" - message = <<-EOS.undent + message = <<~EOS It was migrated from #{old_tap} to #{new_tap}. EOS break if new_tap_name == CoreTap.instance.name - message += <<-EOS.undent + message += <<~EOS You can access it again by running: brew tap #{new_tap_name} EOS @@ -124,7 +124,7 @@ module Homebrew unless silent ohai "Searching for a previously deleted formula..." if (tap.path/".git/shallow").exist? - opoo <<-EOS.undent + opoo <<~EOS #{tap} is shallow clone. To get complete history run: git -C "$(brew --repo #{tap})" fetch --unshallow @@ -147,7 +147,7 @@ module Homebrew commit_message.sub!(/ \(#(\d+)\)$/, " (#{tap.issues_url}/\\1)") commit_message.gsub!(/(Closes|Fixes) #(\d+)/, "\\1 #{tap.issues_url}/\\2") - <<-EOS.undent + <<~EOS #{name} was deleted from #{tap.name} in commit #{short_hash}: #{commit_message} diff --git a/Library/Homebrew/os/mac.rb b/Library/Homebrew/os/mac.rb index 853f75140..cb4141f48 100644 --- a/Library/Homebrew/os/mac.rb +++ b/Library/Homebrew/os/mac.rb @@ -47,19 +47,11 @@ module OS end def languages - return @languages unless @languages.nil? - - @languages = Utils.popen_read("defaults", "read", ".GlobalPreferences", "AppleLanguages").scan(/[^ \n"(),]+/) - - if ENV["HOMEBREW_LANGUAGES"] - @languages = ENV["HOMEBREW_LANGUAGES"].split(",") + @languages - end - - if ARGV.value("language") - @languages = ARGV.value("language").split(",") + @languages - end - - @languages = @languages.uniq + @languages ||= [ + *ARGV.value("language")&.split(","), + *ENV["HOMEBREW_LANGUAGES"]&.split(","), + *Open3.capture2("defaults", "read", "-g", "AppleLanguages")[0].scan(/[^ \n"(),]+/), + ].uniq end def language @@ -209,6 +201,7 @@ module OS "8.3.2" => { clang: "8.1", clang_build: 802 }, "8.3.3" => { clang: "8.1", clang_build: 802 }, "9.0" => { clang: "9.0", clang_build: 900 }, + "9.0.1" => { clang: "9.0", clang_build: 900 }, }.freeze def compilers_standard? @@ -216,7 +209,7 @@ module OS send(:"#{method}_version") == build end rescue IndexError - onoe <<-EOS.undent + onoe <<~EOS Homebrew doesn't know what compiler versions ship with your version of Xcode (#{Xcode.version}). Please `brew update` and if that doesn't help, file an issue with the output of `brew --config`: diff --git a/Library/Homebrew/os/mac/keg.rb b/Library/Homebrew/os/mac/keg.rb index 6caadb1d7..6f2d65fb4 100644 --- a/Library/Homebrew/os/mac/keg.rb +++ b/Library/Homebrew/os/mac/keg.rb @@ -5,7 +5,7 @@ class Keg puts "Changing dylib ID of #{file}\n from #{file.dylib_id}\n to #{id}" if ARGV.debug? MachO::Tools.change_dylib_id(file, id, strict: false) rescue MachO::MachOError - onoe <<-EOS.undent + onoe <<~EOS Failed changing dylib ID of #{file} from #{file.dylib_id} to #{id} @@ -19,7 +19,7 @@ class Keg puts "Changing install name in #{file}\n from #{old}\n to #{new}" if ARGV.debug? MachO::Tools.change_install_name(file, old, new, strict: false) rescue MachO::MachOError - onoe <<-EOS.undent + onoe <<~EOS Failed changing install name in #{file} from #{old} to #{new} diff --git a/Library/Homebrew/os/mac/xcode.rb b/Library/Homebrew/os/mac/xcode.rb index 59e7026bd..81149fb4c 100644 --- a/Library/Homebrew/os/mac/xcode.rb +++ b/Library/Homebrew/os/mac/xcode.rb @@ -17,13 +17,13 @@ module OS when "10.9" then "6.2" when "10.10" then "7.2.1" when "10.11" then "8.2.1" - when "10.12" then "8.3.3" - when "10.13" then "9.0" + when "10.12" then "9.0.1" + when "10.13" then "9.0.1" else raise "macOS '#{MacOS.version}' is invalid" unless OS::Mac.prerelease? # Default to newest known version of Xcode for unreleased macOS versions. - "9.0" + "9.0.1" end end @@ -86,11 +86,11 @@ module OS def update_instructions if MacOS.version >= "10.9" && !OS::Mac.prerelease? - <<-EOS.undent + <<~EOS Xcode can be updated from the App Store. EOS else - <<-EOS.undent + <<~EOS Xcode can be updated from https://developer.apple.com/download/more/ EOS @@ -183,7 +183,7 @@ module OS end module CLT - extend self + module_function STANDALONE_PKG_ID = "com.apple.pkg.DeveloperToolsCLILeo".freeze FROM_XCODE_PKG_ID = "com.apple.pkg.DeveloperToolsCLI".freeze @@ -199,11 +199,11 @@ module OS def update_instructions if MacOS.version >= "10.9" - <<-EOS.undent + <<~EOS Update them from Software Update in the App Store. EOS elsif MacOS.version == "10.8" || MacOS.version == "10.7" - <<-EOS.undent + <<~EOS The standalone package can be obtained from https://developer.apple.com/download/more/ or it can be installed via Xcode's preferences. @@ -216,8 +216,8 @@ module OS # on the older supported platform for that Xcode release, i.e there's no # CLT package for 10.11 that contains the Clang version from Xcode 8. case MacOS.version - when "10.13" then "900.0.37" - when "10.12" then "802.0.42" + when "10.13" then "900.0.38" + when "10.12" then "900.0.38" when "10.11" then "800.0.42.1" when "10.10" then "700.1.81" when "10.9" then "600.0.57" diff --git a/Library/Homebrew/patch.rb b/Library/Homebrew/patch.rb index 7045adf5e..a44add10e 100644 --- a/Library/Homebrew/patch.rb +++ b/Library/Homebrew/patch.rb @@ -60,8 +60,7 @@ class EmbeddedPatch false end - def contents - end + def contents; end def apply data = contents.gsub("HOMEBREW_PREFIX", HOMEBREW_PREFIX) @@ -87,10 +86,13 @@ class DATAPatch < EmbeddedPatch def contents data = "" path.open("rb") do |f| - begin + loop do line = f.gets - end until line.nil? || line =~ /^__END__$/ - data << line while line = f.gets + break if line.nil? || line =~ /^__END__$/ + end + while line = f.gets + data << line + end end data end @@ -137,7 +139,7 @@ class ExternalPatch if patch_files.empty? children = patch_dir.children if children.length != 1 || !children.first.file? - raise MissingApplyError, <<-EOS.undent + raise MissingApplyError, <<~EOS There should be exactly one patch file in the staging directory unless the "apply" method was used one or more times in the patch-do block. EOS diff --git a/Library/Homebrew/postinstall.rb b/Library/Homebrew/postinstall.rb index 0b6d8f6b0..53a5b7e75 100644 --- a/Library/Homebrew/postinstall.rb +++ b/Library/Homebrew/postinstall.rb @@ -14,7 +14,7 @@ begin formula = ARGV.resolved_formulae.first formula.extend(Debrew::Formula) if ARGV.debug? formula.run_post_install -rescue Exception => e +rescue Exception => e # rubocop:disable Lint/RescueException Marshal.dump(e, error_pipe) error_pipe.close exit! 1 diff --git a/Library/Homebrew/readall.rb b/Library/Homebrew/readall.rb index 3595c16be..5f4fd947c 100644 --- a/Library/Homebrew/readall.rb +++ b/Library/Homebrew/readall.rb @@ -52,7 +52,7 @@ module Readall Formulary.factory(file) rescue Interrupt raise - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException onoe "Invalid formula: #{file}" puts e failed = true diff --git a/Library/Homebrew/requirement.rb b/Library/Homebrew/requirement.rb index 1ec8580c4..a69c68466 100644 --- a/Library/Homebrew/requirement.rb +++ b/Library/Homebrew/requirement.rb @@ -35,18 +35,16 @@ class Requirement _, _, class_name = self.class.to_s.rpartition "::" s = "#{class_name} unsatisfied!\n" if cask - s += <<-EOS.undent - + s += <<~EOS You can install with Homebrew-Cask: - brew cask install #{cask} + brew cask install #{cask} EOS end if download - s += <<-EOS.undent - + s += <<~EOS You can download from: - #{download} + #{download} EOS end s diff --git a/Library/Homebrew/requirements.rb b/Library/Homebrew/requirements.rb index 553beb2a2..35a0c242c 100644 --- a/Library/Homebrew/requirements.rb +++ b/Library/Homebrew/requirements.rb @@ -2,7 +2,8 @@ require "requirement" require "requirements/fortran_requirement" require "requirements/gpg2_requirement" require "requirements/language_module_requirement" -require "requirements/minimum_macos_requirement" +require "requirements/linux_requirement" +require "requirements/macos_requirement" require "requirements/maximum_macos_requirement" require "requirements/mpi_requirement" require "requirements/osxfuse_requirement" @@ -33,16 +34,16 @@ class XcodeRequirement < Requirement def message version = " #{@version}" if @version - message = <<-EOS.undent + message = <<~EOS A full installation of Xcode.app#{version} is required to compile this software. Installing just the Command Line Tools is not sufficient. EOS if MacOS.version >= :lion - message + <<-EOS.undent + message + <<~EOS Xcode can be installed from the App Store. EOS else - message + <<-EOS.undent + message + <<~EOS Xcode can be installed from #{Formatter.url("https://developer.apple.com/download/more/")}. EOS end @@ -82,7 +83,7 @@ class TeXRequirement < Requirement satisfy { which("tex") || which("latex") } def message - s = <<-EOS.undent + s = <<~EOS A LaTeX distribution is required for Homebrew to install this formula. Make sure that "/usr/texbin", or the location you installed it to, is in diff --git a/Library/Homebrew/requirements/gpg2_requirement.rb b/Library/Homebrew/requirements/gpg2_requirement.rb index ebdd71f6e..04097f9be 100644 --- a/Library/Homebrew/requirements/gpg2_requirement.rb +++ b/Library/Homebrew/requirements/gpg2_requirement.rb @@ -8,5 +8,5 @@ class GPG2Requirement < Requirement # GPGTools installs GnuPG 2.0.x as a `gpg` symlink pointing # to `gpg2`. Our `gnupg` installs only a non-symlink `gpg`. # The aim is to retain support for any version above 2.0. - satisfy(build_env: false) { Gpg.gpg || Gpg.gpg2 } + satisfy(build_env: false) { Gpg.available? } end diff --git a/Library/Homebrew/requirements/java_requirement.rb b/Library/Homebrew/requirements/java_requirement.rb index de3a33eb4..949978dbd 100644 --- a/Library/Homebrew/requirements/java_requirement.rb +++ b/Library/Homebrew/requirements/java_requirement.rb @@ -11,7 +11,7 @@ class JavaRequirement < Requirement end def initialize(tags) - @version = tags.shift if /(\d\.)+\d/ =~ tags.first + @version = tags.shift if /(\d+\.)+\d/ =~ tags.first super end @@ -103,7 +103,7 @@ class JavaRequirement < Requirement end def satisfies_version(java) - java_version_s = Utils.popen_read("#{java} -version 2>&1")[/1.\d/] + java_version_s = Utils.popen_read("#{java} -version 2>&1")[/\d+.\d/] return false unless java_version_s java_version = Version.create(java_version_s) needed_version = Version.create(version_without_plus) diff --git a/Library/Homebrew/requirements/language_module_requirement.rb b/Library/Homebrew/requirements/language_module_requirement.rb index 392bc9b7a..5ddce7a66 100644 --- a/Library/Homebrew/requirements/language_module_requirement.rb +++ b/Library/Homebrew/requirements/language_module_requirement.rb @@ -13,16 +13,15 @@ class LanguageModuleRequirement < Requirement satisfy(build_env: false) { quiet_system(*the_test) } def message - s = <<-EOS.undent + s = <<~EOS Unsatisfied dependency: #{@module_name} Homebrew does not provide special #{@language.to_s.capitalize} dependencies; install with: `#{command_line} #{@module_name}` EOS unless [:python, :perl, :ruby].include? @language - s += <<-EOS.undent - - You may need to: `brew install #{@language}` + s += <<~EOS + You may need to: `brew install #{@language}` EOS end diff --git a/Library/Homebrew/requirements/linux_requirement.rb b/Library/Homebrew/requirements/linux_requirement.rb new file mode 100644 index 000000000..cb4666e56 --- /dev/null +++ b/Library/Homebrew/requirements/linux_requirement.rb @@ -0,0 +1,9 @@ +class LinuxRequirement < Requirement + fatal true + + satisfy(build_env: false) { OS.linux? } + + def message + "Linux is required." + end +end diff --git a/Library/Homebrew/requirements/macos_requirement.rb b/Library/Homebrew/requirements/macos_requirement.rb new file mode 100644 index 000000000..c89144d2c --- /dev/null +++ b/Library/Homebrew/requirements/macos_requirement.rb @@ -0,0 +1,31 @@ +require "requirement" + +class MacOSRequirement < Requirement + fatal true + + def initialize(tags = []) + @version = MacOS::Version.from_symbol(tags.first) unless tags.empty? + super + end + + def minimum_version_specified? + OS.mac? && @version + end + + satisfy(build_env: false) do + next MacOS.version >= @version if minimum_version_specified? + next true if OS.mac? + next true if @version + false + end + + def message + return "macOS is required." unless minimum_version_specified? + "macOS #{@version.pretty_name} or newer is required." + end + + def display_s + return "macOS is required" unless minimum_version_specified? + "macOS >= #{@version}" + end +end diff --git a/Library/Homebrew/requirements/maximum_macos_requirement.rb b/Library/Homebrew/requirements/maximum_macos_requirement.rb index 6e798b478..9a8851390 100644 --- a/Library/Homebrew/requirements/maximum_macos_requirement.rb +++ b/Library/Homebrew/requirements/maximum_macos_requirement.rb @@ -11,7 +11,7 @@ class MaximumMacOSRequirement < Requirement satisfy(build_env: false) { MacOS.version <= @version } def message - <<-EOS.undent + <<~EOS This formula either does not compile or function as expected on macOS versions newer than #{@version.pretty_name} due to an upstream incompatibility. EOS diff --git a/Library/Homebrew/requirements/minimum_macos_requirement.rb b/Library/Homebrew/requirements/minimum_macos_requirement.rb deleted file mode 100644 index 2cb63f740..000000000 --- a/Library/Homebrew/requirements/minimum_macos_requirement.rb +++ /dev/null @@ -1,20 +0,0 @@ -require "requirement" - -class MinimumMacOSRequirement < Requirement - fatal true - - def initialize(tags) - @version = MacOS::Version.from_symbol(tags.first) - super - end - - satisfy(build_env: false) { MacOS.version >= @version } - - def message - "macOS #{@version.pretty_name} or newer is required." - end - - def display_s - "macOS >= #{@version}" - end -end diff --git a/Library/Homebrew/requirements/unsigned_kext_requirement.rb b/Library/Homebrew/requirements/unsigned_kext_requirement.rb index 2ffc8fda3..b58a20ea6 100644 --- a/Library/Homebrew/requirements/unsigned_kext_requirement.rb +++ b/Library/Homebrew/requirements/unsigned_kext_requirement.rb @@ -6,7 +6,7 @@ class UnsignedKextRequirement < Requirement satisfy(build_env: false) { MacOS.version < :yosemite } def message - s = <<-EOS.undent + s = <<~EOS Building this formula from source isn't possible due to OS X Yosemite (10.10) and above's strict unsigned kext ban. EOS diff --git a/Library/Homebrew/rubocops/conflicts_cop.rb b/Library/Homebrew/rubocops/conflicts_cop.rb index 6f05d0567..1cca3f8ae 100644 --- a/Library/Homebrew/rubocops/conflicts_cop.rb +++ b/Library/Homebrew/rubocops/conflicts_cop.rb @@ -6,7 +6,7 @@ module RuboCop module FormulaAudit # This cop audits versioned Formulae for `conflicts_with` class Conflicts < FormulaCop - MSG = <<-EOS.undent + MSG = <<~EOS.freeze Versioned formulae should not use `conflicts_with`. Use `keg_only :versioned_formula` instead. EOS diff --git a/Library/Homebrew/rubocops/extend/formula_cop.rb b/Library/Homebrew/rubocops/extend/formula_cop.rb index fccce0ded..7da4d0f10 100644 --- a/Library/Homebrew/rubocops/extend/formula_cop.rb +++ b/Library/Homebrew/rubocops/extend/formula_cop.rb @@ -56,6 +56,7 @@ module RuboCop # Returns all string nodes among the descendants of given node def find_strings(node) return [] if node.nil? + return node if node.str_type? node.each_descendant(:str) end @@ -101,7 +102,9 @@ module RuboCop def find_method_with_args(node, method_name, *args) methods = find_every_method_call_by_name(node, method_name) methods.each do |method| - yield method if parameters_passed?(method, *args) + next unless parameters_passed?(method, *args) + return true unless block_given? + yield method end end @@ -119,6 +122,7 @@ module RuboCop method.receiver.method_name != instance @offense_source_range = method.source_range @offensive_node = method + return true unless block_given? yield method end end @@ -167,19 +171,33 @@ module RuboCop type_match && name_match end - def_node_search :required_dependency?, <<-EOS.undent + # Find CONSTANTs in the source + # if block given, yield matching nodes + def find_const(node, const_name) + return if node.nil? + node.each_descendant(:const) do |const_node| + next unless const_node.const_name == const_name + @offensive_node = const_node + @offense_source_range = const_node.source_range + yield const_node if block_given? + return true + end + nil + end + + def_node_search :required_dependency?, <<~EOS (send nil :depends_on ({str sym} _)) EOS - def_node_search :required_dependency_name?, <<-EOS.undent + def_node_search :required_dependency_name?, <<~EOS (send nil :depends_on ({str sym} %1)) EOS - def_node_search :dependency_type_hash_match?, <<-EOS.undent + def_node_search :dependency_type_hash_match?, <<~EOS (hash (pair ({str sym} _) ({str sym} %1))) EOS - def_node_search :dependency_name_hash_match?, <<-EOS.undent + def_node_search :dependency_name_hash_match?, <<~EOS (hash (pair ({str sym} %1) ({str sym} _))) EOS @@ -222,15 +240,17 @@ module RuboCop end # Returns a method definition node with method_name - def find_method_def(node, method_name) + # Returns first method def if method_name is nil + def find_method_def(node, method_name = nil) return if node.nil? node.each_child_node(:def) do |def_node| def_method_name = method_name(def_node) - next unless method_name == def_method_name + next unless method_name == def_method_name || method_name.nil? @offensive_node = def_node @offense_source_range = def_node.source_range return def_node end + return if node.parent.nil? # If not found then, parent node becomes the offensive node @offensive_node = node.parent @offense_source_range = node.parent.source_range @@ -250,11 +270,15 @@ module RuboCop end # Check if method_name is called among the direct children nodes in the given node + # Check if the node itself is the method def method_called?(node, method_name) + if node.send_type? && node.method_name == method_name + offending_node(node) + return true + end node.each_child_node(:send) do |call_node| next unless call_node.method_name == method_name - @offensive_node = call_node - @offense_source_range = call_node.source_range + offending_node(call_node) return true end false @@ -291,6 +315,11 @@ module RuboCop true end + # Check if negation is present in the given node + def negated?(node) + method_called?(node, :!) + end + # Return all the caveats' string nodes in an array def caveats_strings find_strings(find_method_def(@body, :caveats)) diff --git a/Library/Homebrew/rubocops/formula_desc_cop.rb b/Library/Homebrew/rubocops/formula_desc_cop.rb index 2b613c9b4..05f60c9d5 100644 --- a/Library/Homebrew/rubocops/formula_desc_cop.rb +++ b/Library/Homebrew/rubocops/formula_desc_cop.rb @@ -18,12 +18,18 @@ module RuboCop return end - # Check if a formula's desc is too long + # Check the formula's desc length. Should be >0 and <80 characters. desc = parameters(desc_call).first + pure_desc_length = string_content(desc).length + if pure_desc_length.zero? + problem "The desc (description) should not be an empty string." + return + end + desc_length = "#{@formula_name}: #{string_content(desc)}".length max_desc_length = 80 return if desc_length <= max_desc_length - problem <<-EOS.undent + problem <<~EOS Description is too long. "name: desc" should be less than #{max_desc_length} characters. Length is calculated as #{@formula_name} + desc. (currently #{desc_length}) EOS diff --git a/Library/Homebrew/rubocops/lines_cop.rb b/Library/Homebrew/rubocops/lines_cop.rb index 01b13585c..9354f41f6 100644 --- a/Library/Homebrew/rubocops/lines_cop.rb +++ b/Library/Homebrew/rubocops/lines_cop.rb @@ -21,7 +21,7 @@ module RuboCop begin_pos = start_column(parent_class_node) end_pos = end_column(class_node) return unless begin_pos-end_pos != 3 - problem "Use a space in class inheritance: class #{class_name(class_node)} < #{class_name(parent_class_node)}" + problem "Use a space in class inheritance: class #{@formula_name.capitalize} < #{class_name(parent_class_node)}" end end @@ -53,6 +53,87 @@ module RuboCop end end + class AssertStatements < FormulaCop + def audit_formula(_node, _class_node, _parent_class_node, body_node) + find_every_method_call_by_name(body_node, :assert).each do |method| + if method_called_ever?(method, :include?) && !method_called_ever?(method, :!) + problem "Use `assert_match` instead of `assert ...include?`" + end + + if method_called_ever?(method, :exist?) && !method_called_ever?(method, :!) + problem "Use `assert_predicate <path_to_file>, :exist?` instead of `#{method.source}`" + end + + if method_called_ever?(method, :exist?) && method_called_ever?(method, :!) + problem "Use `refute_predicate <path_to_file>, :exist?` instead of `#{method.source}`" + end + + if method_called_ever?(method, :executable?) && !method_called_ever?(method, :!) + problem "Use `assert_predicate <path_to_file>, :executable?` instead of `#{method.source}`" + end + end + end + end + + class OptionDeclarations < FormulaCop + def audit_formula(_node, _class_node, _parent_class_node, body_node) + if find_method_def(body_node, :options) + problem "Use new-style option definitions" + end + + find_instance_method_call(body_node, :build, :without?) do |method| + next unless unless_modifier?(method.parent) + correct = method.source.gsub("out?", "?") + 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}" + end + + find_instance_method_call(body_node, :build, :with?) do |method| + next unless negated?(method.parent) + problem "Don't negate 'build.with?': use 'build.without?'" + end + + find_instance_method_call(body_node, :build, :without?) do |method| + next unless negated?(method.parent) + problem "Don't negate '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]}\"" + 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]}\"" + end + + find_instance_method_call(body_node, :build, :include?) do |method| + arg = parameters(method).first + next unless match = regex_match_group(arg, /with(out)?-(.*)/) + problem "Use build.with#{match[1]}? \"#{match[2]}\" instead of build.include? 'with#{match[1]}-#{match[2]}'" + end + + find_instance_method_call(body_node, :build, :include?) do |method| + arg = parameters(method).first + next unless match = regex_match_group(arg, /\-\-(.*)/) + problem "Reference '#{match[1]}' without dashes" + end + end + + def unless_modifier?(node) + return false unless node.if_type? + node.modifier_form? && node.unless? + end + end + class Miscellaneous < FormulaCop def audit_formula(_node, _class_node, _parent_class_node, body_node) # FileUtils is included in Formula @@ -81,18 +162,128 @@ module RuboCop end end + [:debug?, :verbose?, :value].each do |method_name| + find_instance_method_call(body_node, "ARGV", method_name) do + problem "Use build instead of ARGV to check options" + end + 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]}\"" + end + + # Avoid hard-coding compilers + find_every_method_call_by_name(body_node, :system).each do |method| + param = parameters(method).first + if match = regex_match_group(param, %r{(/usr/bin/)?(gcc|llvm-gcc|clang)\s?}) + problem "Use \"\#{ENV.cc}\" instead of hard-coding \"#{match[2]}\"" + elsif match = regex_match_group(param, %r{(/usr/bin/)?((g|llvm-g|clang)\+\+)\s?}) + problem "Use \"\#{ENV.cxx}\" instead of hard-coding \"#{match[2]}\"" + end + end + + find_instance_method_call(body_node, "ENV", :[]=) do |method| + param = parameters(method)[1] + if match = regex_match_group(param, %r{(/usr/bin/)?(gcc|llvm-gcc|clang)\s?}) + problem "Use \"\#{ENV.cc}\" instead of hard-coding \"#{match[2]}\"" + elsif match = regex_match_group(param, %r{(/usr/bin/)?((g|llvm-g|clang)\+\+)\s?}) + problem "Use \"\#{ENV.cxx}\" instead of hard-coding \"#{match[2]}\"" + end + end + + # Prefer formula path shortcuts in strings + 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]}}\"" + 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]}}\"" + end + if match = regex_match_group(p, %r{((/share/man/)(man[1-8]))}) + problem "\"\#\{prefix}#{match[1]}\" should be \"\#{#{match[3]}}\"" + 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}}\"" + end + end + + find_every_method_call_by_name(body_node, :depends_on).each do |method| + key, value = destructure_hash(parameters(method).first) + 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}`" + 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" + end + + find_every_method_call_by_name(body_node, :depends_on).each do |method| + next if modifier?(method.parent) + param = parameters(method).first + dep, option = hash_dep(param) + next if dep.nil? || option.nil? + offending_node(param) + problem "Dependency #{string_content(dep)} should not use option #{string_content(option)}" + end + + find_instance_method_call(body_node, :version, :==) do |method| + next unless parameters_passed?(method, "HEAD") + problem "Use 'build.head?' instead of inspecting 'version'" + end + + find_instance_method_call(body_node, "ENV", :fortran) do + next if depends_on?(:fortran) + problem "Use `depends_on :fortran` instead of `ENV.fortran`" + end + + find_instance_method_call(body_node, "ARGV", :include?) do |method| + param = parameters(method).first + next unless match = regex_match_group(param, /--(HEAD|devel)/) + problem "Use \"if build.#{match[1].downcase}?\" instead" + end + + find_const(body_node, "MACOS_VERSION") do + 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" + end + + conditional_dependencies(body_node) do |node, method, param, dep_node| + dep = string_content(dep_node) + if node.if? + 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" + 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" + 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" end - find_method_with_args(body_node, :system, /^(otool|install_name_tool|lipo)$/) do + find_method_with_args(body_node, :system, /(otool|install_name_tool|lipo)/) do next if @formula_name == "cctools" problem "Use ruby-macho instead of calling #{@offensive_node.source}" end find_every_method_call_by_name(body_node, :system).each do |method_node| # Skip Kibana: npm cache edge (see formula for more details) - next if @formula_name =~ /^kibana(\@\d+(\.\d+)?)?$/ + next if @formula_name =~ /^kibana(\@\d+(\.\d+)?)?$/i first_param, second_param = parameters(method_node) next if !node_equals?(first_param, "npm") || !node_equals?(second_param, "install") @@ -104,33 +295,88 @@ module RuboCop problem "Use new-style test definitions (test do)" end - if find_method_def(body_node, :options) - problem "Use new-style option definitions" - end - find_method_with_args(body_node, :skip_clean, :all) do - problem <<-EOS.undent.chomp + problem <<~EOS.chomp `skip_clean :all` is deprecated; brew no longer strips symbols Pass explicit paths to prevent Homebrew from removing empty folders. EOS end + if find_method_def(@processed_source.ast) + 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 next if @formula_name == "wine" problem "macOS has been 64-bit only since 10.6 so build.universal? is deprecated." end find_instance_method_call(body_node, "ENV", :universal_binary) do + next if @formula_name == "wine" problem "macOS has been 64-bit only since 10.6 so ENV.universal_binary is deprecated." end find_instance_method_call(body_node, "ENV", :x11) do problem 'Use "depends_on :x11" instead of "ENV.x11"' end + + find_every_method_call_by_name(body_node, :depends_on).each do |method| + next unless method_called?(method, :new) + problem "`depends_on` can take requirement classes instead of instances" + end + + os = [:leopard?, :snow_leopard?, :lion?, :mountain_lion?] + os.each do |version| + find_instance_method_call(body_node, "MacOS", version) do |method| + problem "\"#{method.source}\" is deprecated, use a comparison to MacOS.version instead" + end + end + + find_instance_method_call(body_node, "Dir", :[]) do |method| + path = parameters(method).first + next unless path.str_type? + next unless match = regex_match_group(path, /^[^\*{},]+$/) + problem "Dir([\"#{string_content(path)}\"]) is unnecessary; just use \"#{match[0]}\"" + end + + fileutils_methods = Regexp.new(FileUtils.singleton_methods(false).map { |m| "(?-mix:^" + Regexp.escape(m) + "$)" }.join("|")) + find_every_method_call_by_name(body_node, :system).each do |method| + param = parameters(method).first + next unless match = regex_match_group(param, fileutils_methods) + problem "Use the `#{match}` Ruby method instead of `#{method.source}`" + end + end + + def modifier?(node) + return false unless node.if_type? + node.modifier_form? end + def_node_search :conditional_dependencies, <<~EOS + {$(if (send (send nil :build) ${:include? :with? :without?} $(str _)) + (send nil :depends_on $({str sym} _)) nil) + + $(if (send (send nil :build) ${:include? :with? :without?} $(str _)) nil + (send nil :depends_on $({str sym} _)))} + EOS + + # Match depends_on with hash as argument + def_node_matcher :hash_dep, <<~EOS + {(hash (pair $(str _) $(str _))) + (hash (pair $(str _) (array $(str _) ...)))} + EOS + + def_node_matcher :destructure_hash, <<~EOS + (hash (pair $(str _) $(sym _))) + EOS + + def_node_search :formula_path_strings, <<~EOS + {(dstr (begin (send nil %1)) $(str _ )) + (dstr _ (begin (send nil %1)) $(str _ ))} + EOS + # Node Pattern search for Language::Node - def_node_search :languageNodeModule?, <<-EOS.undent + def_node_search :languageNodeModule?, <<~EOS (const (const nil :Language) :Node) EOS end diff --git a/Library/Homebrew/rubocops/patches_cop.rb b/Library/Homebrew/rubocops/patches_cop.rb index 7ee1a127a..a752f1019 100644 --- a/Library/Homebrew/rubocops/patches_cop.rb +++ b/Library/Homebrew/rubocops/patches_cop.rb @@ -28,7 +28,7 @@ module RuboCop gh_patch_param_pattern = %r{https?://github\.com/.+/.+/(?:commit|pull)/[a-fA-F0-9]*.(?:patch|diff)} if regex_match_group(patch, gh_patch_param_pattern) if patch_url !~ /\?full_index=\w+$/ - problem <<-EOS.undent + problem <<~EOS GitHub patches should use the full_index parameter: #{patch_url}?full_index=1 EOS @@ -41,7 +41,7 @@ module RuboCop %r{gist\.githubusercontent\.com/.+/raw}]) if regex_match_group(patch, gh_patch_patterns) if patch_url !~ /[a-fA-F0-9]{40}/ - problem <<-EOS.undent.chomp + problem <<~EOS.chomp GitHub/Gist patches should specify a revision: #{patch_url} EOS @@ -50,7 +50,7 @@ module RuboCop gh_patch_diff_pattern = %r{https?://patch-diff\.githubusercontent\.com/raw/(.+)/(.+)/pull/(.+)\.(?:diff|patch)} if match_obj = regex_match_group(patch, gh_patch_diff_pattern) - problem <<-EOS.undent + problem <<~EOS use GitHub pull request URLs: https://github.com/#{match_obj[1]}/#{match_obj[2]}/pull/#{match_obj[3]}.patch Rather than patch-diff: @@ -59,21 +59,21 @@ module RuboCop end if regex_match_group(patch, %r{macports/trunk}) - problem <<-EOS.undent.chomp + problem <<~EOS.chomp MacPorts patches should specify a revision instead of trunk: #{patch_url} EOS end if regex_match_group(patch, %r{^http://trac\.macports\.org}) - problem <<-EOS.undent.chomp + problem <<~EOS.chomp Patches from MacPorts Trac should be https://, not http: #{patch_url} EOS end return unless regex_match_group(patch, %r{^http://bugs\.debian\.org}) - problem <<-EOS.undent.chomp + problem <<~EOS.chomp Patches from Debian should be https://, not http: #{patch_url} EOS diff --git a/Library/Homebrew/rubocops/urls_cop.rb b/Library/Homebrew/rubocops/urls_cop.rb index 071a4c42d..414f633c9 100644 --- a/Library/Homebrew/rubocops/urls_cop.rb +++ b/Library/Homebrew/rubocops/urls_cop.rb @@ -104,7 +104,7 @@ module RuboCop end if url =~ %r{^https?://prdownloads\.} - problem <<-EOS.undent.chomp + problem <<~EOS.chomp Don't use prdownloads in SourceForge urls (url is #{url}). See: http://librelist.com/browser/homebrew/2011/1/12/prdownloads-is-bad/ EOS @@ -121,7 +121,7 @@ module RuboCop # one out of the grab bag. unsecure_deb_pattern = %r{^http://http\.debian\.net/debian/(.*)}i audit_urls(urls, unsecure_deb_pattern) do |match, _| - problem <<-EOS.undent + problem <<~EOS Please use a secure mirror for Debian URLs. We recommend: https://mirrors.ocf.berkeley.edu/debian/#{match[1]} @@ -176,7 +176,7 @@ module RuboCop # Don't use GitHub codeload URLs codeload_gh_pattern = %r{https?://codeload\.github\.com/(.+)/(.+)/(?:tar\.gz|zip)/(.+)} audit_urls(urls, codeload_gh_pattern) do |match, url| - problem <<-EOS.undent + problem <<~EOS Use GitHub archive URLs: https://github.com/#{match[1]}/#{match[2]}/archive/#{match[3]}.tar.gz Rather than codeload: diff --git a/Library/Homebrew/sandbox.rb b/Library/Homebrew/sandbox.rb index 7d23e5966..ea74fae09 100644 --- a/Library/Homebrew/sandbox.rb +++ b/Library/Homebrew/sandbox.rb @@ -138,7 +138,7 @@ class Sandbox end class SandboxProfile - SEATBELT_ERB = <<-EOS.undent + SEATBELT_ERB = <<~EOS.freeze (version 1) (debug deny) ; log all denied operations to /var/log/system.log <%= rules.join("\n") %> diff --git a/Library/Homebrew/tab.rb b/Library/Homebrew/tab.rb index af19cabe6..aa0208d51 100644 --- a/Library/Homebrew/tab.rb +++ b/Library/Homebrew/tab.rb @@ -3,18 +3,16 @@ require "ostruct" require "options" require "json" require "development_tools" +require "extend/cachable" # Inherit from OpenStruct to gain a generic initialization method that takes a # hash and creates an attribute for each key and value. `Tab.new` probably # should not be called directly, instead use one of the class methods like # `Tab.create`. class Tab < OpenStruct - FILENAME = "INSTALL_RECEIPT.json".freeze - CACHE = {} + extend Cachable - def self.clear_cache - CACHE.clear - end + FILENAME = "INSTALL_RECEIPT.json".freeze # Instantiates a Tab for a new installation of a formula. def self.create(formula, compiler, stdlib) @@ -57,7 +55,7 @@ class Tab < OpenStruct # Returns the Tab for an install receipt at `path`. # Results are cached. def self.from_file(path) - CACHE.fetch(path) { |p| CACHE[p] = from_file_content(File.read(p), p) } + cache.fetch(path) { |p| cache[p] = from_file_content(File.read(p), p) } end # Like Tab.from_file, but bypass the cache. @@ -343,7 +341,7 @@ class Tab < OpenStruct # will no longer be valid. Formula.clear_installed_formulae_cache unless tabfile.exist? - CACHE[tabfile] = self + self.class.cache[tabfile] = self tabfile.atomic_write(to_json) end diff --git a/Library/Homebrew/tap.rb b/Library/Homebrew/tap.rb index f4e7631b4..2d1c47e32 100644 --- a/Library/Homebrew/tap.rb +++ b/Library/Homebrew/tap.rb @@ -1,4 +1,5 @@ require "extend/string" +require "extend/cachable" require "readall" # a {Tap} is used to extend the formulae provided by Homebrew core. @@ -8,13 +9,9 @@ require "readall" # {#user} represents Github username and {#repo} represents repository # name without leading `homebrew-`. class Tap - TAP_DIRECTORY = HOMEBREW_LIBRARY/"Taps" - - CACHE = {} + extend Cachable - def self.clear_cache - CACHE.clear - end + TAP_DIRECTORY = HOMEBREW_LIBRARY/"Taps" def self.fetch(*args) case args.length @@ -29,16 +26,16 @@ class Tap raise "Invalid tap name '#{args.join("/")}'" end - # we special case homebrew so users don't have to shift in a terminal - user = "Homebrew" if user == "homebrew" + # We special case homebrew and linuxbrew so that users don't have to shift in a terminal. + user = user.capitalize if ["homebrew", "linuxbrew"].include? user repo = repo.strip_prefix "homebrew-" - if user == "Homebrew" && (repo == "homebrew" || repo == "core") + if ["Homebrew", "Linuxbrew"].include?(user) && ["core", "homebrew"].include?(repo) return CoreTap.instance end cache_key = "#{user}/#{repo}".downcase - CACHE.fetch(cache_key) { |key| CACHE[key] = Tap.new(user, repo) } + cache.fetch(cache_key) { |key| cache[key] = Tap.new(user, repo) } end def self.from_path(path) @@ -118,6 +115,12 @@ class Tap path.git? end + # git branch for this {Tap}. + def git_branch + raise TapUnavailableError, name unless installed? + path.git_branch + end + # git HEAD for this {Tap}. def git_head raise TapUnavailableError, name unless installed? @@ -264,7 +267,7 @@ class Tap return if options[:clone_target] return unless private? return if quiet - puts <<-EOS.undent + puts <<~EOS It looks like you tapped a private repository. To avoid entering your credentials each time you update, you can use git HTTP credential caching or issue the following command: @@ -497,7 +500,7 @@ class Tap # an array of all installed {Tap} names. def self.names - map(&:name) + map(&:name).sort end # @private diff --git a/Library/Homebrew/test.rb b/Library/Homebrew/test.rb index d9ec8250e..3d5e62a88 100644 --- a/Library/Homebrew/test.rb +++ b/Library/Homebrew/test.rb @@ -27,7 +27,7 @@ begin Timeout.timeout TEST_TIMEOUT_SECONDS do raise "test returned false" if formula.run_test == false end -rescue Exception => e +rescue Exception => e # rubocop:disable Lint/RescueException Marshal.dump(e, error_pipe) error_pipe.close exit! 1 diff --git a/Library/Homebrew/test/cask/artifact/app_spec.rb b/Library/Homebrew/test/cask/artifact/app_spec.rb index 4ead8b7f9..285cc4f31 100644 --- a/Library/Homebrew/test/cask/artifact/app_spec.rb +++ b/Library/Homebrew/test/cask/artifact/app_spec.rb @@ -82,12 +82,12 @@ describe Hbc::Artifact::App, :cask do describe "target is both writable and user-owned" do it "overwrites the existing app" do - stdout = <<-EOS.undent + stdout = <<~EOS ==> Removing App '#{target_path}'. ==> Moving App 'Caffeine.app' to '#{target_path}'. EOS - stderr = <<-EOS.undent + stderr = <<~EOS Warning: It seems there is already an App at '#{target_path}'; overwriting. EOS @@ -117,12 +117,12 @@ describe Hbc::Artifact::App, :cask do expect(command).to receive(:run).with("/usr/bin/chflags", args: ["-R", "--", "000", target_path], must_succeed: false) .and_call_original - stdout = <<-EOS.undent + stdout = <<~EOS ==> Removing App '#{target_path}'. ==> Moving App 'Caffeine.app' to '#{target_path}'. EOS - stderr = <<-EOS.undent + stderr = <<~EOS Warning: It seems there is already an App at '#{target_path}'; overwriting. EOS @@ -162,12 +162,12 @@ describe Hbc::Artifact::App, :cask do let(:force) { true } it "overwrites the existing app" do - stdout = <<-EOS.undent + stdout = <<~EOS ==> Removing App '#{target_path}'. ==> Moving App 'Caffeine.app' to '#{target_path}'. EOS - stderr = <<-EOS.undent + stderr = <<~EOS Warning: It seems there is already an App at '#{target_path}'; overwriting. EOS diff --git a/Library/Homebrew/test/cask/artifact/pkg_spec.rb b/Library/Homebrew/test/cask/artifact/pkg_spec.rb index 7f1b64d1a..89916d283 100644 --- a/Library/Homebrew/test/cask/artifact/pkg_spec.rb +++ b/Library/Homebrew/test/cask/artifact/pkg_spec.rb @@ -29,7 +29,7 @@ describe Hbc::Artifact::Pkg, :cask do file = double(path: Pathname.new("/tmp/choices.xml")) - expect(file).to receive(:write).with(<<-EOS.undent) + expect(file).to receive(:write).with(<<~EOS) <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> diff --git a/Library/Homebrew/test/cask/artifact/two_apps_correct_spec.rb b/Library/Homebrew/test/cask/artifact/two_apps_correct_spec.rb index 7f2ef75b3..8367dc27d 100644 --- a/Library/Homebrew/test/cask/artifact/two_apps_correct_spec.rb +++ b/Library/Homebrew/test/cask/artifact/two_apps_correct_spec.rb @@ -61,7 +61,7 @@ describe Hbc::Artifact::App, :cask do target_path_mini.mkpath expect { - expect(install_phase).to output(<<-EOS.undent).to_stdout + expect(install_phase).to output(<<~EOS).to_stdout ==> Moving App 'Caffeine Pro.app' to '#{target_path_pro}' EOS }.to raise_error(Hbc::CaskError, "It seems there is already an App at '#{target_path_mini}'.") @@ -75,7 +75,7 @@ describe Hbc::Artifact::App, :cask do target_path_pro.mkpath expect { - expect(install_phase).to output(<<-EOS.undent).to_stdout + expect(install_phase).to output(<<~EOS).to_stdout ==> Moving App 'Caffeine Mini.app' to '#{target_path_mini}' EOS }.to raise_error(Hbc::CaskError, "It seems there is already an App at '#{target_path_pro}'.") diff --git a/Library/Homebrew/test/cask/artifact/uninstall_zap_shared_examples.rb b/Library/Homebrew/test/cask/artifact/uninstall_zap_shared_examples.rb index b9872ab9e..7edfb9e1c 100644 --- a/Library/Homebrew/test/cask/artifact/uninstall_zap_shared_examples.rb +++ b/Library/Homebrew/test/cask/artifact/uninstall_zap_shared_examples.rb @@ -11,7 +11,7 @@ shared_examples "#uninstall_phase or #zap_phase" do let(:launchctl_remove_cmd) { %w[/bin/launchctl remove my.fancy.package.service] } let(:unknown_response) { "launchctl list returned unknown response\n" } let(:service_info) do - <<-EOS.undent + <<~EOS { "LimitLoadToSessionType" = "Aqua"; "Label" = "my.fancy.package.service"; diff --git a/Library/Homebrew/test/cask/cli/cat_spec.rb b/Library/Homebrew/test/cask/cli/cat_spec.rb index 6b54a2e4b..e1db1b17d 100644 --- a/Library/Homebrew/test/cask/cli/cat_spec.rb +++ b/Library/Homebrew/test/cask/cli/cat_spec.rb @@ -7,7 +7,7 @@ describe Hbc::CLI::Cat, :cask do describe "given a basic Cask" do let(:basic_cask_content) { - <<-EOS.undent + <<~EOS cask 'basic-cask' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' diff --git a/Library/Homebrew/test/cask/cli/cleanup_spec.rb b/Library/Homebrew/test/cask/cli/cleanup_spec.rb index 7cf00352d..cbef71be8 100644 --- a/Library/Homebrew/test/cask/cli/cleanup_spec.rb +++ b/Library/Homebrew/test/cask/cli/cleanup_spec.rb @@ -32,7 +32,7 @@ describe Hbc::CLI::Cleanup, :cask do expect { subject.run - }.to output(<<-EOS.undent).to_stdout + }.to output(<<~EOS).to_stdout ==> Removing cached downloads for #{cask_token} #{cached_downloads[0]} ==> This operation has freed approximately #{disk_usage_readable(cleanup_size)} of disk space. @@ -52,7 +52,7 @@ describe Hbc::CLI::Cleanup, :cask do expect { subject.run - }.to output(<<-EOS.undent).to_stdout + }.to output(<<~EOS).to_stdout ==> Removing cached downloads #{cached_download} ==> This operation has freed approximately #{disk_usage_readable(cleanup_size)} of disk space. @@ -70,7 +70,7 @@ describe Hbc::CLI::Cleanup, :cask do expect { subject.run - }.to output(<<-EOS.undent).to_stdout + }.to output(<<~EOS).to_stdout ==> Removing cached downloads older than 10 days old Nothing to do EOS diff --git a/Library/Homebrew/test/cask/cli/create_spec.rb b/Library/Homebrew/test/cask/cli/create_spec.rb index 60c03db75..1b15ecd40 100644 --- a/Library/Homebrew/test/cask/cli/create_spec.rb +++ b/Library/Homebrew/test/cask/cli/create_spec.rb @@ -28,7 +28,7 @@ describe Hbc::CLI::Create, :cask do it "drops a template down for the specified Cask" do described_class.run("new-cask") template = File.read(Hbc::CaskLoader.path("new-cask")) - expect(template).to eq <<-EOS.undent + expect(template).to eq <<~EOS cask 'new-cask' do version '' sha256 '' diff --git a/Library/Homebrew/test/cask/cli/info_spec.rb b/Library/Homebrew/test/cask/cli/info_spec.rb index e24eead11..0fc751e06 100644 --- a/Library/Homebrew/test/cask/cli/info_spec.rb +++ b/Library/Homebrew/test/cask/cli/info_spec.rb @@ -8,7 +8,7 @@ describe Hbc::CLI::Info, :cask do it "displays some nice info about the specified Cask" do expect { described_class.run("local-caffeine") - }.to output(<<-EOS.undent).to_stdout + }.to output(<<~EOS).to_stdout local-caffeine: 1.2.3 http://example.com/local-caffeine Not installed @@ -22,7 +22,7 @@ describe Hbc::CLI::Info, :cask do describe "given multiple Casks" do let(:expected_output) { - <<-EOS.undent + <<~EOS local-caffeine: 1.2.3 http://example.com/local-caffeine Not installed @@ -52,7 +52,7 @@ describe Hbc::CLI::Info, :cask do it "should print caveats if the Cask provided one" do expect { described_class.run("with-caveats") - }.to output(<<-EOS.undent).to_stdout + }.to output(<<~EOS).to_stdout with-caveats: 1.2.3 http://example.com/local-caffeine Not installed @@ -78,7 +78,7 @@ describe Hbc::CLI::Info, :cask do it 'should not print "Caveats" section divider if the caveats block has no output' do expect { described_class.run("with-conditional-caveats") - }.to output(<<-EOS.undent).to_stdout + }.to output(<<~EOS).to_stdout with-conditional-caveats: 1.2.3 http://example.com/local-caffeine Not installed @@ -93,7 +93,7 @@ describe Hbc::CLI::Info, :cask do it "prints languages specified in the Cask" do expect { described_class.run("with-languages") - }.to output(<<-EOS.undent).to_stdout + }.to output(<<~EOS).to_stdout with-languages: 1.2.3 http://example.com/local-caffeine Not installed @@ -110,7 +110,7 @@ describe Hbc::CLI::Info, :cask do it 'does not print "Languages" section divider if the languages block has no output' do expect { described_class.run("without-languages") - }.to output(<<-EOS.undent).to_stdout + }.to output(<<~EOS).to_stdout without-languages: 1.2.3 http://example.com/local-caffeine Not installed diff --git a/Library/Homebrew/test/cask/cli/install_spec.rb b/Library/Homebrew/test/cask/cli/install_spec.rb index c918a3529..25d6cdc93 100644 --- a/Library/Homebrew/test/cask/cli/install_spec.rb +++ b/Library/Homebrew/test/cask/cli/install_spec.rb @@ -6,7 +6,7 @@ describe Hbc::CLI::Install, :cask do it_behaves_like "a command that handles invalid options" it "displays the installation progress" do - output = Regexp.new <<-EOS.undent + output = Regexp.new <<~EOS ==> Downloading file:.*caffeine.zip ==> Verifying checksum for Cask local-caffeine ==> Installing Cask local-caffeine diff --git a/Library/Homebrew/test/cask/cli/list_spec.rb b/Library/Homebrew/test/cask/cli/list_spec.rb index 301ca9b89..eef233acc 100644 --- a/Library/Homebrew/test/cask/cli/list_spec.rb +++ b/Library/Homebrew/test/cask/cli/list_spec.rb @@ -12,7 +12,7 @@ describe Hbc::CLI::List, :cask do expect { described_class.run - }.to output(<<-EOS.undent).to_stdout + }.to output(<<~EOS).to_stdout local-caffeine local-transmission EOS @@ -31,7 +31,7 @@ describe Hbc::CLI::List, :cask do expect { described_class.run("--full-name") - }.to output(<<-EOS.undent).to_stdout + }.to output(<<~EOS).to_stdout local-caffeine local-transmission third-party/tap/third-party-cask @@ -41,7 +41,7 @@ describe Hbc::CLI::List, :cask do describe "lists versions" do let(:casks) { ["local-caffeine", "local-transmission"] } let(:expected_output) { - <<-EOS.undent + <<~EOS local-caffeine 1.2.3 local-transmission 2.61 EOS @@ -78,7 +78,7 @@ describe Hbc::CLI::List, :cask do expect { described_class.run("local-transmission", "local-caffeine") - }.to output(<<-EOS.undent).to_stdout + }.to output(<<~EOS).to_stdout ==> Apps #{Hbc.appdir.join("Transmission.app")} (#{Hbc.appdir.join("Transmission.app").abv}) ==> Apps diff --git a/Library/Homebrew/test/cask/cli/outdated_spec.rb b/Library/Homebrew/test/cask/cli/outdated_spec.rb index 5bbf18d21..1ee6a6d7d 100644 --- a/Library/Homebrew/test/cask/cli/outdated_spec.rb +++ b/Library/Homebrew/test/cask/cli/outdated_spec.rb @@ -23,7 +23,7 @@ describe Hbc::CLI::Outdated, :cask do it "checks all the installed Casks when no token is provided" do expect { described_class.run - }.to output(<<-EOS.undent).to_stdout + }.to output(<<~EOS).to_stdout local-caffeine (1.2.2) != 1.2.3 local-transmission (2.60) != 2.61 EOS @@ -32,7 +32,7 @@ describe Hbc::CLI::Outdated, :cask do it "checks only the tokens specified in the command line" do expect { described_class.run("local-caffeine") - }.to output(<<-EOS.undent).to_stdout + }.to output(<<~EOS).to_stdout local-caffeine (1.2.2) != 1.2.3 EOS end @@ -40,7 +40,7 @@ describe Hbc::CLI::Outdated, :cask do it 'ignores "auto_updates" and "latest" Casks even when their tokens are provided in the command line' do expect { described_class.run("local-caffeine", "auto-updates", "version-latest-string") - }.to output(<<-EOS.undent).to_stdout + }.to output(<<~EOS).to_stdout local-caffeine (1.2.2) != 1.2.3 EOS end @@ -54,7 +54,7 @@ describe Hbc::CLI::Outdated, :cask do it "lists only the names (no versions) of the outdated Casks with --quiet" do expect { described_class.run("--verbose", "--quiet") - }.to output(<<-EOS.undent).to_stdout + }.to output(<<~EOS).to_stdout local-caffeine local-transmission EOS @@ -65,7 +65,7 @@ describe Hbc::CLI::Outdated, :cask do it 'includes the Casks with "auto_updates true" or "version latest" with --greedy' do expect { described_class.run("--greedy") - }.to output(<<-EOS.undent).to_stdout + }.to output(<<~EOS).to_stdout auto-updates (2.57) != 2.61 local-caffeine (1.2.2) != 1.2.3 local-transmission (2.60) != 2.61 @@ -79,7 +79,7 @@ describe Hbc::CLI::Outdated, :cask do expect { described_class.run("--greedy") - }.to output(<<-EOS.undent).to_stdout + }.to output(<<~EOS).to_stdout local-caffeine (1.2.2) != 1.2.3 local-transmission (2.60) != 2.61 version-latest-string (latest) != latest diff --git a/Library/Homebrew/test/cask/cli/reinstall_spec.rb b/Library/Homebrew/test/cask/cli/reinstall_spec.rb index 95294b695..5e551e5b5 100644 --- a/Library/Homebrew/test/cask/cli/reinstall_spec.rb +++ b/Library/Homebrew/test/cask/cli/reinstall_spec.rb @@ -8,7 +8,7 @@ describe Hbc::CLI::Reinstall, :cask do Hbc::Installer.new(caffeine).install - output = Regexp.new <<-EOS.undent + output = Regexp.new <<~EOS ==> Downloading file:.*caffeine.zip Already downloaded: .*local-caffeine--1.2.3.zip ==> Verifying checksum for Cask local-caffeine diff --git a/Library/Homebrew/test/cask/cli/search_spec.rb b/Library/Homebrew/test/cask/cli/search_spec.rb index a4f796f3c..cd1a7bd43 100644 --- a/Library/Homebrew/test/cask/cli/search_spec.rb +++ b/Library/Homebrew/test/cask/cli/search_spec.rb @@ -12,7 +12,7 @@ describe Hbc::CLI::Search, :cask do expect { Hbc::CLI::Search.run("local") - }.to output(<<-EOS.undent).to_stdout.as_tty + }.to output(<<~EOS).to_stdout.as_tty ==> Partial Matches local-caffeine local-transmission @@ -24,7 +24,7 @@ describe Hbc::CLI::Search, :cask do expect { Hbc::CLI::Search.run("local") - }.to output(<<-EOS.undent).to_stdout + }.to output(<<~EOS).to_stdout local-caffeine local-transmission EOS @@ -35,7 +35,7 @@ describe Hbc::CLI::Search, :cask do expect { Hbc::CLI::Search.run("local") - }.to output(<<-EOS.undent).to_stdout + }.to output(<<~EOS).to_stdout local-caffeine local-transmission EOS @@ -45,7 +45,7 @@ describe Hbc::CLI::Search, :cask do it "shows that there are no Casks matching a search term that did not result in anything" do expect { Hbc::CLI::Search.run("foo-bar-baz") - }.to output(<<-EOS.undent).to_stdout.as_tty + }.to output(<<~EOS).to_stdout.as_tty No Cask found for "foo-bar-baz". EOS end @@ -84,7 +84,7 @@ describe Hbc::CLI::Search, :cask do it "accepts a regexp argument" do expect { Hbc::CLI::Search.run("/^local-c[a-z]ffeine$/") - }.to output(<<-EOS.undent).to_stdout.as_tty + }.to output(<<~EOS).to_stdout.as_tty ==> Regexp Matches local-caffeine EOS @@ -93,7 +93,7 @@ describe Hbc::CLI::Search, :cask do it "returns both exact and partial matches" do expect { Hbc::CLI::Search.run("test-opera") - }.to output(<<-EOS.undent).to_stdout.as_tty + }.to output(<<~EOS).to_stdout.as_tty ==> Exact Match test-opera ==> Partial Matches @@ -104,7 +104,7 @@ describe Hbc::CLI::Search, :cask do it "does not search the Tap name" do expect { Hbc::CLI::Search.run("caskroom") - }.to output(<<-EOS.undent).to_stdout.as_tty + }.to output(<<~EOS).to_stdout.as_tty No Cask found for "caskroom". EOS end diff --git a/Library/Homebrew/test/cask/cli/uninstall_spec.rb b/Library/Homebrew/test/cask/cli/uninstall_spec.rb index 80b7edbd3..1ab8f7e4d 100644 --- a/Library/Homebrew/test/cask/cli/uninstall_spec.rb +++ b/Library/Homebrew/test/cask/cli/uninstall_spec.rb @@ -10,7 +10,7 @@ describe Hbc::CLI::Uninstall, :cask do Hbc::Installer.new(caffeine).install - output = Regexp.new <<-EOS.undent + output = Regexp.new <<~EOS ==> Uninstalling Cask local-caffeine ==> Removing App '.*Caffeine.app'. EOS @@ -107,7 +107,7 @@ describe Hbc::CLI::Uninstall, :cask do timestamped_versions.each do |timestamped_version| caskroom_path.join(".metadata", *timestamped_version, "Casks").tap(&:mkpath) .join("#{token}.rb").open("w") do |caskfile| - caskfile.puts <<-EOS.undent + caskfile.puts <<~EOS cask '#{token}' do version '#{timestamped_version[0]}' end @@ -153,7 +153,7 @@ describe Hbc::CLI::Uninstall, :cask do saved_caskfile.dirname.mkpath - IO.write saved_caskfile, <<-EOS.undent + IO.write saved_caskfile, <<~EOS cask 'ive-been-renamed' do version :latest diff --git a/Library/Homebrew/test/cask/dsl_spec.rb b/Library/Homebrew/test/cask/dsl_spec.rb index 28cf6f4b2..a17acfca6 100644 --- a/Library/Homebrew/test/cask/dsl_spec.rb +++ b/Library/Homebrew/test/cask/dsl_spec.rb @@ -20,7 +20,7 @@ describe Hbc::DSL, :cask do } it "prints a warning that it has encountered an unexpected method" do - expected = Regexp.compile(<<-EOS.undent.lines.map(&:chomp).join("")) + expected = Regexp.compile(<<~EOS.lines.map(&:chomp).join("")) (?m) Warning: .* @@ -232,7 +232,7 @@ describe Hbc::DSL, :cask do expect(cask.caveats).to be_empty cask = Hbc::Cask.new("cask-with-caveats") do - def caveats; <<-EOS.undent + def caveats; <<~EOS When you install this Cask, you probably want to know this. EOS end diff --git a/Library/Homebrew/test/cask/pkg_spec.rb b/Library/Homebrew/test/cask/pkg_spec.rb index 07443e76e..f92d6854e 100644 --- a/Library/Homebrew/test/cask/pkg_spec.rb +++ b/Library/Homebrew/test/cask/pkg_spec.rb @@ -123,7 +123,7 @@ describe Hbc::Pkg, :cask do end let(:pkg_info_plist) do - <<-EOS.undent + <<~EOS <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> diff --git a/Library/Homebrew/test/cask/system_command_result_spec.rb b/Library/Homebrew/test/cask/system_command_result_spec.rb index 4a077de7b..d09f1220c 100644 --- a/Library/Homebrew/test/cask/system_command_result_spec.rb +++ b/Library/Homebrew/test/cask/system_command_result_spec.rb @@ -5,7 +5,7 @@ describe Hbc::SystemCommand::Result, :cask do subject { described_class._parse_plist(command, input) } let(:command) { Hbc::SystemCommand.new("/usr/bin/true", {}) } let(:plist) { - <<-EOS.undent + <<~EOS <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> @@ -54,7 +54,7 @@ describe Hbc::SystemCommand::Result, :cask do context "when output contains garbage" do let(:input) { - <<-EOS.undent + <<~EOS Hello there! I am in no way XML am I?!?! That's a little silly... you were expexting XML here! diff --git a/Library/Homebrew/test/cmd/custom-external-command_spec.rb b/Library/Homebrew/test/cmd/custom-external-command_spec.rb index d649786ec..8e6ffe2ff 100644 --- a/Library/Homebrew/test/cmd/custom-external-command_spec.rb +++ b/Library/Homebrew/test/cmd/custom-external-command_spec.rb @@ -4,7 +4,7 @@ describe "brew custom-external-command", :integration_test do cmd = "custom-external-command-#{rand}" file = path/"brew-#{cmd}" - file.write <<-EOS.undent + file.write <<~EOS #!/bin/sh echo 'I am #{cmd}.' EOS diff --git a/Library/Homebrew/test/cmd/install_spec.rb b/Library/Homebrew/test/cmd/install_spec.rb index b6030f26a..8a9f7a0d2 100644 --- a/Library/Homebrew/test/cmd/install_spec.rb +++ b/Library/Homebrew/test/cmd/install_spec.rb @@ -56,7 +56,7 @@ describe "brew install", :integration_test do end specify "install failures" do - path = setup_test_formula "testball1", <<-EOS.undent + path = setup_test_formula "testball1", <<~EOS version "1.0" EOS @@ -66,7 +66,7 @@ describe "brew install", :integration_test do .and be_a_success FileUtils.rm path - setup_test_formula "testball1", <<-EOS.undent + setup_test_formula "testball1", <<~EOS version "2.0" devel do @@ -120,7 +120,7 @@ describe "brew install", :integration_test do end it "can install keg-only Formulae" do - path_keg_only = setup_test_formula "testball1", <<-EOS.undent + path_keg_only = setup_test_formula "testball1", <<~EOS version "1.0" keg_only "test reason" @@ -132,7 +132,7 @@ describe "brew install", :integration_test do .and be_a_success FileUtils.rm path_keg_only - setup_test_formula "testball1", <<-EOS.undent + setup_test_formula "testball1", <<~EOS version "2.0" keg_only "test reason" @@ -162,7 +162,7 @@ describe "brew install", :integration_test do system "git", "commit", "-m", "Initial repo commit" end - setup_test_formula "testball1", <<-EOS.undent + setup_test_formula "testball1", <<~EOS version "1.0" head "file://#{repo_path}", :using => :git @@ -205,7 +205,7 @@ describe "brew install", :integration_test do end it "succeeds when a non-fatal requirement isn't satisfied" do - setup_test_formula "testball1", <<-EOS.undent + setup_test_formula "testball1", <<~EOS class NonFatalRequirement < Requirement satisfy { false } end @@ -220,7 +220,7 @@ describe "brew install", :integration_test do end it "fails when a fatal requirement isn't satisfied" do - setup_test_formula "testball1", <<-EOS.undent + setup_test_formula "testball1", <<~EOS class FatalRequirement < Requirement fatal true satisfy { false } diff --git a/Library/Homebrew/test/cmd/irb_spec.rb b/Library/Homebrew/test/cmd/irb_spec.rb index 44410fabe..0423c6ab7 100644 --- a/Library/Homebrew/test/cmd/irb_spec.rb +++ b/Library/Homebrew/test/cmd/irb_spec.rb @@ -3,7 +3,7 @@ describe "brew irb", :integration_test do setup_test_formula "testball" irb_test = HOMEBREW_TEMP/"irb-test.rb" - irb_test.write <<-EOS.undent + irb_test.write <<~EOS "testball".f :testball.f exit diff --git a/Library/Homebrew/test/cmd/link_spec.rb b/Library/Homebrew/test/cmd/link_spec.rb index 78942b7a8..bde321e4c 100644 --- a/Library/Homebrew/test/cmd/link_spec.rb +++ b/Library/Homebrew/test/cmd/link_spec.rb @@ -36,7 +36,7 @@ describe "brew link", :integration_test do end it "refuses to link keg-only Formulae" do - setup_test_formula "testball1", <<-EOS.undent + setup_test_formula "testball1", <<~EOS keg_only "just because" EOS diff --git a/Library/Homebrew/test/cmd/options_spec.rb b/Library/Homebrew/test/cmd/options_spec.rb index 33fe8b107..bb6b98a47 100644 --- a/Library/Homebrew/test/cmd/options_spec.rb +++ b/Library/Homebrew/test/cmd/options_spec.rb @@ -1,6 +1,6 @@ describe "brew options", :integration_test do it "prints a given Formula's options" do - setup_test_formula "testball", <<-EOS.undent + setup_test_formula "testball", <<~EOS depends_on "bar" => :recommended EOS diff --git a/Library/Homebrew/test/cmd/style_spec.rb b/Library/Homebrew/test/cmd/style_spec.rb index 4701036f1..5c118f32e 100644 --- a/Library/Homebrew/test/cmd/style_spec.rb +++ b/Library/Homebrew/test/cmd/style_spec.rb @@ -4,12 +4,12 @@ describe "brew style" do around(:each) do |example| begin FileUtils.ln_s HOMEBREW_LIBRARY_PATH, HOMEBREW_LIBRARY/"Homebrew" - FileUtils.ln_s HOMEBREW_LIBRARY_PATH.parent/".rubocop.yml", HOMEBREW_LIBRARY/".auditcops.yml" + FileUtils.ln_s HOMEBREW_LIBRARY_PATH.parent/".rubocop.yml", HOMEBREW_LIBRARY/".rubocop_audit.yml" example.run ensure FileUtils.rm_f HOMEBREW_LIBRARY/"Homebrew" - FileUtils.rm_f HOMEBREW_LIBRARY/".auditcops.yml" + FileUtils.rm_f HOMEBREW_LIBRARY/".rubocop_audit.yml" end end @@ -19,7 +19,7 @@ describe "brew style" do it "returns RubocopResults when RuboCop reports offenses" do formula = dir/"my-formula.rb" - formula.write <<-'EOS'.undent + formula.write <<~'EOS' class MyFormula < Formula end diff --git a/Library/Homebrew/test/cmd/switch_spec.rb b/Library/Homebrew/test/cmd/switch_spec.rb index 00fe4ace6..48d7dcdd0 100644 --- a/Library/Homebrew/test/cmd/switch_spec.rb +++ b/Library/Homebrew/test/cmd/switch_spec.rb @@ -10,7 +10,7 @@ describe "brew switch", :integration_test do .and not_to_output.to_stdout .and be_a_failure - setup_test_formula "testball", <<-EOS.undent + setup_test_formula "testball", <<~EOS keg_only "just because" EOS diff --git a/Library/Homebrew/test/cmd/uses_spec.rb b/Library/Homebrew/test/cmd/uses_spec.rb index 2a6f48cb7..4a8c446a5 100644 --- a/Library/Homebrew/test/cmd/uses_spec.rb +++ b/Library/Homebrew/test/cmd/uses_spec.rb @@ -2,7 +2,7 @@ describe "brew uses", :integration_test do it "prints the Formulae a given Formula is used by" do setup_test_formula "foo" setup_test_formula "bar" - setup_test_formula "baz", <<-EOS.undent + setup_test_formula "baz", <<~EOS url "https://example.com/baz-1.0" depends_on "bar" EOS diff --git a/Library/Homebrew/test/deps_spec.rb b/Library/Homebrew/test/deps_spec.rb index 4c892c93d..f0ec514d9 100644 --- a/Library/Homebrew/test/deps_spec.rb +++ b/Library/Homebrew/test/deps_spec.rb @@ -2,7 +2,7 @@ describe "brew deps", :integration_test do before(:each) do setup_test_formula "foo" setup_test_formula "bar" - setup_test_formula "baz", <<-EOS.undent + setup_test_formula "baz", <<~EOS url "https://example.com/baz-1.0" depends_on "bar" EOS diff --git a/Library/Homebrew/test/descriptions_spec.rb b/Library/Homebrew/test/descriptions_spec.rb index e873c73b4..c4f67cc4c 100644 --- a/Library/Homebrew/test/descriptions_spec.rb +++ b/Library/Homebrew/test/descriptions_spec.rb @@ -19,7 +19,7 @@ describe Descriptions do descriptions_hash["somedev/external/foo"] = "External foo" expect { subject.print }.to output( - <<-EOS.undent + <<~EOS homebrew/core/foo: Core foo somedev/external/foo: External foo EOS @@ -32,7 +32,7 @@ describe Descriptions do descriptions_hash["otherdev/external/foo"] = "Other external foo" expect { subject.print }.to output( - <<-EOS.undent + <<~EOS homebrew/core/foo: Core foo otherdev/external/foo: Other external foo somedev/external/foo: External foo diff --git a/Library/Homebrew/test/dev-cmd/audit_spec.rb b/Library/Homebrew/test/dev-cmd/audit_spec.rb index 3e99bd06b..8dd3aee72 100644 --- a/Library/Homebrew/test/dev-cmd/audit_spec.rb +++ b/Library/Homebrew/test/dev-cmd/audit_spec.rb @@ -18,7 +18,7 @@ describe FormulaText do def formula_text(name, body = nil, options = {}) path = dir/"#{name}.rb" - path.write <<-EOS.undent + path.write <<~EOS class #{Formulary.class_s(name)} < Formula #{body} end @@ -29,7 +29,7 @@ describe FormulaText do end specify "simple valid Formula" do - ft = formula_text "valid", <<-EOS.undent + ft = formula_text "valid", <<~EOS url "http://www.example.com/valid-1.0.tar.gz" EOS @@ -49,7 +49,7 @@ describe FormulaText do end specify "#data?" do - ft = formula_text "data", <<-EOS.undent + ft = formula_text "data", <<~EOS patch :DATA EOS @@ -77,7 +77,7 @@ describe FormulaAuditor do describe "#problems" do it "is empty by default" do - fa = formula_auditor "foo", <<-EOS.undent + fa = formula_auditor "foo", <<~EOS class Foo < Formula url "http://example.com/foo-1.0.tgz" end @@ -91,7 +91,7 @@ describe FormulaAuditor do specify "file permissions" do allow(File).to receive(:umask).and_return(022) - fa = formula_auditor "foo", <<-EOS.undent + fa = formula_auditor "foo", <<~EOS class Foo < Formula url "http://example.com/foo-1.0.tgz" end @@ -106,7 +106,7 @@ describe FormulaAuditor do end specify "DATA but no __END__" do - fa = formula_auditor "foo", <<-EOS.undent + fa = formula_auditor "foo", <<~EOS class Foo < Formula url "http://example.com/foo-1.0.tgz" patch :DATA @@ -118,7 +118,7 @@ describe FormulaAuditor do end specify "__END__ but no DATA" do - fa = formula_auditor "foo", <<-EOS.undent + fa = formula_auditor "foo", <<~EOS class Foo < Formula url "http://example.com/foo-1.0.tgz" end @@ -138,7 +138,7 @@ describe FormulaAuditor do end specify "no issue" do - fa = formula_auditor "foo", <<-EOS.undent + fa = formula_auditor "foo", <<~EOS class Foo < Formula url "http://example.com/foo-1.0.tgz" homepage "http://example.com" @@ -152,7 +152,7 @@ describe FormulaAuditor do describe "#line_problems" do specify "pkgshare" do - fa = formula_auditor "foo", <<-EOS.undent, strict: true + fa = formula_auditor "foo", <<~EOS, strict: true class Foo < Formula url "http://example.com/foo-1.0.tgz" end @@ -184,7 +184,7 @@ describe FormulaAuditor do # Formulae with "++" in their name would break various audit regexps: # Error: nested *?+ in regexp: /^libxml++3\s/ specify "++ in name" do - fa = formula_auditor "foolibc++", <<-EOS.undent, strict: true + fa = formula_auditor "foolibc++", <<~EOS, strict: true class Foolibcxx < Formula desc "foolibc++ is a test" url "http://example.com/foo-1.0.tgz" @@ -205,7 +205,7 @@ describe FormulaAuditor do specify "#audit_github_repository when HOMEBREW_NO_GITHUB_API is set" do ENV["HOMEBREW_NO_GITHUB_API"] = "1" - fa = formula_auditor "foo", <<-EOS.undent, strict: true, online: true + fa = formula_auditor "foo", <<~EOS, strict: true, online: true class Foo < Formula homepage "https://github.com/example/example" url "http://example.com/foo-1.0.tgz" @@ -219,7 +219,7 @@ describe FormulaAuditor do describe "#audit_keg_only_style" do specify "keg_only_needs_downcasing" do - fa = formula_auditor "foo", <<-EOS.undent, strict: true + fa = formula_auditor "foo", <<~EOS, strict: true class Foo < Formula url "http://example.com/foo-1.0.tgz" @@ -233,7 +233,7 @@ describe FormulaAuditor do end specify "keg_only_redundant_period" do - fa = formula_auditor "foo", <<-EOS.undent, strict: true + fa = formula_auditor "foo", <<~EOS, strict: true class Foo < Formula url "http://example.com/foo-1.0.tgz" @@ -247,11 +247,11 @@ describe FormulaAuditor do end specify "keg_only_handles_block_correctly" do - fa = formula_auditor "foo", <<-EOS.undent, strict: true + fa = formula_auditor "foo", <<~EOS, strict: true class Foo < Formula url "http://example.com/foo-1.0.tgz" - keg_only <<-EOF.undent + keg_only <<~EOF this line starts with a lowercase word. This line does not but that shouldn't be a @@ -266,7 +266,7 @@ describe FormulaAuditor do end specify "keg_only_handles_whitelist_correctly" do - fa = formula_auditor "foo", <<-EOS.undent, strict: true + fa = formula_auditor "foo", <<~EOS, strict: true class Foo < Formula url "http://example.com/foo-1.0.tgz" @@ -290,7 +290,7 @@ describe FormulaAuditor do before(:each) do @foo_version = Count.increment - origin_formula_path.write <<-EOS.undent + origin_formula_path.write <<~EOS class Foo#{@foo_version} < Formula url "https://example.com/foo-1.0.tar.gz" revision 2 diff --git a/Library/Homebrew/test/dev-cmd/pull_spec.rb b/Library/Homebrew/test/dev-cmd/pull_spec.rb index 9815ef9a1..984ac0843 100644 --- a/Library/Homebrew/test/dev-cmd/pull_spec.rb +++ b/Library/Homebrew/test/dev-cmd/pull_spec.rb @@ -22,7 +22,7 @@ describe "brew pull", :integration_test do .and output(/Current branch is new\-branch/).to_stderr .and be_a_failure - expect { brew "pull", "--bump", "8" } + expect { brew "pull", "--bump", "https://github.com/Homebrew/homebrew-core/pull/8" } .to output(/Fetching patch/).to_stdout .and output(/No changed formulae found to bump/).to_stderr .and be_a_failure diff --git a/Library/Homebrew/test/dev-cmd/test_spec.rb b/Library/Homebrew/test/dev-cmd/test_spec.rb index 9ff365bfb..6e5d822bc 100644 --- a/Library/Homebrew/test/dev-cmd/test_spec.rb +++ b/Library/Homebrew/test/dev-cmd/test_spec.rb @@ -23,7 +23,7 @@ describe "brew test", :integration_test do end it "tests a given Formula" do - setup_test_formula "testball", <<-EOS.undent + setup_test_formula "testball", <<~EOS head "https://github.com/example/testball2.git" devel do diff --git a/Library/Homebrew/test/formula_installer_spec.rb b/Library/Homebrew/test/formula_installer_spec.rb index 7365b2758..1e3c04b68 100644 --- a/Library/Homebrew/test/formula_installer_spec.rb +++ b/Library/Homebrew/test/formula_installer_spec.rb @@ -100,14 +100,14 @@ describe FormulaInstaller do specify "check installation sanity pinned dependency" do dep_name = "dependency" dep_path = CoreTap.new.formula_dir/"#{dep_name}.rb" - dep_path.write <<-EOS.undent + dep_path.write <<~EOS class #{Formulary.class_s(dep_name)} < Formula url "foo" version "0.2" end EOS - Formulary::FORMULAE.delete(dep_path) + Formulary.cache.delete(dep_path) dependency = Formulary.factory(dep_name) dependent = formula do diff --git a/Library/Homebrew/test/formulary_spec.rb b/Library/Homebrew/test/formulary_spec.rb index 3180ad9a7..f091fdd03 100644 --- a/Library/Homebrew/test/formulary_spec.rb +++ b/Library/Homebrew/test/formulary_spec.rb @@ -6,7 +6,7 @@ describe Formulary do let(:formula_name) { "testball_bottle" } let(:formula_path) { CoreTap.new.formula_dir/"#{formula_name}.rb" } let(:formula_content) do - <<-EOS.undent + <<~EOS class #{subject.class_s(formula_name)} < Formula url "file://#{TEST_FIXTURE_DIR}/tarballs/testball-0.1.tbz" sha256 TESTBALL_SHA256 @@ -66,7 +66,7 @@ describe Formulary do context "if the Formula has the wrong class" do let(:formula_name) { "giraffe" } let(:formula_content) do - <<-EOS.undent + <<~EOS class Wrong#{subject.class_s(formula_name)} < Formula end EOS diff --git a/Library/Homebrew/test/gpg2_requirement_spec.rb b/Library/Homebrew/test/gpg2_requirement_spec.rb index a5501c84e..8b9040b82 100644 --- a/Library/Homebrew/test/gpg2_requirement_spec.rb +++ b/Library/Homebrew/test/gpg2_requirement_spec.rb @@ -7,7 +7,7 @@ describe GPG2Requirement do describe "#satisfied?" do it "returns true if GPG2 is installed" do ENV["PATH"] = dir/"bin" - (dir/"bin/gpg").write <<-EOS.undent + (dir/"bin/gpg").write <<~EOS #!/bin/bash echo 2.1.20 EOS diff --git a/Library/Homebrew/test/inreplace_spec.rb b/Library/Homebrew/test/inreplace_spec.rb index 5be44f50d..330943be4 100644 --- a/Library/Homebrew/test/inreplace_spec.rb +++ b/Library/Homebrew/test/inreplace_spec.rb @@ -9,7 +9,7 @@ describe StringInreplaceExtension do context "flag" do context "with spaces" do let(:string) do - <<-EOS.undent + <<~EOS OTHER=def FLAG = abc FLAG2=abc @@ -18,7 +18,7 @@ describe StringInreplaceExtension do it "is successfully replaced" do subject.change_make_var! "FLAG", "def" - expect(subject).to eq <<-EOS.undent + expect(subject).to eq <<~EOS OTHER=def FLAG=def FLAG2=abc @@ -27,7 +27,7 @@ describe StringInreplaceExtension do it "is successfully appended" do subject.change_make_var! "FLAG", "\\1 def" - expect(subject).to eq <<-EOS.undent + expect(subject).to eq <<~EOS OTHER=def FLAG=abc def FLAG2=abc @@ -37,7 +37,7 @@ describe StringInreplaceExtension do context "with tabs" do let(:string) do - <<-EOS.undent + <<~EOS CFLAGS\t=\t-Wall -O2 LDFLAGS\t=\t-lcrypto -lssl EOS @@ -45,7 +45,7 @@ describe StringInreplaceExtension do it "is successfully replaced" do subject.change_make_var! "CFLAGS", "-O3" - expect(subject).to eq <<-EOS.undent + expect(subject).to eq <<~EOS CFLAGS=-O3 LDFLAGS\t=\t-lcrypto -lssl EOS @@ -55,7 +55,7 @@ describe StringInreplaceExtension do context "empty flag between other flags" do let(:string) do - <<-EOS.undent + <<~EOS OTHER=def FLAG = FLAG2=abc @@ -64,7 +64,7 @@ describe StringInreplaceExtension do it "is successfully replaced" do subject.change_make_var! "FLAG", "def" - expect(subject).to eq <<-EOS.undent + expect(subject).to eq <<~EOS OTHER=def FLAG=def FLAG2=abc @@ -74,7 +74,7 @@ describe StringInreplaceExtension do context "empty flag" do let(:string) do - <<-EOS.undent + <<~EOS FLAG = mv file_a file_b EOS @@ -82,7 +82,7 @@ describe StringInreplaceExtension do it "is successfully replaced" do subject.change_make_var! "FLAG", "def" - expect(subject).to eq <<-EOS.undent + expect(subject).to eq <<~EOS FLAG=def mv file_a file_b EOS @@ -91,7 +91,7 @@ describe StringInreplaceExtension do context "shell-style variable" do let(:string) do - <<-EOS.undent + <<~EOS OTHER=def FLAG=abc FLAG2=abc @@ -100,7 +100,7 @@ describe StringInreplaceExtension do it "is successfully replaced" do subject.change_make_var! "FLAG", "def" - expect(subject).to eq <<-EOS.undent + expect(subject).to eq <<~EOS OTHER=def FLAG=def FLAG2=abc @@ -113,7 +113,7 @@ describe StringInreplaceExtension do context "flag" do context "with spaces" do let(:string) do - <<-EOS.undent + <<~EOS OTHER=def FLAG = abc FLAG2 = def @@ -122,7 +122,7 @@ describe StringInreplaceExtension do it "is successfully removed" do subject.remove_make_var! "FLAG" - expect(subject).to eq <<-EOS.undent + expect(subject).to eq <<~EOS OTHER=def FLAG2 = def EOS @@ -131,7 +131,7 @@ describe StringInreplaceExtension do context "with tabs" do let(:string) do - <<-EOS.undent + <<~EOS CFLAGS\t=\t-Wall -O2 LDFLAGS\t=\t-lcrypto -lssl EOS @@ -139,7 +139,7 @@ describe StringInreplaceExtension do it "is successfully removed" do subject.remove_make_var! "LDFLAGS" - expect(subject).to eq <<-EOS.undent + expect(subject).to eq <<~EOS CFLAGS\t=\t-Wall -O2 EOS end @@ -148,7 +148,7 @@ describe StringInreplaceExtension do context "multiple flags" do let(:string) do - <<-EOS.undent + <<~EOS OTHER=def FLAG = abc FLAG2 = def @@ -158,7 +158,7 @@ describe StringInreplaceExtension do specify "are be successfully removed" do subject.remove_make_var! ["FLAG", "FLAG2"] - expect(subject).to eq <<-EOS.undent + expect(subject).to eq <<~EOS OTHER=def OTHER2=def EOS @@ -169,7 +169,7 @@ describe StringInreplaceExtension do describe "#get_make_var" do context "with spaces" do let(:string) do - <<-EOS.undent + <<~EOS CFLAGS = -Wall -O2 LDFLAGS = -lcrypto -lssl EOS @@ -182,7 +182,7 @@ describe StringInreplaceExtension do context "with tabs" do let(:string) do - <<-EOS.undent + <<~EOS CFLAGS\t=\t-Wall -O2 LDFLAGS\t=\t-lcrypto -lssl EOS @@ -217,7 +217,7 @@ describe Utils::Inreplace do let(:file) { Tempfile.new("test") } before(:each) do - file.write <<-EOS.undent + file.write <<~EOS a b c diff --git a/Library/Homebrew/test/java_requirement_spec.rb b/Library/Homebrew/test/java_requirement_spec.rb index 05d4f3cda..685e250e0 100644 --- a/Library/Homebrew/test/java_requirement_spec.rb +++ b/Library/Homebrew/test/java_requirement_spec.rb @@ -50,7 +50,7 @@ describe JavaRequirement do let(:java) { path/"java" } def setup_java_with_version(version) - IO.write java, <<-EOS.undent + IO.write java, <<~EOS #!/bin/sh echo 'java version "#{version}"' EOS diff --git a/Library/Homebrew/test/language/python_spec.rb b/Library/Homebrew/test/language/python_spec.rb index 02f6bf8d2..d384ce602 100644 --- a/Library/Homebrew/test/language/python_spec.rb +++ b/Library/Homebrew/test/language/python_spec.rb @@ -41,7 +41,7 @@ describe Language::Python::Virtualenv::Virtualenv do "--no-binary", ":all:", "--ignore-installed", "foo", "bar") .and_return(true) - subject.pip_install <<-EOS.undent + subject.pip_install <<~EOS foo bar EOS diff --git a/Library/Homebrew/test/missing_formula_spec.rb b/Library/Homebrew/test/missing_formula_spec.rb index 0a905004b..830ecb6aa 100644 --- a/Library/Homebrew/test/missing_formula_spec.rb +++ b/Library/Homebrew/test/missing_formula_spec.rb @@ -116,7 +116,7 @@ describe Homebrew::MissingFormula do Tap.clear_cache tap_path = Tap::TAP_DIRECTORY/"homebrew/homebrew-foo" tap_path.mkpath - (tap_path/"tap_migrations.json").write <<-EOS.undent + (tap_path/"tap_migrations.json").write <<~EOS { "migrated-formula": "homebrew/bar" } EOS end diff --git a/Library/Homebrew/test/os_requirement_spec.rb b/Library/Homebrew/test/os_requirement_spec.rb new file mode 100644 index 000000000..87f86231c --- /dev/null +++ b/Library/Homebrew/test/os_requirement_spec.rb @@ -0,0 +1,18 @@ +require "requirements/linux_requirement" +require "requirements/macos_requirement" + +describe LinuxRequirement do + describe "#satisfied?" do + it "returns true if OS is Linux" do + expect(subject.satisfied?).to eq(OS.linux?) + end + end +end + +describe MacOSRequirement do + describe "#satisfied?" do + it "returns true if OS is macOS" do + expect(subject.satisfied?).to eq(OS.mac?) + end + end +end diff --git a/Library/Homebrew/test/pathname_spec.rb b/Library/Homebrew/test/pathname_spec.rb index 69314e5f4..1349e602b 100644 --- a/Library/Homebrew/test/pathname_spec.rb +++ b/Library/Homebrew/test/pathname_spec.rb @@ -79,12 +79,12 @@ describe Pathname do touch file file.append_lines("CONTENT") - expect(File.read(file)).to eq <<-EOS.undent + expect(File.read(file)).to eq <<~EOS CONTENT EOS file.append_lines("CONTENTS") - expect(File.read(file)).to eq <<-EOS.undent + expect(File.read(file)).to eq <<~EOS CONTENT CONTENTS EOS diff --git a/Library/Homebrew/test/rubocops/bottle_block_cop_spec.rb b/Library/Homebrew/test/rubocops/bottle_block_cop_spec.rb index b1afdc3f9..659750858 100644 --- a/Library/Homebrew/test/rubocops/bottle_block_cop_spec.rb +++ b/Library/Homebrew/test/rubocops/bottle_block_cop_spec.rb @@ -8,7 +8,7 @@ describe RuboCop::Cop::FormulaAuditStrict::BottleBlock do context "When auditing Bottle Block" do it "When there is revision in bottle block" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url 'http://example.com/foo-1.0.tgz' bottle do @@ -41,7 +41,7 @@ describe RuboCop::Cop::FormulaAuditStrict::BottleBlock do context "When auditing Bottle Block with auto correct" do it "When there is revision in bottle block" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url 'http://example.com/foo-1.0.tgz' bottle do @@ -50,7 +50,7 @@ describe RuboCop::Cop::FormulaAuditStrict::BottleBlock do end end EOS - corrected_source = <<-EOS.undent + corrected_source = <<~EOS class Foo < Formula url 'http://example.com/foo-1.0.tgz' bottle do diff --git a/Library/Homebrew/test/rubocops/caveats_cop_spec.rb b/Library/Homebrew/test/rubocops/caveats_cop_spec.rb index 4dbe65cfb..68f79e08a 100644 --- a/Library/Homebrew/test/rubocops/caveats_cop_spec.rb +++ b/Library/Homebrew/test/rubocops/caveats_cop_spec.rb @@ -8,20 +8,19 @@ describe RuboCop::Cop::FormulaAudit::Caveats do context "When auditing caveats" do it "When there is setuid mentioned in caveats" do - source = <<-EOS.undent - class Foo < Formula - homepage "http://example.com/foo" - url "http://example.com/foo-1.0.tgz" - - def caveats - "setuid" + source = <<~EOS + class Foo < Formula + homepage "http://example.com/foo" + url "http://example.com/foo-1.0.tgz" + def caveats + "setuid" + end end - end EOS expected_offenses = [{ message: "Don't recommend setuid in the caveats, suggest sudo instead.", severity: :convention, - line: 6, + line: 5, column: 5, source: source }] diff --git a/Library/Homebrew/test/rubocops/checksum_cop_spec.rb b/Library/Homebrew/test/rubocops/checksum_cop_spec.rb index 2f508bbf5..ab70f2dcf 100644 --- a/Library/Homebrew/test/rubocops/checksum_cop_spec.rb +++ b/Library/Homebrew/test/rubocops/checksum_cop_spec.rb @@ -8,7 +8,7 @@ describe RuboCop::Cop::FormulaAudit::Checksum do context "When auditing spec checksums" do it "When the checksum is empty" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url 'http://example.com/foo-1.0.tgz' stable do @@ -42,7 +42,7 @@ describe RuboCop::Cop::FormulaAudit::Checksum do end it "When the checksum is not 64 characters" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url 'http://example.com/foo-1.0.tgz' stable do @@ -76,7 +76,7 @@ describe RuboCop::Cop::FormulaAudit::Checksum do end it "When the checksum has invalid chars" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url 'http://example.com/foo-1.0.tgz' stable do @@ -116,7 +116,7 @@ describe RuboCop::Cop::FormulaAudit::ChecksumCase do context "When auditing spec checksums" do it "When the checksum has upper case characters" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url 'http://example.com/foo-1.0.tgz' stable do @@ -150,7 +150,7 @@ describe RuboCop::Cop::FormulaAudit::ChecksumCase do end it "When auditing stable blocks outside spec blocks" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url 'http://example.com/foo-1.0.tgz' resource "foo-outside" do @@ -185,7 +185,7 @@ describe RuboCop::Cop::FormulaAudit::ChecksumCase do context "When auditing checksum with autocorrect" do it "When there is uppercase sha256" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url 'http://example.com/foo-1.0.tgz' stable do @@ -200,7 +200,7 @@ describe RuboCop::Cop::FormulaAudit::ChecksumCase do end EOS - corrected_source = <<-EOS.undent + corrected_source = <<~EOS class Foo < Formula url 'http://example.com/foo-1.0.tgz' stable do diff --git a/Library/Homebrew/test/rubocops/class_cop_spec.rb b/Library/Homebrew/test/rubocops/class_cop_spec.rb index 59252587c..3f210af11 100644 --- a/Library/Homebrew/test/rubocops/class_cop_spec.rb +++ b/Library/Homebrew/test/rubocops/class_cop_spec.rb @@ -17,10 +17,10 @@ describe RuboCop::Cop::FormulaAudit::ClassName do }] formulas.each do |formula| - source = <<-EOS.undent - class Foo < #{formula["class"]} - url 'http://example.com/foo-1.0.tgz' - end + source = <<~EOS + class Foo < #{formula["class"]} + url 'http://example.com/foo-1.0.tgz' + end EOS expected_offenses = [{ message: "#{formula["class"]} is deprecated, use Formula instead", @@ -38,12 +38,12 @@ describe RuboCop::Cop::FormulaAudit::ClassName do end it "with deprecated inheritance and autocorrect" do - source = <<-EOS.undent + source = <<~EOS class Foo < AmazonWebServicesFormula url 'http://example.com/foo-1.0.tgz' end EOS - corrected_source = <<-EOS.undent + corrected_source = <<~EOS class Foo < Formula url 'http://example.com/foo-1.0.tgz' end @@ -60,7 +60,7 @@ describe RuboCop::Cop::FormulaAuditStrict::Test do context "When auditing formula" do it "without a test block" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url 'http://example.com/foo-1.0.tgz' end diff --git a/Library/Homebrew/test/rubocops/components_order_cop_spec.rb b/Library/Homebrew/test/rubocops/components_order_cop_spec.rb index f093f4927..a4726c001 100644 --- a/Library/Homebrew/test/rubocops/components_order_cop_spec.rb +++ b/Library/Homebrew/test/rubocops/components_order_cop_spec.rb @@ -8,7 +8,7 @@ describe RuboCop::Cop::FormulaAuditStrict::ComponentsOrder do context "When auditing formula components order" do it "When url precedes homepage" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url "http://example.com/foo-1.0.tgz" homepage "http://example.com" @@ -29,7 +29,7 @@ describe RuboCop::Cop::FormulaAuditStrict::ComponentsOrder do end it "When `resource` precedes `depends_on`" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url "https://example.com/foo-1.0.tgz" @@ -55,7 +55,7 @@ describe RuboCop::Cop::FormulaAuditStrict::ComponentsOrder do end it "When `test` precedes `plist`" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url "https://example.com/foo-1.0.tgz" @@ -82,7 +82,7 @@ describe RuboCop::Cop::FormulaAuditStrict::ComponentsOrder do end it "When only one of many `depends_on` precedes `conflicts_with`" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula depends_on "autoconf" => :build conflicts_with "visionmedia-watch" @@ -116,13 +116,13 @@ describe RuboCop::Cop::FormulaAuditStrict::ComponentsOrder do context "When auditing formula components order with autocorrect" do it "When url precedes homepage" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url "http://example.com/foo-1.0.tgz" homepage "http://example.com" end EOS - correct_source = <<-EOS.undent + correct_source = <<~EOS class Foo < Formula homepage "http://example.com" url "http://example.com/foo-1.0.tgz" @@ -134,7 +134,7 @@ describe RuboCop::Cop::FormulaAuditStrict::ComponentsOrder do end it "When `resource` precedes `depends_on`" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url "https://example.com/foo-1.0.tgz" @@ -145,7 +145,7 @@ describe RuboCop::Cop::FormulaAuditStrict::ComponentsOrder do depends_on "openssl" end EOS - correct_source = <<-EOS.undent + correct_source = <<~EOS class Foo < Formula url "https://example.com/foo-1.0.tgz" diff --git a/Library/Homebrew/test/rubocops/components_redundancy_cop_spec.rb b/Library/Homebrew/test/rubocops/components_redundancy_cop_spec.rb index 9fbe15904..e899a9b07 100644 --- a/Library/Homebrew/test/rubocops/components_redundancy_cop_spec.rb +++ b/Library/Homebrew/test/rubocops/components_redundancy_cop_spec.rb @@ -8,7 +8,7 @@ describe RuboCop::Cop::FormulaAuditStrict::ComponentsRedundancy do context "When auditing formula components common errors" do it "When url outside stable block" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url "http://example.com/foo-1.0.tgz" stable do @@ -31,7 +31,7 @@ describe RuboCop::Cop::FormulaAuditStrict::ComponentsRedundancy do end it "When both `head` and `head do` are present" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula head "http://example.com/foo.git" head do @@ -54,7 +54,7 @@ describe RuboCop::Cop::FormulaAuditStrict::ComponentsRedundancy do end it "When both `bottle :modifier` and `bottle do` are present" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url "http://example.com/foo-1.0.tgz" bottle do diff --git a/Library/Homebrew/test/rubocops/conflicts_cop_spec.rb b/Library/Homebrew/test/rubocops/conflicts_cop_spec.rb index 8874ecc96..40efe8545 100644 --- a/Library/Homebrew/test/rubocops/conflicts_cop_spec.rb +++ b/Library/Homebrew/test/rubocops/conflicts_cop_spec.rb @@ -8,7 +8,7 @@ describe RuboCop::Cop::FormulaAudit::Conflicts do context "When auditing formula for conflicts with" do it "multiple conflicts_with" do - source = <<-EOS.undent + source = <<~EOS class FooAT20 < Formula url 'http://example.com/foo-2.0.tgz' conflicts_with "mysql", "mariadb", "percona-server", @@ -30,7 +30,7 @@ describe RuboCop::Cop::FormulaAudit::Conflicts do end it "no conflicts_with" do - source = <<-EOS.undent + source = <<~EOS class FooAT20 < Formula url 'http://example.com/foo-2.0.tgz' desc 'Bar' diff --git a/Library/Homebrew/test/rubocops/formula_desc_cop_spec.rb b/Library/Homebrew/test/rubocops/formula_desc_cop_spec.rb index ac8893e18..0f0189aa8 100644 --- a/Library/Homebrew/test/rubocops/formula_desc_cop_spec.rb +++ b/Library/Homebrew/test/rubocops/formula_desc_cop_spec.rb @@ -8,7 +8,7 @@ describe RuboCop::Cop::FormulaAuditStrict::DescLength do context "When auditing formula desc" do it "When there is no desc" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url 'http://example.com/foo-1.0.tgz' end @@ -27,15 +27,36 @@ describe RuboCop::Cop::FormulaAuditStrict::DescLength do end end + it "reports an offense when desc is an empty string" do + source = <<~EOS + class Foo < Formula + url 'http://example.com/foo-1.0.tgz' + desc '' + end + EOS + + msg = "The desc (description) should not be an empty string." + expected_offenses = [{ message: msg, + severity: :convention, + line: 3, + column: 2, + source: source }] + + inspect_source(source, "/homebrew-core/Formula/foo.rb") + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + it "When desc is too long" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url 'http://example.com/foo-1.0.tgz' desc 'Bar#{"bar" * 29}' end EOS - msg = <<-EOS.undent + msg = <<~EOS Description is too long. "name: desc" should be less than 80 characters. Length is calculated as foo + desc. (currently 95) EOS @@ -52,7 +73,7 @@ describe RuboCop::Cop::FormulaAuditStrict::DescLength do end it "When desc is multiline string" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url 'http://example.com/foo-1.0.tgz' desc 'Bar#{"bar" * 9}'\ @@ -60,7 +81,7 @@ describe RuboCop::Cop::FormulaAuditStrict::DescLength do end EOS - msg = <<-EOS.undent + msg = <<~EOS Description is too long. "name: desc" should be less than 80 characters. Length is calculated as foo + desc. (currently 98) EOS @@ -83,7 +104,7 @@ describe RuboCop::Cop::FormulaAuditStrict::Desc do context "When auditing formula desc" do it "When wrong \"command-line\" usage in desc" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url 'http://example.com/foo-1.0.tgz' desc 'command line' @@ -103,7 +124,7 @@ describe RuboCop::Cop::FormulaAuditStrict::Desc do end it "When an article is used in desc" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url 'http://example.com/foo-1.0.tgz' desc 'An ' @@ -123,7 +144,7 @@ describe RuboCop::Cop::FormulaAuditStrict::Desc do end it "When an lowercase letter starts a desc" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url 'http://example.com/foo-1.0.tgz' desc 'bar' @@ -143,7 +164,7 @@ describe RuboCop::Cop::FormulaAuditStrict::Desc do end it "When formula name is in desc" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url 'http://example.com/foo-1.0.tgz' desc 'Foo is a foobar' @@ -163,13 +184,13 @@ describe RuboCop::Cop::FormulaAuditStrict::Desc do end it "autocorrects all rules" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url 'http://example.com/foo-1.0.tgz' desc ' an bar: commandline foo ' end EOS - correct_source = <<-EOS.undent + correct_source = <<~EOS class Foo < Formula url 'http://example.com/foo-1.0.tgz' desc 'an bar: command-line' diff --git a/Library/Homebrew/test/rubocops/homepage_cop_spec.rb b/Library/Homebrew/test/rubocops/homepage_cop_spec.rb index 6c7f248ba..be9dddae6 100644 --- a/Library/Homebrew/test/rubocops/homepage_cop_spec.rb +++ b/Library/Homebrew/test/rubocops/homepage_cop_spec.rb @@ -8,7 +8,7 @@ describe RuboCop::Cop::FormulaAudit::Homepage do context "When auditing homepage" do it "When there is no homepage" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url 'http://example.com/foo-1.0.tgz' end @@ -28,7 +28,7 @@ describe RuboCop::Cop::FormulaAudit::Homepage do end it "Homepage with ftp" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula homepage "ftp://example.com/foo" url "http://example.com/foo-1.0.tgz" @@ -65,7 +65,7 @@ describe RuboCop::Cop::FormulaAudit::Homepage do } formula_homepages.each do |name, homepage| - source = <<-EOS.undent + source = <<~EOS class #{name.capitalize} < Formula homepage "#{homepage}" url "http://example.com/#{name}-1.0.tgz" diff --git a/Library/Homebrew/test/rubocops/lines_cop_spec.rb b/Library/Homebrew/test/rubocops/lines_cop_spec.rb index 753439c8e..f96a4fd48 100644 --- a/Library/Homebrew/test/rubocops/lines_cop_spec.rb +++ b/Library/Homebrew/test/rubocops/lines_cop_spec.rb @@ -7,7 +7,7 @@ describe RuboCop::Cop::FormulaAudit::Lines do subject(:cop) { described_class.new } context "When auditing lines" do - it "with correctable deprecated dependencies" do + it "correctable deprecated dependencies usage" do formulae = [{ "dependency" => :automake, "correct" => "automake", @@ -25,22 +25,22 @@ describe RuboCop::Cop::FormulaAudit::Lines do }] formulae.each do |formula| - source = <<-EOS.undent - class Foo < Formula - url 'http://example.com/foo-1.0.tgz' - depends_on :#{formula["dependency"]} - end + source = <<~EOS + class Foo < Formula + url 'http://example.com/foo-1.0.tgz' + depends_on :#{formula["dependency"]} + end EOS if formula.key?("correct") offense = ":#{formula["dependency"]} is deprecated. Usage should be \"#{formula["correct"]}\"" else offense = ":#{formula["dependency"]} is deprecated" end - expected_offenses = [{ message: offense, - severity: :convention, - line: 3, - column: 2, - source: source }] + expected_offenses = [{ message: offense, + severity: :convention, + line: 3, + column: 2, + source: source }] inspect_source(source) @@ -56,21 +56,21 @@ describe RuboCop::Cop::FormulaAudit::ClassInheritance do subject(:cop) { described_class.new } context "When auditing lines" do - it "with no space in class inheritance" do - source = <<-EOS.undent + it "inconsistent space in class inheritance" do + source = <<~EOS class Foo<Formula desc "foo" url 'http://example.com/foo-1.0.tgz' end EOS - expected_offenses = [{ message: "Use a space in class inheritance: class Foo < Formula", - severity: :convention, - line: 1, - column: 10, - source: source }] + expected_offenses = [{ message: "Use a space in class inheritance: class Foo < Formula", + severity: :convention, + line: 1, + column: 10, + source: source }] - inspect_source(source) + inspect_source(source, "/homebrew-core/Formula/foo.rb") expected_offenses.zip(cop.offenses).each do |expected, actual| expect_offense(expected, actual) @@ -83,8 +83,8 @@ describe RuboCop::Cop::FormulaAudit::Comments do subject(:cop) { described_class.new } context "When auditing formula" do - it "with commented cmake call" do - source = <<-EOS.undent + it "commented cmake call" do + source = <<~EOS class Foo < Formula desc "foo" url 'http://example.com/foo-1.0.tgz' @@ -92,11 +92,11 @@ describe RuboCop::Cop::FormulaAudit::Comments do end EOS - expected_offenses = [{ message: "Please remove default template comments", - severity: :convention, - line: 4, - column: 2, - source: source }] + expected_offenses = [{ message: "Please remove default template comments", + severity: :convention, + line: 4, + column: 2, + source: source }] inspect_source(source) @@ -105,8 +105,8 @@ describe RuboCop::Cop::FormulaAudit::Comments do end end - it "with default template comments" do - source = <<-EOS.undent + it "default template comments" do + source = <<~EOS class Foo < Formula # PLEASE REMOVE desc "foo" @@ -114,11 +114,11 @@ describe RuboCop::Cop::FormulaAudit::Comments do end EOS - expected_offenses = [{ message: "Please remove default template comments", - severity: :convention, - line: 2, - column: 2, - source: source }] + expected_offenses = [{ message: "Please remove default template comments", + severity: :convention, + line: 2, + column: 2, + source: source }] inspect_source(source) @@ -127,8 +127,8 @@ describe RuboCop::Cop::FormulaAudit::Comments do end end - it "with commented out depends_on" do - source = <<-EOS.undent + it "commented out depends_on" do + source = <<~EOS class Foo < Formula desc "foo" url 'http://example.com/foo-1.0.tgz' @@ -136,11 +136,11 @@ describe RuboCop::Cop::FormulaAudit::Comments do end EOS - expected_offenses = [{ message: 'Commented-out dependency "foo"', - severity: :convention, - line: 4, - column: 2, - source: source }] + expected_offenses = [{ message: 'Commented-out dependency "foo"', + severity: :convention, + line: 4, + column: 2, + source: source }] inspect_source(source) @@ -151,12 +151,325 @@ describe RuboCop::Cop::FormulaAudit::Comments do end end +describe RuboCop::Cop::FormulaAudit::AssertStatements do + subject(:cop) { described_class.new } + + it "assert ...include usage" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + assert File.read("inbox").include?("Sample message 1") + end + EOS + + expected_offenses = [{ message: "Use `assert_match` instead of `assert ...include?`", + severity: :convention, + line: 4, + column: 9, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "assert ...exist? without a negation" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + assert File.exist? "default.ini" + end + EOS + + expected_offenses = [{ message: 'Use `assert_predicate <path_to_file>, :exist?` instead of `assert File.exist? "default.ini"`', + severity: :convention, + line: 4, + column: 9, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "assert ...exist? with a negation" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + assert !File.exist?("default.ini") + end + EOS + + expected_offenses = [{ message: 'Use `refute_predicate <path_to_file>, :exist?` instead of `assert !File.exist?("default.ini")`', + severity: :convention, + line: 4, + column: 9, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "assert ...executable? without a negation" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + assert File.executable? f + end + EOS + + expected_offenses = [{ message: "Use `assert_predicate <path_to_file>, :executable?` instead of `assert File.executable? f`", + severity: :convention, + line: 4, + column: 9, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end +end + +describe RuboCop::Cop::FormulaAudit::OptionDeclarations do + subject(:cop) { described_class.new } + + it "unless build.without? conditional" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + def post_install + return unless build.without? "bar" + end + end + EOS + + expected_offenses = [{ message: 'Use if build.with? "bar" instead of unless build.without? "bar"', + severity: :convention, + line: 5, + column: 18, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "unless build.with? conditional" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + def post_install + return unless build.with? "bar" + end + end + EOS + + expected_offenses = [{ message: 'Use if build.without? "bar" instead of unless build.with? "bar"', + severity: :convention, + line: 5, + column: 18, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "negated build.with? conditional" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + def post_install + return if !build.with? "bar" + end + end + EOS + + expected_offenses = [{ message: "Don't negate 'build.with?': use 'build.without?'", + severity: :convention, + line: 5, + column: 14, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "negated build.without? conditional" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + def post_install + return if !build.without? "bar" + end + end + EOS + + expected_offenses = [{ message: "Don't negate 'build.without?': use 'build.with?'", + severity: :convention, + line: 5, + column: 14, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "unnecessary build.without? conditional" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + def post_install + return if build.without? "--without-bar" + end + end + EOS + + expected_offenses = [{ message: "Don't duplicate 'without': Use `build.without? \"bar\"` to check for \"--without-bar\"", + severity: :convention, + line: 5, + column: 30, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "unnecessary build.with? conditional" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + def post_install + return if build.with? "--with-bar" + end + end + EOS + + expected_offenses = [{ message: "Don't duplicate 'with': Use `build.with? \"bar\"` to check for \"--with-bar\"", + severity: :convention, + line: 5, + column: 27, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "build.include? conditional" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + def post_install + return if build.include? "without-bar" + end + end + EOS + + expected_offenses = [{ message: "Use build.without? \"bar\" instead of build.include? 'without-bar'", + severity: :convention, + line: 5, + column: 30, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "build.include? with dashed args conditional" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + def post_install + return if build.include? "--bar" + end + end + EOS + + expected_offenses = [{ message: "Reference 'bar' without dashes", + severity: :convention, + line: 5, + column: 30, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "def options usage" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + + def options + [["--bar", "desc"]] + end + end + EOS + + expected_offenses = [{ message: "Use new-style option definitions", + severity: :convention, + line: 5, + column: 2, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end +end + describe RuboCop::Cop::FormulaAudit::Miscellaneous do subject(:cop) { described_class.new } context "When auditing formula" do - it "with FileUtils" do - source = <<-EOS.undent + it "FileUtils usage" do + source = <<~EOS class Foo < Formula desc "foo" url 'http://example.com/foo-1.0.tgz' @@ -164,11 +477,11 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do end EOS - expected_offenses = [{ message: "Don't need 'FileUtils.' before mv", - severity: :convention, - line: 4, - column: 2, - source: source }] + expected_offenses = [{ message: "Don't need 'FileUtils.' before mv", + severity: :convention, + line: 4, + column: 2, + source: source }] inspect_source(source) @@ -177,8 +490,8 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do end end - it "with long inreplace block vars" do - source = <<-EOS.undent + it "long inreplace block vars" do + source = <<~EOS class Foo < Formula desc "foo" url 'http://example.com/foo-1.0.tgz' @@ -188,11 +501,11 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do end EOS - expected_offenses = [{ message: "\"inreplace <filenames> do |s|\" is preferred over \"|longvar|\".", - severity: :convention, - line: 4, - column: 2, - source: source }] + expected_offenses = [{ message: "\"inreplace <filenames> do |s|\" is preferred over \"|longvar|\".", + severity: :convention, + line: 4, + column: 2, + source: source }] inspect_source(source) @@ -201,8 +514,8 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do end end - it "with invalid rebuild" do - source = <<-EOS.undent + it "an invalid rebuild statement" do + source = <<~EOS class Foo < Formula desc "foo" url 'http://example.com/foo-1.0.tgz' @@ -213,11 +526,11 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do end EOS - expected_offenses = [{ message: "'rebuild 0' should be removed", - severity: :convention, - line: 5, - column: 4, - source: source }] + expected_offenses = [{ message: "'rebuild 0' should be removed", + severity: :convention, + line: 5, + column: 4, + source: source }] inspect_source(source) @@ -226,8 +539,8 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do end end - it "with OS.linux? check" do - source = <<-EOS.undent + it "OS.linux? check" do + source = <<~EOS class Foo < Formula desc "foo" url 'http://example.com/foo-1.0.tgz' @@ -240,11 +553,11 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do end EOS - expected_offenses = [{ message: "Don't use OS.linux?; Homebrew/core only supports macOS", - severity: :convention, - line: 5, - column: 7, - source: source }] + expected_offenses = [{ message: "Don't use OS.linux?; Homebrew/core only supports macOS", + severity: :convention, + line: 5, + column: 7, + source: source }] inspect_source(source, "/homebrew-core/") @@ -253,8 +566,8 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do end end - it "with fails_with :llvm" do - source = <<-EOS.undent + it "fails_with :llvm block" do + source = <<~EOS class Foo < Formula desc "foo" url 'http://example.com/foo-1.0.tgz' @@ -268,11 +581,11 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do end EOS - expected_offenses = [{ message: "'fails_with :llvm' is now a no-op so should be removed", - severity: :convention, - line: 7, - column: 2, - source: source }] + expected_offenses = [{ message: "'fails_with :llvm' is now a no-op so should be removed", + severity: :convention, + line: 7, + column: 2, + source: source }] inspect_source(source) @@ -281,8 +594,8 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do end end - it "with def test" do - source = <<-EOS.undent + it "def test's deprecated usage" do + source = <<~EOS class Foo < Formula desc "foo" url 'http://example.com/foo-1.0.tgz' @@ -293,36 +606,11 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do end EOS - expected_offenses = [{ message: "Use new-style test definitions (test do)", - severity: :convention, - line: 5, - column: 2, - source: source }] - - inspect_source(source) - - expected_offenses.zip(cop.offenses).each do |expected, actual| - expect_offense(expected, actual) - end - end - - it "with def options" do - source = <<-EOS.undent - class Foo < Formula - desc "foo" - url 'http://example.com/foo-1.0.tgz' - - def options - [["--bar", "desc"]] - end - end - EOS - - expected_offenses = [{ message: "Use new-style option definitions", - severity: :convention, - line: 5, - column: 2, - source: source }] + expected_offenses = [{ message: "Use new-style test definitions (test do)", + severity: :convention, + line: 5, + column: 2, + source: source }] inspect_source(source) @@ -331,8 +619,8 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do end end - it "with deprecated skip_clean call" do - source = <<-EOS.undent + it "deprecated skip_clean call" do + source = <<~EOS class Foo < Formula desc "foo" url 'http://example.com/foo-1.0.tgz' @@ -340,9 +628,9 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do end EOS - expected_offenses = [{ message: <<-EOS.undent.chomp, - `skip_clean :all` is deprecated; brew no longer strips symbols - Pass explicit paths to prevent Homebrew from removing empty folders. + expected_offenses = [{ message: <<~EOS.chomp, + `skip_clean :all` is deprecated; brew no longer strips symbols + Pass explicit paths to prevent Homebrew from removing empty folders. EOS severity: :convention, line: 4, @@ -356,8 +644,8 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do end end - it "with build.universal?" do - source = <<-EOS.undent + it "build.universal? deprecated usage" do + source = <<~EOS class Foo < Formula desc "foo" url 'http://example.com/foo-1.0.tgz' @@ -367,11 +655,11 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do end EOS - expected_offenses = [{ message: "macOS has been 64-bit only since 10.6 so build.universal? is deprecated.", - severity: :convention, - line: 4, - column: 5, - source: source }] + expected_offenses = [{ message: "macOS has been 64-bit only since 10.6 so build.universal? is deprecated.", + severity: :convention, + line: 4, + column: 5, + source: source }] inspect_source(source) @@ -380,8 +668,8 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do end end - it "with build.universal? exempted formula" do - source = <<-EOS.undent + it "build.universal? deprecation exempted formula" do + source = <<~EOS class Wine < Formula desc "foo" url 'http://example.com/foo-1.0.tgz' @@ -392,11 +680,11 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do EOS inspect_source(source, "/homebrew-core/Formula/wine.rb") - expect(cop.offenses).to eq([]) + expect(cop.offenses).to be_empty end - it "with ENV.universal_binary" do - source = <<-EOS.undent + it "deprecated ENV.universal_binary usage" do + source = <<~EOS class Foo < Formula desc "foo" url 'http://example.com/foo-1.0.tgz' @@ -406,11 +694,11 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do end EOS - expected_offenses = [{ message: "macOS has been 64-bit only since 10.6 so ENV.universal_binary is deprecated.", - severity: :convention, - line: 5, - column: 5, - source: source }] + expected_offenses = [{ message: "macOS has been 64-bit only since 10.6 so ENV.universal_binary is deprecated.", + severity: :convention, + line: 5, + column: 5, + source: source }] inspect_source(source) @@ -419,8 +707,23 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do end end - it "with ENV.universal_binary" do - source = <<-EOS.undent + it "ENV.universal_binary deprecation exempted formula" do + source = <<~EOS + class Wine < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + if build? + ENV.universal_binary + end + end + EOS + + inspect_source(source, "/homebrew-core/Formula/wine.rb") + expect(cop.offenses).to be_empty + end + + it "deprecated ENV.x11 usage" do + source = <<~EOS class Foo < Formula desc "foo" url 'http://example.com/foo-1.0.tgz' @@ -430,11 +733,11 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do end EOS - expected_offenses = [{ message: 'Use "depends_on :x11" instead of "ENV.x11"', - severity: :convention, - line: 5, - column: 5, - source: source }] + expected_offenses = [{ message: 'Use "depends_on :x11" instead of "ENV.x11"', + severity: :convention, + line: 5, + column: 5, + source: source }] inspect_source(source) @@ -443,8 +746,8 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do end end - it "with ruby-macho alternatives" do - source = <<-EOS.undent + it "install_name_tool usage instead of ruby-macho" do + source = <<~EOS class Foo < Formula desc "foo" url 'http://example.com/foo-1.0.tgz' @@ -452,11 +755,11 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do end EOS - expected_offenses = [{ message: 'Use ruby-macho instead of calling "install_name_tool"', - severity: :convention, - line: 4, - column: 10, - source: source }] + expected_offenses = [{ message: 'Use ruby-macho instead of calling "install_name_tool"', + severity: :convention, + line: 4, + column: 10, + source: source }] inspect_source(source) @@ -465,8 +768,8 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do end end - it "with ruby-macho alternatives audit exempted formula" do - source = <<-EOS.undent + it "ruby-macho alternatives audit exempted formula" do + source = <<~EOS class Cctools < Formula desc "foo" url 'http://example.com/foo-1.0.tgz' @@ -475,11 +778,11 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do EOS inspect_source(source, "/homebrew-core/Formula/cctools.rb") - expect(cop.offenses).to eq([]) + expect(cop.offenses).to be_empty end - it "with npm install without language::Node args" do - source = <<-EOS.undent + it "npm install without language::Node args" do + source = <<~EOS class Foo < Formula desc "foo" url 'http://example.com/foo-1.0.tgz' @@ -487,11 +790,11 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do end EOS - expected_offenses = [{ message: "Use Language::Node for npm install args", - severity: :convention, - line: 4, - column: 2, - source: source }] + expected_offenses = [{ message: "Use Language::Node for npm install args", + severity: :convention, + line: 4, + column: 2, + source: source }] inspect_source(source) @@ -500,8 +803,8 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do end end - it "with npm install without language::Node args in kibana" do - source = <<-EOS.undent + it "npm install without language::Node args in kibana(exempted formula)" do + source = <<~EOS class KibanaAT44 < Formula desc "foo" url 'http://example.com/foo-1.0.tgz' @@ -510,7 +813,588 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do EOS inspect_source(source, "/homebrew-core/Formula/kibana@4.4.rb") - expect(cop.offenses).to eq([]) + expect(cop.offenses).to be_empty + end + + it "depends_on with an instance as argument" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + depends_on FOO::BAR.new + end + EOS + + expected_offenses = [{ message: "`depends_on` can take requirement classes instead of instances", + severity: :convention, + line: 4, + column: 13, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "old style OS check" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + depends_on :foo if MacOS.snow_leopard? + end + EOS + + expected_offenses = [{ message: "\"MacOS.snow_leopard?\" is deprecated, use a comparison to MacOS.version instead", + severity: :convention, + line: 4, + column: 21, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "non glob DIR usage" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + rm_rf Dir["src/{llvm,test,librustdoc,etc/snapshot.pyc}"] + rm_rf Dir["src/snapshot.pyc"] + end + EOS + + expected_offenses = [{ message: 'Dir(["src/snapshot.pyc"]) is unnecessary; just use "src/snapshot.pyc"', + severity: :convention, + line: 5, + column: 13, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "system call to fileUtils Method" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + system "mkdir", "foo" + end + EOS + + expected_offenses = [{ message: 'Use the `mkdir` Ruby method instead of `system "mkdir", "foo"`', + severity: :convention, + line: 4, + column: 10, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "top-level function def outside class body" do + source = <<~EOS + def test + nil + end + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + end + EOS + + expected_offenses = [{ message: "Define method test in the class body, not at the top-level", + severity: :convention, + line: 1, + column: 0, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "Using ARGV to check options" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + def install + verbose = ARGV.verbose? + end + end + EOS + + expected_offenses = [{ message: "Use build instead of ARGV to check options", + severity: :convention, + line: 5, + column: 14, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it 'man+"man8" usage' do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + def install + man1.install man+"man8" => "faad.1" + end + end + EOS + + expected_offenses = [{ message: '"man+"man8"" should be "man8"', + severity: :convention, + line: 5, + column: 22, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "hardcoded gcc compiler" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + def install + system "/usr/bin/gcc", "foo" + end + end + EOS + + expected_offenses = [{ message: "Use \"\#{ENV.cc}\" instead of hard-coding \"gcc\"", + severity: :convention, + line: 5, + column: 12, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "hardcoded g++ compiler" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + def install + system "/usr/bin/g++", "-o", "foo", "foo.cc" + end + end + EOS + + expected_offenses = [{ message: "Use \"\#{ENV.cxx}\" instead of hard-coding \"g++\"", + severity: :convention, + line: 5, + column: 12, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "hardcoded llvm-g++ compiler" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + def install + ENV["COMPILER_PATH"] = "/usr/bin/llvm-g++" + end + end + EOS + + expected_offenses = [{ message: "Use \"\#{ENV.cxx}\" instead of hard-coding \"llvm-g++\"", + severity: :convention, + line: 5, + column: 28, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "hardcoded gcc compiler" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + def install + ENV["COMPILER_PATH"] = "/usr/bin/gcc" + end + end + EOS + + expected_offenses = [{ message: "Use \"\#{ENV.cc}\" instead of hard-coding \"gcc\"", + severity: :convention, + line: 5, + column: 28, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "formula path shortcut : man" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + def install + mv "\#{share}/man", share + end + end + EOS + + expected_offenses = [{ message: '"#{share}/man" should be "#{man}"', + severity: :convention, + line: 5, + column: 17, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "formula path shortcut : libexec" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + def install + mv "\#{prefix}/libexec", share + end + end + EOS + + expected_offenses = [{ message: "\"\#\{prefix}/libexec\" should be \"\#{libexec}\"", + severity: :convention, + line: 5, + column: 18, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "formula path shortcut : info" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + def install + system "./configure", "--INFODIR=\#{prefix}/share/info" + end + end + EOS + + expected_offenses = [{ message: "\"\#\{prefix}/share/info\" should be \"\#{info}\"", + severity: :convention, + line: 5, + column: 47, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "formula path shortcut : man8" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + def install + system "./configure", "--MANDIR=\#{prefix}/share/man/man8" + end + end + EOS + + expected_offenses = [{ message: "\"\#\{prefix}/share/man/man8\" should be \"\#{man8}\"", + severity: :convention, + line: 5, + column: 46, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "dependecies which have to vendored" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + depends_on "lpeg" => :lua51 + end + EOS + + expected_offenses = [{ message: "lua modules should be vendored rather than use deprecated depends_on \"lpeg\" => :lua51`", + severity: :convention, + line: 4, + column: 24, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "manually setting env" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + system "export", "var=value" + end + EOS + + expected_offenses = [{ message: "Use ENV instead of invoking 'export' to modify the environment", + severity: :convention, + line: 4, + column: 10, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "dependencies with invalid options" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + depends_on "foo" => "with-bar" + end + EOS + + expected_offenses = [{ message: "Dependency foo should not use option with-bar", + severity: :convention, + line: 4, + column: 13, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "inspecting version manually" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + if version == "HEAD" + foo() + end + end + EOS + + expected_offenses = [{ message: "Use 'build.head?' instead of inspecting 'version'", + severity: :convention, + line: 4, + column: 5, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "deprecated ENV.fortran usage" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + test do + ENV.fortran + end + end + EOS + + expected_offenses = [{ message: "Use `depends_on :fortran` instead of `ENV.fortran`", + severity: :convention, + line: 5, + column: 4, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "deprecated ARGV.include? (--HEAD) usage" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + test do + head = ARGV.include? "--HEAD" + end + end + EOS + + expected_offenses = [{ message: 'Use "if build.head?" instead', + severity: :convention, + line: 5, + column: 26, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "deprecated MACOS_VERSION const usage" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + test do + version = MACOS_VERSION + end + end + EOS + + expected_offenses = [{ message: "Use MacOS.version instead of MACOS_VERSION", + severity: :convention, + line: 5, + column: 14, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "deprecated if build.with? conditional dependency" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + depends_on "foo" if build.with? "with-foo" + end + EOS + + expected_offenses = [{ message: 'Replace depends_on "foo" if build.with? "with-foo" with depends_on "foo" => :optional', + severity: :convention, + line: 4, + column: 2, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "unless conditional dependency with build.without?" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + depends_on :foo unless build.without? "foo" + end + EOS + + expected_offenses = [{ message: 'Replace depends_on :foo unless build.without? "foo" with depends_on :foo => :recommended', + severity: :convention, + line: 4, + column: 2, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "unless conditional dependency with build.include?" do + source = <<~EOS + class Foo < Formula + desc "foo" + url 'http://example.com/foo-1.0.tgz' + depends_on :foo unless build.include? "without-foo" + end + EOS + + expected_offenses = [{ message: 'Replace depends_on :foo unless build.include? "without-foo" with depends_on :foo => :recommended', + severity: :convention, + line: 4, + column: 2, + source: source }] + + inspect_source(source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end end end end diff --git a/Library/Homebrew/test/rubocops/options_cop_spec.rb b/Library/Homebrew/test/rubocops/options_cop_spec.rb index c27389a68..1ed6ee740 100644 --- a/Library/Homebrew/test/rubocops/options_cop_spec.rb +++ b/Library/Homebrew/test/rubocops/options_cop_spec.rb @@ -8,7 +8,7 @@ describe RuboCop::Cop::FormulaAudit::Options do context "When auditing options" do it "32-bit" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url 'http://example.com/foo-1.0.tgz' option "32-bit", "with 32-bit" @@ -35,7 +35,7 @@ describe RuboCop::Cop::FormulaAuditStrict::Options do context "When auditing options strictly" do it "with universal" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url 'http://example.com/foo-1.0.tgz' option :universal @@ -56,7 +56,7 @@ describe RuboCop::Cop::FormulaAuditStrict::Options do end it "with deprecated options" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url 'http://example.com/foo-1.0.tgz' option :cxx11 @@ -80,7 +80,7 @@ describe RuboCop::Cop::FormulaAuditStrict::Options do end it "with misc deprecated options" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url 'http://example.com/foo-1.0.tgz' option "without-check" @@ -109,7 +109,7 @@ describe RuboCop::Cop::NewFormulaAudit::Options do context "When auditing options for a new formula" do it "with deprecated options" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url 'http://example.com/foo-1.0.tgz' deprecated_option "examples" => "with-examples" diff --git a/Library/Homebrew/test/rubocops/patches_cop_spec.rb b/Library/Homebrew/test/rubocops/patches_cop_spec.rb index 4f9ca2df8..fdecb676e 100644 --- a/Library/Homebrew/test/rubocops/patches_cop_spec.rb +++ b/Library/Homebrew/test/rubocops/patches_cop_spec.rb @@ -8,7 +8,7 @@ describe RuboCop::Cop::FormulaAudit::Patches do context "When auditing legacy patches" do it "When there is no legacy patch" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url 'http://example.com/foo-1.0.tgz' end @@ -18,7 +18,7 @@ describe RuboCop::Cop::FormulaAudit::Patches do end it "Formula with `def patches`" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula homepage "ftp://example.com/foo" url "http://example.com/foo-1.0.tgz" @@ -51,7 +51,7 @@ describe RuboCop::Cop::FormulaAudit::Patches do "https://github.com/dlang/dub/pull/1221.patch", ] patch_urls.each do |patch_url| - source = <<-EOS.undent + source = <<~EOS class Foo < Formula homepage "ftp://example.com/foo" url "http://example.com/foo-1.0.tgz" @@ -63,56 +63,56 @@ describe RuboCop::Cop::FormulaAudit::Patches do inspect_source(source) expected_offense = if patch_url =~ %r{/raw\.github\.com/} - [{ message: <<-EOS.undent.chomp, - GitHub/Gist patches should specify a revision: - #{patch_url} + [{ message: <<~EOS.chomp, + GitHub/Gist patches should specify a revision: + #{patch_url} EOS severity: :convention, line: 5, column: 12, source: source }] elsif patch_url =~ %r{macports/trunk} - [{ message: <<-EOS.undent.chomp, - MacPorts patches should specify a revision instead of trunk: - #{patch_url} + [{ message: <<~EOS.chomp, + MacPorts patches should specify a revision instead of trunk: + #{patch_url} EOS severity: :convention, line: 5, column: 33, source: source }] elsif patch_url =~ %r{^http://trac\.macports\.org} - [{ message: <<-EOS.undent.chomp, - Patches from MacPorts Trac should be https://, not http: - #{patch_url} + [{ message: <<~EOS.chomp, + Patches from MacPorts Trac should be https://, not http: + #{patch_url} EOS severity: :convention, line: 5, column: 5, source: source }] elsif patch_url =~ %r{^http://bugs\.debian\.org} - [{ message: <<-EOS.undent.chomp, - Patches from Debian should be https://, not http: - #{patch_url} + [{ message: <<~EOS.chomp, + Patches from Debian should be https://, not http: + #{patch_url} EOS severity: :convention, line: 5, column: 5, source: source }] elsif patch_url =~ %r{https?://patch-diff\.githubusercontent\.com/raw/(.+)/(.+)/pull/(.+)\.(?:diff|patch)} - [{ message: <<-EOS.undent, - use GitHub pull request URLs: - https://github.com/foo/foo-bar/pull/100.patch - Rather than patch-diff: - https://patch-diff.githubusercontent.com/raw/foo/foo-bar/pull/100.patch + [{ message: <<~EOS, + use GitHub pull request URLs: + https://github.com/foo/foo-bar/pull/100.patch + Rather than patch-diff: + https://patch-diff.githubusercontent.com/raw/foo/foo-bar/pull/100.patch EOS severity: :convention, line: 5, column: 5, source: source }] elsif patch_url =~ %r{https?://github\.com/.+/.+/(?:commit|pull)/[a-fA-F0-9]*.(?:patch|diff)} - [{ message: <<-EOS.undent, - GitHub patches should use the full_index parameter: - #{patch_url}?full_index=1 + [{ message: <<~EOS, + GitHub patches should use the full_index parameter: + #{patch_url}?full_index=1 EOS severity: :convention, line: 5, @@ -126,7 +126,7 @@ describe RuboCop::Cop::FormulaAudit::Patches do end it "Formula with nested `def patches`" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula homepage "ftp://example.com/foo" url "http://example.com/foo-1.0.tgz" @@ -145,9 +145,9 @@ describe RuboCop::Cop::FormulaAudit::Patches do line: 4, column: 2, source: source }, - { message: <<-EOS.undent.chomp, - Patches from MacPorts Trac should be https://, not http: - http://trac.macports.org/export/68507/trunk/dports/net/trafshow/files/ + { message: <<~EOS.chomp, + Patches from MacPorts Trac should be https://, not http: + http://trac.macports.org/export/68507/trunk/dports/net/trafshow/files/ EOS severity: :convention, line: 8, @@ -172,7 +172,7 @@ describe RuboCop::Cop::FormulaAudit::Patches do "https://patch-diff.githubusercontent.com/raw/foo/foo-bar/pull/100.patch", ] patch_urls.each do |patch_url| - source = <<-EOS.undent + source = <<~EOS class Foo < Formula homepage "ftp://example.com/foo" url "http://example.com/foo-1.0.tgz" @@ -185,47 +185,47 @@ describe RuboCop::Cop::FormulaAudit::Patches do inspect_source(source) expected_offense = if patch_url =~ %r{/raw\.github\.com/} - [{ message: <<-EOS.undent.chomp, - GitHub/Gist patches should specify a revision: - #{patch_url} + [{ message: <<~EOS.chomp, + GitHub/Gist patches should specify a revision: + #{patch_url} EOS severity: :convention, line: 5, column: 16, source: source }] elsif patch_url =~ %r{macports/trunk} - [{ message: <<-EOS.undent.chomp, - MacPorts patches should specify a revision instead of trunk: - #{patch_url} + [{ message: <<~EOS.chomp, + MacPorts patches should specify a revision instead of trunk: + #{patch_url} EOS severity: :convention, line: 5, column: 37, source: source }] elsif patch_url =~ %r{^http://trac\.macports\.org} - [{ message: <<-EOS.undent.chomp, - Patches from MacPorts Trac should be https://, not http: - #{patch_url} + [{ message: <<~EOS.chomp, + Patches from MacPorts Trac should be https://, not http: + #{patch_url} EOS severity: :convention, line: 5, column: 9, source: source }] elsif patch_url =~ %r{^http://bugs\.debian\.org} - [{ message: <<-EOS.undent.chomp, - Patches from Debian should be https://, not http: - #{patch_url} + [{ message: <<~EOS.chomp, + Patches from Debian should be https://, not http: + #{patch_url} EOS severity: :convention, line: 5, column: 9, source: source }] elsif patch_url =~ %r{https?://patch-diff\.githubusercontent\.com/raw/(.+)/(.+)/pull/(.+)\.(?:diff|patch)} - [{ message: <<-EOS.undent, - use GitHub pull request URLs: - https://github.com/foo/foo-bar/pull/100.patch - Rather than patch-diff: - https://patch-diff.githubusercontent.com/raw/foo/foo-bar/pull/100.patch + [{ message: <<~EOS, + use GitHub pull request URLs: + https://github.com/foo/foo-bar/pull/100.patch + Rather than patch-diff: + https://patch-diff.githubusercontent.com/raw/foo/foo-bar/pull/100.patch EOS severity: :convention, line: 5, diff --git a/Library/Homebrew/test/rubocops/text_cop_spec.rb b/Library/Homebrew/test/rubocops/text_cop_spec.rb index 490801770..dbddff1ad 100644 --- a/Library/Homebrew/test/rubocops/text_cop_spec.rb +++ b/Library/Homebrew/test/rubocops/text_cop_spec.rb @@ -8,7 +8,7 @@ describe RuboCop::Cop::FormulaAudit::Text do context "When auditing formula text" do it "with both openssl and libressl optional dependencies" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url "http://example.com/foo-1.0.tgz" homepage "http://example.com" @@ -32,7 +32,7 @@ describe RuboCop::Cop::FormulaAudit::Text do end it "with both openssl and libressl dependencies" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url "http://example.com/foo-1.0.tgz" homepage "http://example.com" @@ -56,7 +56,7 @@ describe RuboCop::Cop::FormulaAudit::Text do end it "When xcodebuild is called without SYMROOT" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url "http://example.com/foo-1.0.tgz" homepage "http://example.com" @@ -81,7 +81,7 @@ describe RuboCop::Cop::FormulaAudit::Text do end it "When xcodebuild is called without any args" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url "http://example.com/foo-1.0.tgz" homepage "http://example.com" @@ -106,7 +106,7 @@ describe RuboCop::Cop::FormulaAudit::Text do end it "When go get is executed" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url "http://example.com/foo-1.0.tgz" homepage "http://example.com" @@ -131,7 +131,7 @@ describe RuboCop::Cop::FormulaAudit::Text do end it "When xcodebuild is executed" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url "http://example.com/foo-1.0.tgz" homepage "http://example.com" @@ -156,7 +156,7 @@ describe RuboCop::Cop::FormulaAudit::Text do end it "When scons is executed" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url "http://example.com/foo-1.0.tgz" homepage "http://example.com" @@ -180,8 +180,8 @@ describe RuboCop::Cop::FormulaAudit::Text do end end - it "When plist_options are not defined when using a formula-defined plist" do - source = <<-EOS.undent + it "When plist_options are not defined when using a formula-defined plist", :ruby23 do + source = <<~RUBY class Foo < Formula url "http://example.com/foo-1.0.tgz" homepage "http://example.com" @@ -190,19 +190,20 @@ describe RuboCop::Cop::FormulaAudit::Text do system "xcodebuild", "foo", "bar" end - def plist; <<-EOS.undent - <?xml version="1.0" encoding="UTF-8"?> - <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> - <plist version="1.0"> - <dict> - <key>Label</key> - <string>org.nrpe.agent</string> - </dict> - </plist> - \EOS + def plist + <<~XML + <?xml version="1.0" encoding="UTF-8"?> + <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> + <plist version="1.0"> + <dict> + <key>Label</key> + <string>org.nrpe.agent</string> + </dict> + </plist> + XML end end - EOS + RUBY expected_offenses = [{ message: "Please set plist_options when using a formula-defined plist.", severity: :convention, @@ -218,7 +219,7 @@ describe RuboCop::Cop::FormulaAudit::Text do end it "When language/go is require'd" do - source = <<-EOS.undent + source = <<~EOS require "language/go" class Foo < Formula @@ -245,7 +246,7 @@ describe RuboCop::Cop::FormulaAudit::Text do end it "When formula uses virtualenv and also `setuptools` resource" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url "http://example.com/foo-1.0.tgz" homepage "http://example.com" @@ -275,7 +276,7 @@ describe RuboCop::Cop::FormulaAudit::Text do end it "When Formula.factory(name) is used" do - source = <<-EOS.undent + source = <<~EOS class Foo < Formula url "http://example.com/foo-1.0.tgz" homepage "http://example.com" diff --git a/Library/Homebrew/test/rubocops/urls_cop_spec.rb b/Library/Homebrew/test/rubocops/urls_cop_spec.rb index ad939a1a2..0bda7f110 100644 --- a/Library/Homebrew/test/rubocops/urls_cop_spec.rb +++ b/Library/Homebrew/test/rubocops/urls_cop_spec.rb @@ -54,7 +54,7 @@ describe RuboCop::Cop::FormulaAudit::Urls do "col" => 2, }, { "url" => "http://prdownloads.sourceforge.net/foo/foo-1.tar.gz", - "msg" => <<-EOS.undent.chomp, + "msg" => <<~EOS.chomp, Don't use prdownloads in SourceForge urls (url is http://prdownloads.sourceforge.net/foo/foo-1.tar.gz). See: http://librelist.com/browser/homebrew/2011/1/12/prdownloads-is-bad/ EOS @@ -69,7 +69,7 @@ describe RuboCop::Cop::FormulaAudit::Urls do "col" => 2, }, { "url" => "http://http.debian.net/debian/dists/foo/", - "msg" => <<-EOS.undent, + "msg" => <<~EOS, Please use a secure mirror for Debian URLs. We recommend: https://mirrors.ocf.berkeley.edu/debian/dists/foo/ @@ -101,7 +101,7 @@ describe RuboCop::Cop::FormulaAudit::Urls do "col" => 2, }, { "url" => "https://codeload.github.com/foo/bar/tar.gz/v0.1.1", - "msg" => <<-EOS.undent, + "msg" => <<~EOS, Use GitHub archive URLs: https://github.com/foo/bar/archive/v0.1.1.tar.gz Rather than codeload: @@ -114,7 +114,7 @@ describe RuboCop::Cop::FormulaAudit::Urls do "col" => 2, }] formulas.each do |formula| - source = <<-EOS.undent + source = <<~EOS class Foo < Formula desc "foo" url "#{formula["url"]}" @@ -141,7 +141,7 @@ describe RuboCop::Cop::FormulaAudit::Urls do "col" => 4, }] formulas.each do |formula| - source = <<-EOS.undent + source = <<~EOS class Foo < Formula desc "foo" url "https://foo.com" @@ -169,12 +169,12 @@ describe RuboCop::Cop::FormulaAudit::Urls do end it "with duplicate mirror" do - source = <<-EOS.undent - class Foo < Formula - desc "foo" - url "https://ftpmirror.fnu.org/foo/foo-1.0.tar.gz" - mirror "https://ftpmirror.fnu.org/foo/foo-1.0.tar.gz" - end + source = <<~EOS + class Foo < Formula + desc "foo" + url "https://ftpmirror.fnu.org/foo/foo-1.0.tar.gz" + mirror "https://ftpmirror.fnu.org/foo/foo-1.0.tar.gz" + end EOS expected_offenses = [{ message: "URL should not be duplicated as a mirror: https://ftpmirror.fnu.org/foo/foo-1.0.tar.gz", @@ -204,13 +204,13 @@ describe RuboCop::Cop::FormulaAuditStrict::PyPiUrls do "corrected_url" =>"https://files.pythonhosted.org/packages/source/foo/foo-0.1.tar.gz", }] formulas.each do |formula| - source = <<-EOS.undent + source = <<~EOS class Foo < Formula desc "foo" url "#{formula["url"]}" end EOS - corrected_source = <<-EOS.undent + corrected_source = <<~EOS class Foo < Formula desc "foo" url "#{formula["corrected_url"]}" diff --git a/Library/Homebrew/test/sandbox_spec.rb b/Library/Homebrew/test/sandbox_spec.rb index 38ff4da75..774337967 100644 --- a/Library/Homebrew/test/sandbox_spec.rb +++ b/Library/Homebrew/test/sandbox_spec.rb @@ -49,7 +49,7 @@ describe Sandbox do it "ignores bogus Python error" do ENV["HOMEBREW_VERBOSE"] = "1" - with_bogus_error = <<-EOS.undent + with_bogus_error = <<~EOS foo Mar 17 02:55:06 sandboxd[342]: Python(49765) deny file-write-unlink /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/distutils/errors.pyc bar diff --git a/Library/Homebrew/test/spec_helper.rb b/Library/Homebrew/test/spec_helper.rb index a4ac84547..a5821ee14 100644 --- a/Library/Homebrew/test/spec_helper.rb +++ b/Library/Homebrew/test/spec_helper.rb @@ -131,7 +131,7 @@ RSpec.configure do |config| files_after_test = find_files diff = Set.new(@__files_before_test) ^ Set.new(files_after_test) - expect(diff).to be_empty, <<-EOS.undent + expect(diff).to be_empty, <<~EOS file leak detected: #{diff.map { |f| " #{f}" }.join("\n")} EOS diff --git a/Library/Homebrew/test/string_spec.rb b/Library/Homebrew/test/string_spec.rb index ce26d70d4..6de89dc99 100644 --- a/Library/Homebrew/test/string_spec.rb +++ b/Library/Homebrew/test/string_spec.rb @@ -1,41 +1,5 @@ require "extend/string" -describe String do - describe "#undent" do - it "removes leading whitespace, taking the first line as reference" do - string = <<-EOS.unindent - hi - ........my friend over - there - EOS - - expect(string).to eq("hi\n........my friend over\n there\n") - end - - it "removes nothing if the text is not indented" do - string = <<-EOS.unindent - hi - I'm not indented - EOS - - expect(string).to eq("hi\nI'm not indented\n") - end - - it "can be nested" do - nested_string = <<-EOS.undent - goodbye - EOS - - string = <<-EOS.undent - hello - #{nested_string} - EOS - - expect(string).to eq("hello\ngoodbye\n\n") - end - end -end - describe StringInreplaceExtension do subject { string.extend(described_class) } let(:string) { "foobar" } diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/with-caveats.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-caveats.rb index d5d90114a..5624f486e 100644 --- a/Library/Homebrew/test/support/fixtures/cask/Casks/with-caveats.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-caveats.rb @@ -8,7 +8,7 @@ cask 'with-caveats' do app 'Caffeine.app' # simple string is evaluated at compile-time - caveats <<-EOS.undent + caveats <<~EOS Here are some things you might want to know. EOS # do block is evaluated at install-time diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-script-app.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-script-app.rb index f5f3ae5dd..885f3b157 100644 --- a/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-script-app.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-script-app.rb @@ -8,7 +8,7 @@ cask 'with-uninstall-script-app' do app 'MyFancyApp/MyFancyApp.app' postflight do - IO.write "#{appdir}/MyFancyApp.app/uninstall.sh", <<-EOS.undent + IO.write "#{appdir}/MyFancyApp.app/uninstall.sh", <<~EOS #!/bin/sh /bin/rm -r "#{appdir}/MyFancyApp.app" EOS 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 7bf2ce96a..da01580c2 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 @@ -123,7 +123,7 @@ RSpec.shared_context "integration test" do def setup_test_formula(name, content = nil) case name when /^testball/ - content = <<-EOS.undent + content = <<~EOS desc "Some test" homepage "https://example.com/#{name}" url "file://#{TEST_FIXTURE_DIR}/tarballs/testball-0.1.tbz" @@ -145,18 +145,18 @@ RSpec.shared_context "integration test" do # something here EOS when "foo" - content = <<-EOS.undent + content = <<~EOS url "https://example.com/#{name}-1.0" EOS when "bar" - content = <<-EOS.undent + content = <<~EOS url "https://example.com/#{name}-1.0" depends_on "foo" EOS end Formulary.core_path(name).tap do |formula_path| - formula_path.write <<-EOS.undent + formula_path.write <<~EOS class #{Formulary.class_s(name)} < Formula #{content} end diff --git a/Library/Homebrew/test/tap_spec.rb b/Library/Homebrew/test/tap_spec.rb index 957f9bdd2..76af27b92 100644 --- a/Library/Homebrew/test/tap_spec.rb +++ b/Library/Homebrew/test/tap_spec.rb @@ -19,7 +19,7 @@ describe Tap do end def setup_tap_files - formula_file.write <<-EOS.undent + formula_file.write <<~EOS class Foo < Formula url "https://example.com/foo-1.0.tar.gz" end @@ -28,11 +28,11 @@ describe Tap do alias_file.parent.mkpath ln_s formula_file, alias_file - (path/"formula_renames.json").write <<-EOS.undent + (path/"formula_renames.json").write <<~EOS { "oldname": "foo" } EOS - (path/"tap_migrations.json").write <<-EOS.undent + (path/"tap_migrations.json").write <<~EOS { "removed-formula": "homebrew/foo" } EOS @@ -61,6 +61,7 @@ describe Tap do specify "::fetch" do begin + expect(described_class.fetch("Homebrew", "core")).to be_kind_of(CoreTap) expect(described_class.fetch("Homebrew", "homebrew")).to be_kind_of(CoreTap) tap = described_class.fetch("Homebrew", "foo") expect(tap).to be_kind_of(Tap) @@ -327,7 +328,7 @@ describe CoreTap do specify "files" do formula_file = subject.formula_dir/"foo.rb" - formula_file.write <<-EOS.undent + formula_file.write <<~EOS class Foo < Formula url "https://example.com/foo-1.0.tar.gz" end diff --git a/Library/Homebrew/test/utils_spec.rb b/Library/Homebrew/test/utils_spec.rb index 3b5355b15..0c2ae5161 100644 --- a/Library/Homebrew/test/utils_spec.rb +++ b/Library/Homebrew/test/utils_spec.rb @@ -98,7 +98,7 @@ describe "globally-scoped helper methods" do let(:shell) { dir/"myshell" } it "starts an interactive shell session" do - IO.write shell, <<-EOS.undent + IO.write shell, <<~EOS #!/bin/sh echo called > "#{dir}/called" EOS diff --git a/Library/Homebrew/test/version_spec.rb b/Library/Homebrew/test/version_spec.rb index d0393afa6..7d3e129f6 100644 --- a/Library/Homebrew/test/version_spec.rb +++ b/Library/Homebrew/test/version_spec.rb @@ -248,9 +248,9 @@ describe Version do end failure_message do |expected| - message = <<-EOS - expected: %s - detected: %s + message = <<~EOS + expected: %s + detected: %s EOS format(message, expected, detected) end diff --git a/Library/Homebrew/utils.rb b/Library/Homebrew/utils.rb index d293b2a6f..2211ed75b 100644 --- a/Library/Homebrew/utils.rb +++ b/Library/Homebrew/utils.rb @@ -93,7 +93,7 @@ def odeprecated(method, replacement = nil, disable: false, disable_on: nil, call end caller_message ||= backtrace[1] - message = <<-EOS.undent + message = <<~EOS Calling #{method} is #{verb}! #{replacement_message} #{caller_message}#{tap_message} @@ -223,16 +223,15 @@ module Homebrew end return if which(executable) - odie <<-EOS.undent + odie <<~EOS The '#{name}' gem is installed but couldn't find '#{executable}' in the PATH: #{ENV["PATH"]} EOS end - # Hash of Module => Set(method_names) - @injected_dump_stat_modules = {} - + # rubocop:disable Style/GlobalVars def inject_dump_stats!(the_module, pattern) + @injected_dump_stat_modules ||= {} @injected_dump_stat_modules[the_module] ||= [] injected_methods = @injected_dump_stat_modules[the_module] the_module.module_eval do @@ -260,6 +259,7 @@ module Homebrew end end end + # rubocop:enable Style/GlobalVars end def with_system_path @@ -347,7 +347,7 @@ def which_editor end editor ||= "/usr/bin/vim" - opoo <<-EOS.undent + opoo <<~EOS Using #{editor} because no editor was set in the environment. This may change in the future, so we recommend setting EDITOR, or HOMEBREW_EDITOR to your preferred text editor. diff --git a/Library/Homebrew/utils/fork.rb b/Library/Homebrew/utils/fork.rb index 2f2a403e2..57ddbfae2 100644 --- a/Library/Homebrew/utils/fork.rb +++ b/Library/Homebrew/utils/fork.rb @@ -14,7 +14,7 @@ module Utils read.close write.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) yield - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException Marshal.dump(e, write) write.close exit! @@ -26,8 +26,11 @@ module Utils ignore_interrupts(:quietly) do # the child will receive the interrupt and marshal it back begin socket = server.accept_nonblock + # rubocop:disable Lint/ShadowedException + # FIXME: https://github.com/bbatsov/rubocop/issues/4843 rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR retry unless Process.waitpid(pid, Process::WNOHANG) + # rubocop:enable Lint/ShadowedException else socket.send_io(write) socket.close @@ -36,7 +39,7 @@ module Utils data = read.read read.close Process.wait(pid) unless socket.nil? - raise Marshal.load(data) unless data.nil? || data.empty? + raise Marshal.load(data) unless data.nil? || data.empty? # rubocop:disable Security/MarshalLoad raise Interrupt if $CHILD_STATUS.exitstatus == 130 raise "Forked child process failed: #{$CHILD_STATUS}" unless $CHILD_STATUS.success? end diff --git a/Library/Homebrew/utils/github.rb b/Library/Homebrew/utils/github.rb index df0811e95..e73951c8d 100644 --- a/Library/Homebrew/utils/github.rb +++ b/Library/Homebrew/utils/github.rb @@ -16,7 +16,7 @@ module GitHub class RateLimitExceededError < Error def initialize(reset, error) - super <<-EOS.undent + super <<~EOS GitHub API Error: #{error} Try again in #{pretty_ratelimit_reset(reset)}, or create a personal access token: #{ALL_SCOPES_URL} @@ -33,12 +33,12 @@ module GitHub def initialize(error) message = "GitHub #{error}\n" if ENV["HOMEBREW_GITHUB_API_TOKEN"] - message << <<-EOS.undent + message << <<~EOS HOMEBREW_GITHUB_API_TOKEN may be invalid or expired; check: #{Formatter.url("https://github.com/settings/tokens")} EOS else - message << <<-EOS.undent + message << <<~EOS The GitHub credentials in the macOS keychain may be invalid. Clear them with: printf "protocol=https\\nhost=github.com\\n" | git credential-osxkeychain erase @@ -104,7 +104,7 @@ module GitHub case GitHub.api_credentials_type when :keychain - onoe <<-EOS.undent + onoe <<~EOS Your macOS keychain GitHub credentials do not have sufficient scope! Scopes they need: #{needed_human_scopes} Scopes they have: #{credentials_scopes} @@ -112,7 +112,7 @@ module GitHub and then set HOMEBREW_GITHUB_API_TOKEN as the authentication method instead. EOS when :environment - onoe <<-EOS.undent + onoe <<~EOS Your HOMEBREW_GITHUB_API_TOKEN does not have sufficient scope! Scopes they need: #{needed_human_scopes} Scopes it has: #{credentials_scopes} @@ -235,7 +235,7 @@ module GitHub def issues_for_formula(name, options = {}) tap = options[:tap] || CoreTap.instance - search_issues(name, state: "open", repo: "#{tap.user}/homebrew-#{tap.repo}") + search_issues(name, state: "open", repo: "#{tap.user}/homebrew-#{tap.repo}", in: "title") end def print_pull_requests_matching(query) diff --git a/Library/Homebrew/utils/link.rb b/Library/Homebrew/utils/link.rb index 095dba209..96bfd602e 100644 --- a/Library/Homebrew/utils/link.rb +++ b/Library/Homebrew/utils/link.rb @@ -22,7 +22,7 @@ module Utils end return if conflicts.empty? - onoe <<-EOS.undent + onoe <<~EOS Could not link: #{conflicts.join("\n")} diff --git a/Library/Homebrew/utils/ruby.sh b/Library/Homebrew/utils/ruby.sh index 9a3ab2e81..b16531e9f 100644 --- a/Library/Homebrew/utils/ruby.sh +++ b/Library/Homebrew/utils/ruby.sh @@ -40,7 +40,7 @@ setup-ruby-path() { ruby_old_version="$("$HOMEBREW_RUBY_PATH" -rrubygems -e "puts Gem::Version.new('$minimum_ruby_version') > Gem::Version.new(RUBY_VERSION)")" fi - if [[ "$ruby_old_version" == "true" || -n "$HOMEBREW_FORCE_VENDOR_RUBY" ]] + if [[ -z "$HOMEBREW_RUBY_PATH" || "$ruby_old_version" == "true" || -n "$HOMEBREW_FORCE_VENDOR_RUBY" ]] then brew vendor-install ruby if [[ ! -x "$vendor_ruby_path" ]] diff --git a/Library/Homebrew/version.rb b/Library/Homebrew/version.rb index 3ac748037..d43e0c665 100644 --- a/Library/Homebrew/version.rb +++ b/Library/Homebrew/version.rb @@ -213,110 +213,6 @@ class Version end end - def initialize(val) - unless val.respond_to?(:to_str) - raise TypeError, "Version value must be a string; got a #{val.class} (#{val})" - end - @version = val.to_str - end - - def detected_from_url? - false - end - - def head? - false - end - - def null? - false - end - - def <=>(other) - # Needed to retain API compatibility with older string comparisons - # for compiler versions, etc. - other = Version.new(other) if other.is_a? String - # Used by the *_build_version comparisons, which formerly returned Fixnum - other = Version.new(other.to_s) if other.is_a? Integer - return 1 if other.nil? - - return unless other.is_a?(Version) - return 0 if version == other.version - return 1 if head? && !other.head? - return -1 if !head? && other.head? - return 0 if head? && other.head? - - ltokens = tokens - rtokens = other.tokens - max = max(ltokens.length, rtokens.length) - l = r = 0 - - while l < max - a = ltokens[l] || NULL_TOKEN - b = rtokens[r] || NULL_TOKEN - - if a == b - l += 1 - r += 1 - next - elsif a.numeric? && b.numeric? - return a <=> b - elsif a.numeric? - return 1 if a > NULL_TOKEN - l += 1 - elsif b.numeric? - return -1 if b > NULL_TOKEN - r += 1 - else - return a <=> b - end - end - - 0 - end - alias eql? == - - def hash - version.hash - end - - def to_f - version.to_f - end - - def to_s - version.dup - end - alias to_str to_s - - protected - - attr_reader :version - - def tokens - @tokens ||= tokenize - end - - private - - def max(a, b) - (a > b) ? a : b - end - - def tokenize - version.scan(SCAN_PATTERN).map! do |token| - case token - when /\A#{AlphaToken::PATTERN}\z/o then AlphaToken - when /\A#{BetaToken::PATTERN}\z/o then BetaToken - when /\A#{RCToken::PATTERN}\z/o then RCToken - when /\A#{PreToken::PATTERN}\z/o then PreToken - when /\A#{PatchToken::PATTERN}\z/o then PatchToken - when /\A#{NumericToken::PATTERN}\z/o then NumericToken - when /\A#{StringToken::PATTERN}\z/o then StringToken - end.new(token) - end - end - def self.parse(spec) version = _parse(spec) version.nil? ? NULL : new(version) @@ -461,6 +357,112 @@ class Version m = /[-.vV]?((?:\d+\.)+\d+(?:[-_.]?(?i:alpha|beta|pre|rc)\.?\d{,2})?)/.match(spec_s) return m.captures.first unless m.nil? end + + private_class_method :_parse + + def initialize(val) + unless val.respond_to?(:to_str) + raise TypeError, "Version value must be a string; got a #{val.class} (#{val})" + end + @version = val.to_str + end + + def detected_from_url? + false + end + + def head? + false + end + + def null? + false + end + + def <=>(other) + # Needed to retain API compatibility with older string comparisons + # for compiler versions, etc. + other = Version.new(other) if other.is_a? String + # Used by the *_build_version comparisons, which formerly returned Fixnum + other = Version.new(other.to_s) if other.is_a? Integer + return 1 if other.nil? + + return unless other.is_a?(Version) + return 0 if version == other.version + return 1 if head? && !other.head? + return -1 if !head? && other.head? + return 0 if head? && other.head? + + ltokens = tokens + rtokens = other.tokens + max = max(ltokens.length, rtokens.length) + l = r = 0 + + while l < max + a = ltokens[l] || NULL_TOKEN + b = rtokens[r] || NULL_TOKEN + + if a == b + l += 1 + r += 1 + next + elsif a.numeric? && b.numeric? + return a <=> b + elsif a.numeric? + return 1 if a > NULL_TOKEN + l += 1 + elsif b.numeric? + return -1 if b > NULL_TOKEN + r += 1 + else + return a <=> b + end + end + + 0 + end + alias eql? == + + def hash + version.hash + end + + def to_f + version.to_f + end + + def to_s + version.dup + end + alias to_str to_s + + protected + + attr_reader :version + + def tokens + @tokens ||= tokenize + end + + private + + def max(a, b) + (a > b) ? a : b + end + + def tokenize + version.scan(SCAN_PATTERN).map! do |token| + case token + when /\A#{AlphaToken::PATTERN}\z/o then AlphaToken + when /\A#{BetaToken::PATTERN}\z/o then BetaToken + when /\A#{RCToken::PATTERN}\z/o then RCToken + when /\A#{PreToken::PATTERN}\z/o then PreToken + when /\A#{PatchToken::PATTERN}\z/o then PatchToken + when /\A#{NumericToken::PATTERN}\z/o then NumericToken + when /\A#{StringToken::PATTERN}\z/o then StringToken + end.new(token) + end + end end class HeadVersion < Version diff --git a/docs/Checksum_Deprecation.md b/docs/Checksum_Deprecation.md index 3ef0d41ec..a2e49e50a 100644 --- a/docs/Checksum_Deprecation.md +++ b/docs/Checksum_Deprecation.md @@ -1,22 +1,18 @@ # MD5 and SHA-1 Deprecation -During early 2015 Homebrew started the process of deprecating _SHA1_ for package -integrity verification. Since then every formulae under the Homebrew organisation -has been moved onto _SHA256_ verification; this includes both source packages -and our precompiled packages (bottles). +In early 2015 Homebrew started the process of deprecating _SHA1_ for package +integrity verification. Since then formulae under the Homebrew organisation +have been moved onto using _SHA256_ for verification; this includes both source +packages and our precompiled packages (bottles). -We have stopped supporting _SHA1_ and _MD5_ entirely. -_MD5_ checksums were removed from core formulae in 2012 but until April 2015 -if you tried to install a formula still using one Homebrew wouldn't actively stop you. +Homebrew has since stopped supporting _SHA1_ and _MD5_ entirely. +_MD5_ checksums were removed from core formulae in 2012 and as of April 2015 +installing a formula verified by _MD5_ is actively blocked. We removed _SHA1_ support in **November 2016**, 21 months after we started warning people to move away from it for verification. This is enforced in the same way _MD5_ is, by blocking the installation of that individual formula until the checksum is migrated. -From March 20th 2016 we've stepped up the visibility of that notification & you'll start -seeing deprecation warnings when installing _SHA1_-validated formula. -If you see these please consider reporting it to where the formula originated. - This means custom taps, local custom formulae, etc need to be migrated to use _SHA256_ before you can install them. diff --git a/docs/External-Commands.md b/docs/External-Commands.md index e1178ceda..881a1293a 100644 --- a/docs/External-Commands.md +++ b/docs/External-Commands.md @@ -44,12 +44,12 @@ Note they are largely untested, and as always, be careful about running untested ### brew-livecheck Check if there is a new upstream version of a formula. -See the [`README`](https://github.com/youtux/homebrew-livecheck/blob/master/README.md) for more info and usage. +See the [`README`](https://github.com/Homebrew/homebrew-livecheck/blob/master/README.md) for more info and usage. Install using: ```sh -brew tap youtux/livecheck +brew tap homebrew/livecheck ``` ### brew-gem diff --git a/docs/Manpage.md b/docs/Manpage.md index f92991147..59969a3e8 100644 --- a/docs/Manpage.md +++ b/docs/Manpage.md @@ -770,7 +770,7 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note Additionally, the date used in new manpages will match those in the existing manpages (to allow comparison without factoring in the date). - * `pull` [`--bottle`] [`--bump`] [`--clean`] [`--ignore-whitespace`] [`--resolve`] [`--branch-okay`] [`--no-pbcopy`] [`--no-publish`] [`--warn-on-publish-failure`] `patch-source` [`patch-source`]: + * `pull` [`--bottle`] [`--bump`] [`--clean`] [`--ignore-whitespace`] [`--resolve`] [`--branch-okay`] [`--no-pbcopy`] [`--no-publish`] [`--warn-on-publish-failure`] [`--bintray-org=``bintray-org`] [`--test-bot-user=``test-bot-user`] `patch-source` [`patch-source`]: Gets a patch from a GitHub commit or pull request and applies it to Homebrew. Optionally, installs the formulae changed by the patch. @@ -814,6 +814,12 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note If `--warn-on-publish-failure` was passed, do not exit if there's a failure publishing bottles on Bintray. + If `--bintray-org=``bintray-org` is passed, publish at the given Bintray + organisation. + + If `--test-bot-user=``test-bot-user` is passed, pull the bottle block + commit from the specified user on GitHub. + * `release-notes` [`--markdown`] [`previous_tag`] [`end_ref`]: Output the merged pull requests on Homebrew/brew between two Git refs. If no `previous_tag` is provided it defaults to the newest tag. diff --git a/docs/Xcode.md b/docs/Xcode.md index 21ad66f95..18ced07ed 100644 --- a/docs/Xcode.md +++ b/docs/Xcode.md @@ -12,7 +12,8 @@ Tools available for your platform: | 10.9 | 6.2 | 6.2 | | 10.10 | 7.2.1 | 7.2 | | 10.11 | 8.2.1 | 8.2 | -| 10.12 | 8.3.3 | 8.3 | +| 10.12 | 9.0.1 | 9.0.1 | +| 10.13 | 9.0.1 | 9.0.1 | ## Compiler version database @@ -73,6 +74,8 @@ Tools available for your platform: | 8.3.1 | — | — | — | — | 8.1 (802.0.41) | — | | 8.3.2 | — | — | — | — | 8.1 (802.0.42) | — | | 8.3.3 | — | — | — | — | 8.1 (802.0.42) | — | +| 9.0.0 | — | — | — | — | 9.0 (900.0.37) | — | +| 9.0.1 | — | — | — | — | 9.0 (900.0.38) | — | ## References to Xcode and compiler versions in code When a new Xcode release is made, the following things need to be diff --git a/manpages/brew.1 b/manpages/brew.1 index b3d840275..69ee416d7 100644 --- a/manpages/brew.1 +++ b/manpages/brew.1 @@ -797,7 +797,7 @@ Generate Homebrew\'s manpages\. If \fB\-\-fail\-if\-changed\fR is passed, the command will return a failing status code if changes are detected in the manpage outputs\. This can be used for CI to be notified when the manpages are out of date\. Additionally, the date used in new manpages will match those in the existing manpages (to allow comparison without factoring in the date)\. . .TP -\fBpull\fR [\fB\-\-bottle\fR] [\fB\-\-bump\fR] [\fB\-\-clean\fR] [\fB\-\-ignore\-whitespace\fR] [\fB\-\-resolve\fR] [\fB\-\-branch\-okay\fR] [\fB\-\-no\-pbcopy\fR] [\fB\-\-no\-publish\fR] [\fB\-\-warn\-on\-publish\-failure\fR] \fIpatch\-source\fR [\fIpatch\-source\fR]: +\fBpull\fR [\fB\-\-bottle\fR] [\fB\-\-bump\fR] [\fB\-\-clean\fR] [\fB\-\-ignore\-whitespace\fR] [\fB\-\-resolve\fR] [\fB\-\-branch\-okay\fR] [\fB\-\-no\-pbcopy\fR] [\fB\-\-no\-publish\fR] [\fB\-\-warn\-on\-publish\-failure\fR] [\fB\-\-bintray\-org=\fR\fIbintray\-org\fR] [\fB\-\-test\-bot\-user=\fR\fItest\-bot\-user\fR] \fIpatch\-source\fR [\fIpatch\-source\fR]: . .IP Gets a patch from a GitHub commit or pull request and applies it to Homebrew\. Optionally, installs the formulae changed by the patch\. @@ -844,6 +844,12 @@ If \fB\-\-no\-publish\fR is passed, do not publish bottles to Bintray\. .IP If \fB\-\-warn\-on\-publish\-failure\fR was passed, do not exit if there\'s a failure publishing bottles on Bintray\. . +.IP +If \fB\-\-bintray\-org=\fR\fIbintray\-org\fR is passed, publish at the given Bintray organisation\. +. +.IP +If \fB\-\-test\-bot\-user=\fR\fItest\-bot\-user\fR is passed, pull the bottle block commit from the specified user on GitHub\. +. .TP \fBrelease\-notes\fR [\fB\-\-markdown\fR] [\fIprevious_tag\fR] [\fIend_ref\fR] Output the merged pull requests on Homebrew/brew between two Git refs\. If no \fIprevious_tag\fR is provided it defaults to the newest tag\. If no \fIend_ref\fR is provided it defaults to \fBorigin/master\fR\. |
