diff --git a/.github/ISSUE_TEMPLATE/feature.md b/.github/ISSUE_TEMPLATE/feature.md index 9033c7b4d7..8651038872 100644 --- a/.github/ISSUE_TEMPLATE/feature.md +++ b/.github/ISSUE_TEMPLATE/feature.md @@ -4,6 +4,8 @@ about: Request our thoughts on your suggestion for a new feature for Homebrew. --- +# Please note we will close your issue without comment if you delete, do not read or do not fill out the issue checklist below and provide ALL the requested information. If you repeatedly fail to use the issue template, we will block you from ever submitting issues to Homebrew again. + # A detailed description of the proposed feature diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index b11413c5db..c804e66553 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - version: ["18.04", "20.04"] + version: ["16.04", "18.04", "20.04"] steps: - name: Checkout uses: actions/checkout@master @@ -33,9 +33,24 @@ jobs: docker login docker.pkg.github.com -u BrewTestBot -p ${{secrets.GITHUB_TOKEN}} docker tag brew "docker.pkg.github.com/homebrew/brew/ubuntu${{matrix.version}}:$brew_version" docker push "docker.pkg.github.com/homebrew/brew/ubuntu${{matrix.version}}:$brew_version" + docker tag brew "docker.pkg.github.com/homebrew/brew/ubuntu${{matrix.version}}:latest" + docker push "docker.pkg.github.com/homebrew/brew/ubuntu${{matrix.version}}:latest" - name: Deploy the tagged Docker image to Docker Hub if: startsWith(github.ref, 'refs/tags/') run: | docker login -u brewtestbot -p ${{secrets.DOCKER_TOKEN}} docker tag brew "homebrew/ubuntu${{matrix.version}}:$brew_version" docker push "homebrew/ubuntu${{matrix.version}}:$brew_version" + docker tag brew "homebrew/ubuntu${{matrix.version}}:latest" + docker push "homebrew/ubuntu${{matrix.version}}:latest" + - name: Deploy the homebrew/brew Docker image to GitHub and Docker Hub + if: startsWith(github.ref, 'refs/tags/') && matrix.version == '20.04' + run: | + docker tag brew "docker.pkg.github.com/homebrew/brew/brew:$brew_version" + docker push "docker.pkg.github.com/homebrew/brew/brew:$brew_version" + docker tag brew "docker.pkg.github.com/homebrew/brew/brew:latest" + docker push "docker.pkg.github.com/homebrew/brew/brew:latest" + docker tag brew "homebrew/brew:$brew_version" + docker push "homebrew/brew:$brew_version" + docker tag brew "homebrew/brew:latest" + docker push "homebrew/brew:latest" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2737da80e7..8b273bede7 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -3,9 +3,6 @@ on: push: branches: master pull_request: [] - release: - types: - - published env: HOMEBREW_GITHUB_ACTIONS: 1 HOMEBREW_NO_AUTO_UPDATE: 1 @@ -71,6 +68,9 @@ jobs: else # Link old gettext (otherwise `brew doctor` is sad) brew link gettext + + # remove deleted formula + brew uninstall --force python@2 fi brew doctor @@ -173,7 +173,7 @@ jobs: - name: Build Docker image if: matrix.os == 'ubuntu-latest' - run: docker build -t brew . + run: docker build -t brew --build-arg=version=16.04 . - name: Run brew test-bot run: | @@ -184,16 +184,11 @@ jobs: fi - name: Deploy the Docker image to GitHub and Docker Hub - if: matrix.os == 'ubuntu-latest' && (github.ref == 'refs/heads/master' || github.event_name == 'release') + if: matrix.os == 'ubuntu-latest' && github.ref == 'refs/heads/master' run: | - case $GITHUB_REF in - refs/heads/master) v=latest ;; - refs/tags/*) v=${GITHUB_REF:10} ;; - *) echo Error: unexpected GITHUB_REF: $GITHUB_REF; exit 1 ;; - esac docker login docker.pkg.github.com -u BrewTestBot -p ${{secrets.GITHUB_TOKEN}} - docker tag brew "docker.pkg.github.com/homebrew/brew/brew:$v" - docker push "docker.pkg.github.com/homebrew/brew/brew:$v" + docker tag brew "docker.pkg.github.com/homebrew/brew/ubuntu16.04:master" + docker push "docker.pkg.github.com/homebrew/brew/ubuntu16.04:master" docker login -u brewtestbot -p ${{secrets.DOCKER_TOKEN}} - docker tag brew "homebrew/brew:$v" - docker push "homebrew/brew:$v" + docker tag brew "homebrew/ubuntu16.04:master" + docker push "homebrew/ubuntu16.04:master" diff --git a/.gitignore b/.gitignore index 0c3bf37367..45de01f3f3 100644 --- a/.gitignore +++ b/.gitignore @@ -110,6 +110,7 @@ **/vendor/bundle/ruby/*/gems/pry-*/ **/vendor/bundle/ruby/*/gems/rainbow-*/ **/vendor/bundle/ruby/*/gems/rdiscount-*/ +**/vendor/bundle/ruby/*/gems/regexp_parser-*/ **/vendor/bundle/ruby/*/gems/ronn-*/ **/vendor/bundle/ruby/*/gems/rspec-*/ **/vendor/bundle/ruby/*/gems/rspec-core-*/ @@ -120,6 +121,7 @@ **/vendor/bundle/ruby/*/gems/rspec-support-*/ **/vendor/bundle/ruby/*/gems/rspec-wait-*/ **/vendor/bundle/ruby/*/gems/rubocop-0*/ +**/vendor/bundle/ruby/*/gems/rubocop-ast-*/ **/vendor/bundle/ruby/*/gems/ruby-prof-*/ **/vendor/bundle/ruby/*/gems/ruby-progressbar-*/ **/vendor/bundle/ruby/*/gems/simplecov-*/ diff --git a/Dockerfile b/Dockerfile index 94012220e9..6e34b61c22 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -ARG version=16.04 +ARG version=20.04 FROM ubuntu:$version ARG DEBIAN_FRONTEND=noninteractive @@ -42,6 +42,8 @@ RUN cd /home/linuxbrew/.linuxbrew \ && HOMEBREW_NO_ANALYTICS=1 HOMEBREW_NO_AUTO_UPDATE=1 brew tap homebrew/core \ && brew install-bundler-gems \ && brew cleanup \ + && { git -C /home/linuxbrew/.linuxbrew/Homebrew config --unset gc.auto; true; } \ + && { git -C /home/linuxbrew/.linuxbrew/Homebrew config --unset homebrew.devcmdrun; true; } \ && rm -rf ~/.cache \ && chown -R linuxbrew: /home/linuxbrew/.linuxbrew \ && chmod -R g+w,o-w /home/linuxbrew/.linuxbrew diff --git a/Library/.rubocop_shared.yml b/Library/.rubocop_shared.yml index b2d8eca8df..1f35180e12 100644 --- a/Library/.rubocop_shared.yml +++ b/Library/.rubocop_shared.yml @@ -8,7 +8,7 @@ AllCops: # Use `<<~` for heredocs. Layout/HeredocIndentation: - EnforcedStyle: squiggly + Enabled: true # Not useful in casks and formulae. Metrics/BlockLength: diff --git a/Library/Homebrew/Gemfile.lock b/Library/Homebrew/Gemfile.lock index 58fff27589..9ddd014ae9 100644 --- a/Library/Homebrew/Gemfile.lock +++ b/Library/Homebrew/Gemfile.lock @@ -10,7 +10,7 @@ GEM ast (2.4.0) byebug (11.1.3) concurrent-ruby (1.1.6) - connection_pool (2.2.2) + connection_pool (2.2.3) coveralls (0.8.23) json (>= 1.8, < 3) simplecov (~> 0.16.1) @@ -24,7 +24,7 @@ GEM hpricot (0.8.6) http-cookie (1.0.3) domain_name (~> 0.5) - i18n (1.8.2) + i18n (1.8.3) concurrent-ruby (~> 1.0) json (2.3.0) mechanize (2.7.6) @@ -51,11 +51,12 @@ GEM parallel (1.19.1) parallel_tests (2.32.0) parallel - parser (2.7.1.2) + parser (2.7.1.3) ast (~> 2.4.0) plist (3.5.0) rainbow (3.0.0) rdiscount (2.2.0.1) + regexp_parser (1.7.0) rexml (3.2.4) ronn (0.7.3) hpricot (>= 0.8.2) @@ -81,14 +82,18 @@ GEM rspec-support (3.9.3) rspec-wait (0.0.9) rspec (>= 3, < 4) - rubocop (0.83.0) + rubocop (0.85.0) parallel (~> 1.10) parser (>= 2.7.0.1) rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.7) rexml + rubocop-ast (>= 0.0.3) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 2.0) - rubocop-performance (1.5.2) + rubocop-ast (0.0.3) + parser (>= 2.7.0.1) + rubocop-performance (1.6.1) rubocop (>= 0.71.0) rubocop-rspec (1.39.0) rubocop (>= 0.68.1) diff --git a/Library/Homebrew/brew.rb b/Library/Homebrew/brew.rb index b141390a0f..17a008a778 100644 --- a/Library/Homebrew/brew.rb +++ b/Library/Homebrew/brew.rb @@ -50,7 +50,7 @@ begin help_flag = !ENV["HOMEBREW_HELP"].nil? cmd = nil - ARGV.dup.each_with_index do |arg, i| + ARGV.each_with_index do |arg, i| break if help_flag && cmd if arg == "help" && !cmd @@ -139,8 +139,8 @@ rescue UsageError => e require "help" Homebrew::Help.help cmd, usage_error: e.message rescue SystemExit => e - onoe "Kernel.exit" if ARGV.debug? && !e.success? - $stderr.puts e.backtrace if ARGV.debug? + onoe "Kernel.exit" if Homebrew.args.debug? && !e.success? + $stderr.puts e.backtrace if Homebrew.args.debug? raise rescue Interrupt $stderr.puts # seemingly a newline is typical @@ -156,7 +156,7 @@ rescue RuntimeError, SystemCallError => e raise if e.message.empty? onoe e - $stderr.puts e.backtrace if ARGV.debug? + $stderr.puts e.backtrace if Homebrew.args.debug? output_unsupported_error if Homebrew.args.HEAD? @@ -167,7 +167,7 @@ rescue MethodDeprecatedError => e $stderr.puts "If reporting this issue please do so at (not Homebrew/brew or Homebrew/core):" $stderr.puts " #{Formatter.url(e.issues_url)}" end - $stderr.puts e.backtrace if ARGV.debug? + $stderr.puts e.backtrace if Homebrew.args.debug? exit 1 rescue Exception => e # rubocop:disable Lint/RescueException onoe e diff --git a/Library/Homebrew/build.rb b/Library/Homebrew/build.rb index c63f45f97e..bd1a68614c 100644 --- a/Library/Homebrew/build.rb +++ b/Library/Homebrew/build.rb @@ -52,6 +52,8 @@ class Build Requirement.prune elsif req.prune_if_build_and_not_dependent?(dependent, formula) Requirement.prune + elsif req.test? + Requirement.prune end end end @@ -65,6 +67,8 @@ class Build Dependency.prune elsif dep.build? Dependency.keep_but_prune_recursive_deps + elsif dep.test? + Dependency.prune end end end @@ -112,7 +116,7 @@ class Build } with_env(new_env) do - formula.extend(Debrew::Formula) if ARGV.debug? + formula.extend(Debrew::Formula) if Homebrew.args.debug? formula.update_head_version diff --git a/Library/Homebrew/cask/artifact/abstract_uninstall.rb b/Library/Homebrew/cask/artifact/abstract_uninstall.rb index 32d958f069..1a2c10d2f2 100644 --- a/Library/Homebrew/cask/artifact/abstract_uninstall.rb +++ b/Library/Homebrew/cask/artifact/abstract_uninstall.rb @@ -89,7 +89,7 @@ module Cask args: ["list", service], sudo: with_sudo, print_stderr: false ).stdout - if plist_status.match?(/^\{/) + if plist_status.start_with?("{") command.run!("/bin/launchctl", args: ["remove", service], sudo: with_sudo) sleep 1 end @@ -326,7 +326,14 @@ module Cask next end - yield path, Pathname.glob(resolved_path) + begin + yield path, Pathname.glob(resolved_path) + rescue Errno::EPERM + raise if File.readable?(File.expand_path("~/Library/Application Support/com.apple.TCC")) + + odie "Unable to remove some files. Please enable Full Disk Access for your terminal under " \ + "System Preferences → Security & Privacy → Privacy → Full Disk Access." + end end end diff --git a/Library/Homebrew/cask/audit.rb b/Library/Homebrew/cask/audit.rb index 6aea3a6d38..2b3429f5dd 100644 --- a/Library/Homebrew/cask/audit.rb +++ b/Library/Homebrew/cask/audit.rb @@ -6,6 +6,7 @@ require "cask/download" require "digest" require "utils/curl" require "utils/git" +require "utils/notability" module Cask class Audit @@ -14,22 +15,22 @@ module Cask attr_reader :cask, :commit_range, :download - attr_predicate :check_appcast? + attr_predicate :appcast? - def initialize(cask, check_appcast: false, download: false, check_token_conflicts: false, - commit_range: nil, command: SystemCommand) + def initialize(cask, appcast: false, download: false, + token_conflicts: false, online: false, strict: false, + new_cask: false, commit_range: nil, command: SystemCommand) @cask = cask - @check_appcast = check_appcast + @appcast = appcast @download = download + @online = online + @strict = strict + @new_cask = new_cask @commit_range = commit_range - @check_token_conflicts = check_token_conflicts + @token_conflicts = token_conflicts @command = command end - def check_token_conflicts? - @check_token_conflicts - end - def run! check_blacklist check_required_stanzas @@ -48,6 +49,9 @@ module Cask check_latest_with_auto_updates check_stanza_requires_uninstall check_appcast_contains_version + check_github_repository + check_gitlab_repository + check_bitbucket_repository self rescue => e odebug "#{e.message}\n#{e.backtrace.join("\n")}" @@ -255,7 +259,7 @@ module Cask bad_url_format?(/sourceforge/, [ %r{\Ahttps://sourceforge\.net/projects/[^/]+/files/latest/download\Z}, - %r{\Ahttps://downloads\.sourceforge\.net/(?!(project|sourceforge)\/)}, + %r{\Ahttps://downloads\.sourceforge\.net/(?!(project|sourceforge)/)}, ]) end @@ -272,7 +276,7 @@ module Cask end def check_token_conflicts - return unless check_token_conflicts? + return unless @token_conflicts return unless core_formula_names.include?(cask.token) add_warning "possible duplicate, cask token conflicts with Homebrew core formula: #{core_formula_url}" @@ -301,7 +305,7 @@ module Cask end def check_appcast_contains_version - return unless check_appcast? + return unless appcast? return if cask.appcast.to_s.empty? return if cask.appcast.must_contain == :no_check @@ -309,8 +313,8 @@ module Cask appcast_contents, = curl_output("--compressed", "--user-agent", HOMEBREW_USER_AGENT_FAKE_SAFARI, "--location", "--globoff", "--max-time", "5", appcast_stanza) version_stanza = cask.version.to_s - adjusted_version_stanza = if cask.appcast.must_contain.blank? - version_stanza.split(",")[0].split("-")[0].split("_")[0] + adjusted_version_stanza = if cask.appcast.configuration.blank? + version_stanza.match(/^[[:alnum:].]+/)[0] else cask.appcast.must_contain end @@ -322,6 +326,50 @@ module Cask add_error "appcast at URL '#{appcast_stanza}' offline or looping" end + def check_github_repository + user, repo = get_repo_data(%r{https?://github\.com/([^/]+)/([^/]+)/?.*}) + return if user.nil? + + odebug "Auditing GitHub repo" + + error = SharedAudits.github(user, repo) + add_error error if error + end + + def check_gitlab_repository + user, repo = get_repo_data(%r{https?://gitlab\.com/([^/]+)/([^/]+)/?.*}) + return if user.nil? + + odebug "Auditing GitLab repo" + + error = SharedAudits.gitlab(user, repo) + add_error error if error + end + + def check_bitbucket_repository + user, repo = get_repo_data(%r{https?://bitbucket\.org/([^/]+)/([^/]+)/?.*}) + return if user.nil? + + odebug "Auditing Bitbucket repo" + + error = SharedAudits.bitbucket(user, repo) + add_error error if error + end + + def get_repo_data(regex) + return unless @online + return unless @new_cask + + _, user, repo = *regex.match(cask.url.to_s) + _, user, repo = *regex.match(cask.homepage) unless user + _, user, repo = *regex.match(cask.appcast.to_s) unless user + return if !user || !repo + + repo.gsub!(/.git$/, "") + + [user, repo] + end + def check_blacklist return if cask.tap&.user != "Homebrew" return unless reason = Blacklist.blacklisted_reason(cask.token) diff --git a/Library/Homebrew/cask/auditor.rb b/Library/Homebrew/cask/auditor.rb index 844fa8d9ee..4f209120dc 100644 --- a/Library/Homebrew/cask/auditor.rb +++ b/Library/Homebrew/cask/auditor.rb @@ -8,37 +8,40 @@ module Cask extend Predicable def self.audit(cask, audit_download: false, audit_appcast: false, - check_token_conflicts: false, quarantine: true, commit_range: nil) + audit_online: false, audit_strict: false, + audit_token_conflicts: false, audit_new_cask: false, + quarantine: true, commit_range: nil) new(cask, audit_download: audit_download, audit_appcast: audit_appcast, - check_token_conflicts: check_token_conflicts, + audit_online: audit_online, + audit_new_cask: audit_new_cask, + audit_strict: audit_strict, + audit_token_conflicts: audit_token_conflicts, quarantine: quarantine, commit_range: commit_range).audit end attr_reader :cask, :commit_range def initialize(cask, audit_download: false, audit_appcast: false, - check_token_conflicts: false, quarantine: true, commit_range: nil) + audit_online: false, audit_strict: false, + audit_token_conflicts: false, audit_new_cask: false, + quarantine: true, commit_range: nil) @cask = cask @audit_download = audit_download @audit_appcast = audit_appcast + @audit_online = audit_online + @audit_strict = audit_strict + @audit_new_cask = audit_new_cask @quarantine = quarantine @commit_range = commit_range - @check_token_conflicts = check_token_conflicts + @audit_token_conflicts = audit_token_conflicts end - def audit_download? - @audit_download - end - - attr_predicate :audit_appcast?, :quarantine? - - def check_token_conflicts? - @check_token_conflicts - end + attr_predicate :audit_appcast?, :audit_download?, :audit_online?, + :audit_strict?, :audit_new_cask?, :audit_token_conflicts?, :quarantine? def audit - if !ARGV.value("language") && language_blocks + if !Homebrew.args.value("language") && language_blocks audit_all_languages else audit_cask_instance(cask) @@ -64,10 +67,13 @@ module Cask def audit_cask_instance(cask) download = audit_download? && Download.new(cask, quarantine: quarantine?) - audit = Audit.new(cask, check_appcast: audit_appcast?, - download: download, - check_token_conflicts: check_token_conflicts?, - commit_range: commit_range) + audit = Audit.new(cask, appcast: audit_appcast?, + online: audit_online?, + strict: audit_strict?, + new_cask: audit_new_cask?, + token_conflicts: audit_token_conflicts?, + download: download, + commit_range: commit_range) audit.run! puts audit.summary audit.success? diff --git a/Library/Homebrew/cask/blacklist.rb b/Library/Homebrew/cask/blacklist.rb index c37ac82fef..810067a39e 100644 --- a/Library/Homebrew/cask/blacklist.rb +++ b/Library/Homebrew/cask/blacklist.rb @@ -4,7 +4,7 @@ module Cask module Blacklist def self.blacklisted_reason(name) case name - when /^adobe\-(after|illustrator|indesign|photoshop|premiere)/ + when /^adobe-(after|illustrator|indesign|photoshop|premiere)/ "Adobe casks were removed because they are too difficult to maintain." when /^audacity$/ "Audacity was removed because it is too difficult to download programmatically." diff --git a/Library/Homebrew/cask/cmd.rb b/Library/Homebrew/cask/cmd.rb index af03b04385..139e063887 100644 --- a/Library/Homebrew/cask/cmd.rb +++ b/Library/Homebrew/cask/cmd.rb @@ -145,13 +145,13 @@ module Cask command, args = detect_internal_command(*args) || detect_external_command(*args) || [NullCommand.new, args] if help? - puts command.help + Help.new(command.command_name).run else command.run(*args) end rescue CaskError, MethodDeprecatedError, ArgumentError, OptionParser::InvalidOption => e onoe e.message - $stderr.puts e.backtrace if ARGV.debug? + $stderr.puts e.backtrace if Homebrew.args.debug? exit 1 rescue StandardError, ScriptError, NoMemoryError => e onoe e.message @@ -180,7 +180,7 @@ module Cask end def process_options(*args) - exclude_regex = /^\-\-#{Regexp.union(*Config::DEFAULT_DIRS.keys.map(&Regexp.public_method(:escape)))}=/ + exclude_regex = /^--#{Regexp.union(*Config::DEFAULT_DIRS.keys.map(&Regexp.public_method(:escape)))}=/ non_options = [] diff --git a/Library/Homebrew/cask/cmd/audit.rb b/Library/Homebrew/cask/cmd/audit.rb index f046b91df4..c2b94dba98 100644 --- a/Library/Homebrew/cask/cmd/audit.rb +++ b/Library/Homebrew/cask/cmd/audit.rb @@ -1,32 +1,66 @@ # frozen_string_literal: true +require "cli/parser" + module Cask class Cmd class Audit < AbstractCommand - option "--download", :download, false - option "--appcast", :appcast, false - option "--token-conflicts", :token_conflicts, false + option "--download", :download_arg, false + option "--appcast", :appcast_arg, false + option "--token-conflicts", :token_conflicts_arg, false + option "--strict", :strict_arg, false + option "--online", :online_arg, false + option "--new-cask", :new_cask_arg, false + + def self.usage + <<~EOS + `cask audit` [] [] + + --strict - Run additional, stricter style checks. + --online - Run additional, slower style checks that require a network connection. + --new-cask - Run various additional style checks to determine if a new cask is eligible + for Homebrew. This should be used when creating new casks and implies + `--strict` and `--online`. + --download - Audit the downloaded file + --appcast - Audit the appcast + --token-conflicts - Audit for token conflicts + + Check for Homebrew coding style violations. This should be run before + submitting a new cask. If no are provided, check all locally + available casks. Will exit with a non-zero status if any errors are + found, which can be useful for implementing pre-commit hooks. + EOS + end def self.help "verifies installability of Casks" end def run + Homebrew.auditing = true + strict = new_cask_arg? || strict_arg? + token_conflicts = strict || token_conflicts_arg? + + online = new_cask_arg? || online_arg? + download = online || download_arg? + appcast = online || appcast_arg? + failed_casks = casks(alternative: -> { Cask.to_a }) - .reject { |cask| audit(cask) } + .reject do |cask| + odebug "Auditing Cask #{cask}" + Auditor.audit(cask, audit_download: download, + audit_appcast: appcast, + audit_online: online, + audit_strict: strict, + audit_new_cask: new_cask_arg?, + audit_token_conflicts: token_conflicts, + quarantine: quarantine?) + end return if failed_casks.empty? raise CaskError, "audit failed for casks: #{failed_casks.join(" ")}" end - - def audit(cask) - odebug "Auditing Cask #{cask}" - Auditor.audit(cask, audit_download: download?, - audit_appcast: appcast?, - check_token_conflicts: token_conflicts?, - quarantine: quarantine?) - end end end end diff --git a/Library/Homebrew/cask/cmd/help.rb b/Library/Homebrew/cask/cmd/help.rb index 51b6ce7876..28db5331b7 100644 --- a/Library/Homebrew/cask/cmd/help.rb +++ b/Library/Homebrew/cask/cmd/help.rb @@ -3,17 +3,26 @@ module Cask class Cmd class Help < AbstractCommand - def initialize(*) - super - return if args.empty? - - raise ArgumentError, "#{self.class.command_name} does not take arguments." - end - def run - puts self.class.purpose - puts - puts self.class.usage + if args.empty? + puts self.class.purpose + puts + puts self.class.usage + elsif args.count == 1 + command_name = args.first + + unless command = self.class.commands[command_name] + raise "No help information found for command '#{command_name}'." + end + + if command.respond_to?(:usage) + puts command.usage + else + puts command.help + end + else + raise ArgumentError, "#{self.class.command_name} only takes up to one argument." + end end def self.purpose @@ -23,6 +32,10 @@ module Cask EOS end + def self.commands + Cmd.command_classes.select(&:visible?).map { |klass| [klass.command_name, klass] }.to_h + end + def self.usage max_command_len = Cmd.commands.map(&:length).max diff --git a/Library/Homebrew/cask/cmd/info.rb b/Library/Homebrew/cask/cmd/info.rb index a09291bce0..e4acbbe56d 100644 --- a/Library/Homebrew/cask/cmd/info.rb +++ b/Library/Homebrew/cask/cmd/info.rb @@ -46,6 +46,7 @@ module Cask def self.info(cask) puts get_info(cask) + ::Utils::Analytics.cask_output(cask) end def self.title_info(cask) diff --git a/Library/Homebrew/cask/cmd/options.rb b/Library/Homebrew/cask/cmd/options.rb index 9dca4e3d7f..c6bb427892 100644 --- a/Library/Homebrew/cask/cmd/options.rb +++ b/Library/Homebrew/cask/cmd/options.rb @@ -46,7 +46,7 @@ module Cask next if self.class.options.nil? self.class.options.each do |option_name, option_method| - option_type = case option_name.split(/(\ |\=)/).last + option_type = case option_name.split(/(\ |=)/).last when "PATH" Pathname when /\w+(,\w+)+/ diff --git a/Library/Homebrew/cask/config.rb b/Library/Homebrew/cask/config.rb index a415b74d78..bd9bd71155 100644 --- a/Library/Homebrew/cask/config.rb +++ b/Library/Homebrew/cask/config.rb @@ -86,7 +86,7 @@ module Cask Shellwords.shellsplit(ENV.fetch("HOMEBREW_CASK_OPTS", "")) .select { |arg| arg.include?("=") } .map { |arg| arg.split("=", 2) } - .map { |(flag, value)| [flag.sub(/^\-\-/, ""), value] }, + .map { |(flag, value)| [flag.sub(/^--/, ""), value] }, ) end diff --git a/Library/Homebrew/cask/dsl/caveats.rb b/Library/Homebrew/cask/dsl/caveats.rb index 035c1d6a3b..b6105915e4 100644 --- a/Library/Homebrew/cask/dsl/caveats.rb +++ b/Library/Homebrew/cask/dsl/caveats.rb @@ -58,6 +58,19 @@ module Cask EOS end + caveat :unsigned_accessibility do |access = "Accessibility"| + # access: the category in System Preferences -> Security & Privacy -> Privacy the app requires. + + <<~EOS + #{@cask} is not signed and requires Accessibility access, + so you will need to re-grant Accessibility access every time the app is updated. + + Enable or re-enable it in: + System Preferences → Security & Privacy → Privacy -> #{access} + To re-enable untick and retick #{@cask}.app. + EOS + end + caveat :path_environment_variable do |path| <<~EOS To use #{@cask}, you may need to add the #{path} directory diff --git a/Library/Homebrew/cask/dsl/version.rb b/Library/Homebrew/cask/dsl/version.rb index 477360047e..fd8328ad06 100644 --- a/Library/Homebrew/cask/dsl/version.rb +++ b/Library/Homebrew/cask/dsl/version.rb @@ -11,9 +11,9 @@ module Cask DIVIDER_REGEX = /(#{DIVIDERS.keys.map { |v| Regexp.quote(v) }.join('|')})/.freeze - MAJOR_MINOR_PATCH_REGEX = /^([^.,:]+)(?:\.([^.,:]+)(?:\.([^.,:]+))?)?/.freeze + MAJOR_MINOR_PATCH_REGEX = /^([^.,:]+)(?:.([^.,:]+)(?:.([^.,:]+))?)?/.freeze - INVALID_CHARACTERS = /[^0-9a-zA-Z\.\,\:\-\_]/.freeze + INVALID_CHARACTERS = /[^0-9a-zA-Z.,:\-_]/.freeze class << self private @@ -75,7 +75,7 @@ module Cask s = downcase.delete(".").gsub(/[^a-z\d]+/, "-") return true if s.match?(/(\d+|\b)(alpha|beta|preview|rc|dev|canary|snapshot)(\d+|\b)/i) - return true if s.match?(/\A[a-z\d]+(\-\d+)*\-?(a|b|pre)(\d+|\b)/i) + return true if s.match?(/\A[a-z\d]+(-\d+)*-?(a|b|pre)(\d+|\b)/i) false end diff --git a/Library/Homebrew/cask/installer.rb b/Library/Homebrew/cask/installer.rb index 503962e308..369b05f1d0 100644 --- a/Library/Homebrew/cask/installer.rb +++ b/Library/Homebrew/cask/installer.rb @@ -368,8 +368,8 @@ module Cask fi.installed_on_request = false fi.show_header = true fi.verbose = verbose? - fi.fetch fi.prelude + fi.fetch fi.install fi.finish end diff --git a/Library/Homebrew/cleaner.rb b/Library/Homebrew/cleaner.rb index c469f8f277..cf962341f7 100644 --- a/Library/Homebrew/cleaner.rb +++ b/Library/Homebrew/cleaner.rb @@ -109,7 +109,7 @@ class Cleaner else 0444 end - if ARGV.debug? + if Homebrew.args.debug? old_perms = path.stat.mode & 0777 odebug "Fixing #{path} permissions from #{old_perms.to_s(8)} to #{perms.to_s(8)}" if perms != old_perms end diff --git a/Library/Homebrew/cleanup.rb b/Library/Homebrew/cleanup.rb index 480a9c9ca1..c2b53660fc 100644 --- a/Library/Homebrew/cleanup.rb +++ b/Library/Homebrew/cleanup.rb @@ -56,14 +56,14 @@ module CleanupRefinement end end - version ||= basename.to_s[/\A.*(?:\-\-.*?)*\-\-(.*?)#{Regexp.escape(extname)}\Z/, 1] - version ||= basename.to_s[/\A.*\-\-?(.*?)#{Regexp.escape(extname)}\Z/, 1] + version ||= basename.to_s[/\A.*(?:--.*?)*--(.*?)#{Regexp.escape(extname)}\Z/, 1] + version ||= basename.to_s[/\A.*--?(.*?)#{Regexp.escape(extname)}\Z/, 1] return false unless version version = Version.new(version) - return false unless formula_name = basename.to_s[/\A(.*?)(?:\-\-.*?)*\-\-?(?:#{Regexp.escape(version)})/, 1] + return false unless formula_name = basename.to_s[/\A(.*?)(?:--.*?)*--?(?:#{Regexp.escape(version)})/, 1] formula = begin Formulary.from_rack(HOMEBREW_CELLAR/formula_name) @@ -71,7 +71,7 @@ module CleanupRefinement return false end - resource_name = basename.to_s[/\A.*?\-\-(.*?)\-\-?(?:#{Regexp.escape(version)})/, 1] + resource_name = basename.to_s[/\A.*?--(.*?)--?(?:#{Regexp.escape(version)})/, 1] if resource_name == "patch" patch_hashes = formula.stable&.patches&.select(&:external?)&.map(&:resource)&.map(&:version) @@ -84,7 +84,7 @@ module CleanupRefinement return true end - return true if scrub && !formula.installed? + return true if scrub && !formula.latest_version_installed? return true if Utils::Bottles.file_outdated?(formula, self) @@ -92,7 +92,7 @@ module CleanupRefinement end def stale_cask?(scrub) - return false unless name = basename.to_s[/\A(.*?)\-\-/, 1] + return false unless name = basename.to_s[/\A(.*?)--/, 1] cask = begin Cask::CaskLoader.load(name) @@ -100,7 +100,7 @@ module CleanupRefinement return false end - return true unless basename.to_s.match?(/\A#{Regexp.escape(name)}\-\-#{Regexp.escape(cask.version)}\b/) + return true unless basename.to_s.match?(/\A#{Regexp.escape(name)}--#{Regexp.escape(cask.version)}\b/) return true if scrub && !cask.versions.include?(cask.version) diff --git a/Library/Homebrew/cli/args.rb b/Library/Homebrew/cli/args.rb index 202b5557db..ac5fd1875b 100644 --- a/Library/Homebrew/cli/args.rb +++ b/Library/Homebrew/cli/args.rb @@ -10,7 +10,7 @@ module Homebrew # undefine tap to allow --tap argument undef tap - def initialize(argv = ARGV.dup.freeze, set_default_args: false) + def initialize(argv = ARGV.freeze, set_default_args: false) super() @processed_options = [] @@ -84,11 +84,7 @@ module Homebrew require "formula" @formulae ||= (downcased_unique_named - casks).map do |name| - if name.include?("/") || File.exist?(name) - Formulary.factory(name, spec) - else - Formulary.find_with_priority(name, spec) - end + Formulary.factory(name, spec) end.uniq(&:name).freeze end @@ -175,6 +171,20 @@ module Homebrew formulae.any? { |args_f| args_f.full_name == f.full_name } end + def include_formula_test_deps?(f) + return false unless include_test? + + formulae.any? { |args_f| args_f.full_name == f.full_name } + end + + def value(name) + arg_prefix = "--#{name}=" + flag_with_value = flags_only.find { |arg| arg.start_with?(arg_prefix) } + return unless flag_with_value + + flag_with_value.delete_prefix(arg_prefix) + end + private def option_to_name(option) diff --git a/Library/Homebrew/cli/parser.rb b/Library/Homebrew/cli/parser.rb index 53efc00584..8109bceee1 100644 --- a/Library/Homebrew/cli/parser.rb +++ b/Library/Homebrew/cli/parser.rb @@ -13,7 +13,7 @@ module Homebrew class Parser attr_reader :processed_options, :hide_from_man_page - def self.parse(argv = ARGV.dup.freeze, allow_no_named_args: false, &block) + def self.parse(argv = ARGV.freeze, allow_no_named_args: false, &block) new(argv, &block).parse(allow_no_named_args: allow_no_named_args) end @@ -38,7 +38,7 @@ module Homebrew } end - def initialize(argv = ARGV.dup.freeze, &block) + def initialize(argv = ARGV.freeze, &block) @parser = OptionParser.new @argv = argv @args = Homebrew::CLI::Args.new(@argv) @@ -359,11 +359,7 @@ module Homebrew named_args.map do |arg| next if arg.match?(HOMEBREW_CASK_TAP_CASK_REGEX) - if arg.include?("/") || arg.end_with?(".tar.gz") || File.exist?(arg) - Formulary.factory(arg, spec) - else - Formulary.find_with_priority(arg.downcase, spec) - end + Formulary.factory(arg, spec) end.compact.uniq(&:name) end end diff --git a/Library/Homebrew/cmd/--env.rb b/Library/Homebrew/cmd/--env.rb index 694b432078..a0c16eaafc 100644 --- a/Library/Homebrew/cmd/--env.rb +++ b/Library/Homebrew/cmd/--env.rb @@ -36,7 +36,6 @@ module Homebrew shell = if args.plain? nil elsif args.shell.nil? - # legacy behavior :bash unless $stdout.tty? elsif args.shell == "auto" Utils::Shell.parent || Utils::Shell.preferred diff --git a/Library/Homebrew/cmd/info.rb b/Library/Homebrew/cmd/info.rb index d914eb4977..e6db9ec358 100644 --- a/Library/Homebrew/cmd/info.rb +++ b/Library/Homebrew/cmd/info.rb @@ -105,11 +105,7 @@ module Homebrew args.named.each_with_index do |f, i| puts unless i.zero? begin - formula = if f.include?("/") || File.exist?(f) - Formulary.factory(f) - else - Formulary.find_with_priority(f) - end + formula = Formulary.factory(f) if args.analytics? Utils::Analytics.formula_output(formula) else diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb index 03f373447d..ef95b00c76 100644 --- a/Library/Homebrew/cmd/install.rb +++ b/Library/Homebrew/cmd/install.rb @@ -325,8 +325,8 @@ module Homebrew fi.build_bottle = args.build_bottle? fi.interactive = args.interactive? fi.git = args.git? - fi.fetch fi.prelude + fi.fetch fi.install fi.finish rescue FormulaInstallationAlreadyAttemptedError diff --git a/Library/Homebrew/cmd/shellenv.sh b/Library/Homebrew/cmd/shellenv.sh index 193924f27c..4355ce52ea 100644 --- a/Library/Homebrew/cmd/shellenv.sh +++ b/Library/Homebrew/cmd/shellenv.sh @@ -20,8 +20,8 @@ homebrew-shellenv() { echo "setenv HOMEBREW_CELLAR $HOMEBREW_CELLAR;" echo "setenv HOMEBREW_REPOSITORY $HOMEBREW_REPOSITORY;" echo "setenv PATH $HOMEBREW_PREFIX/bin:$HOMEBREW_PREFIX/sbin:\$PATH;" - echo "setenv MANPATH $HOMEBREW_PREFIX/share/man:\$MANPATH;" - echo "setenv INFOPATH $HOMEBREW_PREFIX/share/info:\$INFOPATH;" + echo "setenv MANPATH $HOMEBREW_PREFIX/share/man\`[ \${?MANPATH} == 1 ] && echo \":\${MANPATH}\"\`:;" + echo "setenv INFOPATH $HOMEBREW_PREFIX/share/info\`[ \${?INFOPATH} == 1 ] && echo \":\${INFOPATH}\"\`;" ;; *) echo "export HOMEBREW_PREFIX=\"$HOMEBREW_PREFIX\";" diff --git a/Library/Homebrew/cmd/tap-pin.rb b/Library/Homebrew/cmd/tap-pin.rb deleted file mode 100644 index b8e7a87365..0000000000 --- a/Library/Homebrew/cmd/tap-pin.rb +++ /dev/null @@ -1,18 +0,0 @@ -# frozen_string_literal: true - -require "cli/parser" - -module Homebrew - module_function - - def tap_pin_args - Homebrew::CLI::Parser.new do - hide_from_man_page! - end - end - - def tap_pin - odisabled "the brew tap-pin command", - "fully-scoped user/tap/formula naming when installing and in dependency references" - end -end diff --git a/Library/Homebrew/cmd/tap-unpin.rb b/Library/Homebrew/cmd/tap-unpin.rb deleted file mode 100644 index 2ec6e681a9..0000000000 --- a/Library/Homebrew/cmd/tap-unpin.rb +++ /dev/null @@ -1,18 +0,0 @@ -# frozen_string_literal: true - -require "cli/parser" - -module Homebrew - module_function - - def tap_unpin_args - Homebrew::CLI::Parser.new do - hide_from_man_page! - end - end - - def tap_unpin - odisabled "the brew tap-unpin command", - "fully-scoped user/tap/formula naming when installing and in dependency references" - end -end diff --git a/Library/Homebrew/cmd/update.sh b/Library/Homebrew/cmd/update.sh index a7c384a5af..19ece3f2d0 100644 --- a/Library/Homebrew/cmd/update.sh +++ b/Library/Homebrew/cmd/update.sh @@ -599,7 +599,6 @@ EOS -d "$HOMEBREW_LIBRARY/LinkedKegs" || (-n "$HOMEBREW_DEVELOPER" && -z "$HOMEBREW_UPDATE_PREINSTALL") ]] then - unset HOMEBREW_RUBY_PATH brew update-report "$@" return $? elif [[ -z "$HOMEBREW_UPDATE_PREINSTALL" ]] diff --git a/Library/Homebrew/cmd/upgrade.rb b/Library/Homebrew/cmd/upgrade.rb index df2481fb10..11efd5be00 100644 --- a/Library/Homebrew/cmd/upgrade.rb +++ b/Library/Homebrew/cmd/upgrade.rb @@ -191,8 +191,8 @@ module Homebrew end oh1 "Upgrading #{Formatter.identifier(f.full_specified_name)} #{upgrade_version} #{fi.options.to_a.join(" ")}" - fi.fetch fi.prelude + fi.fetch # first we unlink the currently active keg for this formula otherwise it is # possible for the existing build to interfere with the build we are about to @@ -216,7 +216,7 @@ module Homebrew ensure # restore previous installation state if build failed begin - linked_kegs.each(&:link) unless f.installed? + linked_kegs.each(&:link) unless f.latest_version_installed? rescue nil end diff --git a/Library/Homebrew/commands.rb b/Library/Homebrew/commands.rb index fae9376cb4..7a23065416 100644 --- a/Library/Homebrew/commands.rb +++ b/Library/Homebrew/commands.rb @@ -101,7 +101,7 @@ module Commands end def official_external_commands_paths - %w[bundle services].map do |cmd| + %w[bundle services test-bot].map do |cmd| tap = Tap.fetch("Homebrew/#{cmd}") tap.install unless tap.installed? external_ruby_v2_cmd_path(cmd) diff --git a/Library/Homebrew/compat.rb b/Library/Homebrew/compat.rb index a73aa184ef..79806737a5 100644 --- a/Library/Homebrew/compat.rb +++ b/Library/Homebrew/compat.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true -require "compat/cask/dsl/version" -require "compat/language/python" -require "compat/requirements/macos_requirement" +require "compat/extend/nil" +require "compat/extend/string" require "compat/formula" +require "compat/language/python" require "compat/os/mac" if OS.mac? diff --git a/Library/Homebrew/compat/cask/dsl/version.rb b/Library/Homebrew/compat/cask/dsl/version.rb deleted file mode 100644 index d2b4aa94cf..0000000000 --- a/Library/Homebrew/compat/cask/dsl/version.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true - -module Cask - class DSL - class Version < ::String - module Compat - def dots_to_slashes - odisabled "#dots_to_slashes" - end - - def hyphens_to_slashes - odisabled "#hyphens_to_slashes" - end - - def underscores_to_slashes - odisabled "#underscores_to_slashes" - end - end - - prepend Compat - end - end -end diff --git a/Library/Homebrew/compat/extend/nil.rb b/Library/Homebrew/compat/extend/nil.rb new file mode 100644 index 0000000000..0fa1479558 --- /dev/null +++ b/Library/Homebrew/compat/extend/nil.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class NilClass + module Compat + def chuzzle + odeprecated "chuzzle", "chomp.presence" + end + end + + prepend Compat +end diff --git a/Library/Homebrew/compat/extend/string.rb b/Library/Homebrew/compat/extend/string.rb new file mode 100644 index 0000000000..78baab5073 --- /dev/null +++ b/Library/Homebrew/compat/extend/string.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class String + module Compat + # String.chomp, but if result is empty: returns nil instead. + # Allows `chuzzle || foo` short-circuits. + def chuzzle + odeprecated "chuzzle", "chomp.presence" + s = chomp + s unless s.empty? + end + end + + prepend Compat +end diff --git a/Library/Homebrew/compat/formula.rb b/Library/Homebrew/compat/formula.rb index 66a6f8befb..74caf081fb 100644 --- a/Library/Homebrew/compat/formula.rb +++ b/Library/Homebrew/compat/formula.rb @@ -3,10 +3,19 @@ class Formula module Compat def installed? - # odeprecated "Formula#installed?", - # "Formula#latest_version_installed? (or Formula#any_version_installed? )" + odeprecated "Formula#installed?", + "Formula#latest_version_installed? (or Formula#any_version_installed? )" latest_version_installed? end + + def prepare_patches + if respond_to?(:patches) + active_spec.add_legacy_patches(patches) + odeprecated "patches", "patch do" + end + + super + end end prepend Compat diff --git a/Library/Homebrew/compat/language/haskell.rb b/Library/Homebrew/compat/language/haskell.rb index 0f961b1c34..bea5f40de9 100644 --- a/Library/Homebrew/compat/language/haskell.rb +++ b/Library/Homebrew/compat/language/haskell.rb @@ -5,7 +5,7 @@ module Language module Cabal module Compat def cabal_sandbox(options = {}) - # odeprecated "Language::Haskell::Cabal.cabal_sandbox" + odeprecated "Language::Haskell::Cabal.cabal_sandbox" pwd = Pathname.pwd home = options[:home] || pwd @@ -41,14 +41,14 @@ module Language end def cabal_sandbox_add_source(*args) - # odeprecated "Language::Haskell::Cabal.cabal_sandbox_add_source" + odeprecated "Language::Haskell::Cabal.cabal_sandbox_add_source" system "cabal", "v1-sandbox", "add-source", *args end def cabal_install(*args) - # odeprecated "Language::Haskell::Cabal.cabal_install", - # "cabal v2-install directly with std_cabal_v2_args" + odeprecated "Language::Haskell::Cabal.cabal_install", + "cabal v2-install directly with std_cabal_v2_args" # cabal hardcodes 64 as the maximum number of parallel jobs # https://github.com/Homebrew/legacy-homebrew/issues/49509 @@ -64,13 +64,13 @@ module Language end def cabal_configure(flags) - # odeprecated "Language::Haskell::Cabal.cabal_configure" + odeprecated "Language::Haskell::Cabal.cabal_configure" system "cabal", "v1-configure", flags end def cabal_install_tools(*tools) - # odeprecated "Language::Haskell::Cabal.cabal_install_tools" + odeprecated "Language::Haskell::Cabal.cabal_install_tools" # install tools sequentially, as some tools can depend on other tools tools.each { |tool| cabal_install tool } @@ -81,8 +81,8 @@ module Language end def install_cabal_package(*args, **options) - # odeprecated "Language::Haskell::Cabal.install_cabal_package", - # "cabal v2-update directly followed by v2-install with std_cabal_v2_args" + odeprecated "Language::Haskell::Cabal.install_cabal_package", + "cabal v2-update directly followed by v2-install with std_cabal_v2_args" cabal_sandbox do cabal_install_tools(*options[:using]) if options[:using] diff --git a/Library/Homebrew/compat/language/python.rb b/Library/Homebrew/compat/language/python.rb index 54784465ba..1012e98ddd 100644 --- a/Library/Homebrew/compat/language/python.rb +++ b/Library/Homebrew/compat/language/python.rb @@ -5,6 +5,8 @@ module Language class << self module Compat def rewrite_python_shebang(python_path) + odeprecated "Language::Python.rewrite_python_shebang", + "Utils::Shebang.rewrite_shebang and Shebang.python_shebang_rewrite_info(python_path)" Pathname.pwd.find do |f| Utils::Shebang.rewrite_shebang(Shebang.python_shebang_rewrite_info(python_path), f) end diff --git a/Library/Homebrew/compat/os/mac.rb b/Library/Homebrew/compat/os/mac.rb index af3863c86a..b9b6a0bf74 100644 --- a/Library/Homebrew/compat/os/mac.rb +++ b/Library/Homebrew/compat/os/mac.rb @@ -5,7 +5,7 @@ module OS class << self module Compat def preferred_arch - # odeprecated "MacOS.preferred_arch", "Hardware::CPU.arch (or ideally let the compiler handle it)" + odeprecated "MacOS.preferred_arch", "Hardware::CPU.arch (or ideally let the compiler handle it)" if Hardware::CPU.is_64_bit? Hardware::CPU.arch_64_bit else @@ -14,12 +14,12 @@ module OS end def tcc_db - # odeprecated "MacOS.tcc_db" + odeprecated "MacOS.tcc_db" @tcc_db ||= Pathname.new("/Library/Application Support/com.apple.TCC/TCC.db") end def pre_mavericks_accessibility_dotfile - # odeprecated "MacOS.pre_mavericks_accessibility_dotfile" + odeprecated "MacOS.pre_mavericks_accessibility_dotfile" @pre_mavericks_accessibility_dotfile ||= Pathname.new("/private/var/db/.AccessibilityAPIEnabled") end end diff --git a/Library/Homebrew/compat/requirements/macos_requirement.rb b/Library/Homebrew/compat/requirements/macos_requirement.rb deleted file mode 100644 index 3fe3208d94..0000000000 --- a/Library/Homebrew/compat/requirements/macos_requirement.rb +++ /dev/null @@ -1,35 +0,0 @@ -# frozen_string_literal: true - -class MacOSRequirement < Requirement - module Compat - def initialize(tags = [], comparator: ">=") - if tags.first.respond_to?(:map) - versions, *rest = tags - - versions = versions.map do |v| - next v if v.is_a?(Symbol) - - sym = MacOS::Version.new(v).to_sym - - odisabled "depends_on macos: #{v.inspect}", - "depends_on macos: #{sym.inspect}" - sym - end - - tags = [versions, *rest] - elsif !tags.empty? && !tags.first.is_a?(Symbol) - v, *rest = tags - sym = MacOS::Version.new(v).to_sym - - odisabled "depends_on macos: #{v.inspect}", - "depends_on macos: #{sym.inspect}" - - tags = [sym, *rest] - end - - super(tags, comparator: comparator) - end - end - - prepend Compat -end diff --git a/Library/Homebrew/dependencies.rb b/Library/Homebrew/dependencies.rb index 3ef90b2ed1..512a06a09b 100644 --- a/Library/Homebrew/dependencies.rb +++ b/Library/Homebrew/dependencies.rb @@ -100,16 +100,11 @@ module Homebrew klass.prune if ignores.include?("recommended?") || dependent.build.without?(dep) elsif dep.optional? klass.prune if !includes.include?("optional?") && !dependent.build.with?(dep) - elsif dep.test? - if includes.include?("test?") - Dependency.keep_but_prune_recursive_deps if type == :dependencies - elsif dep.build? - klass.prune unless includes.include?("build?") - else - klass.prune - end - elsif dep.build? - klass.prune unless includes.include?("build?") + elsif dep.build? || dep.test? + keep = false + keep ||= dep.test? && includes.include?("test?") && dependent == formula + keep ||= dep.build? && includes.include?("build?") + klass.prune unless keep end # If a tap isn't installed, we can't find the dependencies of one of diff --git a/Library/Homebrew/dependency.rb b/Library/Homebrew/dependency.rb index 21b8c778e7..d97a5a22a1 100644 --- a/Library/Homebrew/dependency.rb +++ b/Library/Homebrew/dependency.rb @@ -89,9 +89,6 @@ class Dependency deps.each do |dep| next if dependent.name == dep.name - # we only care about one level of test dependencies. - next if dep.test? && @expand_stack.length > 1 - case action(dependent, dep, &block) when :prune next diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index 33c157f6ee..da19542935 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -3,6 +3,7 @@ require "formula" require "formula_versions" require "utils/curl" +require "utils/notability" require "extend/ENV" require "formula_cellar_checks" require "cmd/search" @@ -134,19 +135,8 @@ module Homebrew end end - created_pr_comment = false - if new_formula && !new_formula_problem_lines.empty? - begin - created_pr_comment = true if GitHub.create_issue_comment(new_formula_problem_lines.join("\n")) - rescue *GitHub.api_errors => e - opoo "Unable to create issue comment: #{e.message}" - end - end - - unless created_pr_comment - new_formula_problem_count += new_formula_problem_lines.size - puts new_formula_problem_lines.map { |s| " #{s}" } - end + new_formula_problem_count += new_formula_problem_lines.size + puts new_formula_problem_lines.map { |s| " #{s}" } total_problems_count = problem_count + new_formula_problem_count problem_plural = "#{total_problems_count} #{"problem".pluralize(total_problems_count)}" @@ -155,10 +145,7 @@ module Homebrew errors_summary = "#{problem_plural} in #{formula_plural} detected" errors_summary += ", #{corrected_problem_plural} corrected" if corrected_problem_count.positive? - if problem_count.positive? || - (new_formula_problem_count.positive? && !created_pr_comment) - ofail errors_summary - end + ofail errors_summary if problem_count.positive? || new_formula_problem_count.positive? end def format_problem_lines(problems) @@ -458,9 +445,10 @@ module Homebrew autoconf@2.13 bash-completion@2 gnupg@1.4 + libsigc++@2 lua@5.1 numpy@1.16 - libsigc++@2 + python@3.8 ].freeze def audit_versioned_keg_only @@ -524,79 +512,30 @@ module Homebrew user, repo = get_repo_data(%r{https?://github\.com/([^/]+)/([^/]+)/?.*}) return if user.nil? - begin - metadata = GitHub.repository(user, repo) - rescue GitHub::HTTPNotFoundError - return - end + warning = SharedAudits.github(user, repo) + return if warning.nil? - return if metadata.nil? - - new_formula_problem "GitHub fork (not canonical repository)" if metadata["fork"] - if (metadata["forks_count"] < 30) && (metadata["subscribers_count"] < 30) && - (metadata["stargazers_count"] < 75) - new_formula_problem "GitHub repository not notable enough (<30 forks, <30 watchers and <75 stars)" - end - - return if Date.parse(metadata["created_at"]) <= (Date.today - 30) - - new_formula_problem "GitHub repository too new (<30 days old)" + new_formula_problem warning end def audit_gitlab_repository user, repo = get_repo_data(%r{https?://gitlab\.com/([^/]+)/([^/]+)/?.*}) return if user.nil? - out, _, status= curl_output("--request", "GET", "https://gitlab.com/api/v4/projects/#{user}%2F#{repo}") - return unless status.success? + warning = SharedAudits.gitlab(user, repo) + return if warning.nil? - metadata = JSON.parse(out) - return if metadata.nil? - - new_formula_problem "GitLab fork (not canonical repository)" if metadata["fork"] - if (metadata["forks_count"] < 30) && (metadata["star_count"] < 75) - new_formula_problem "GitLab repository not notable enough (<30 forks and <75 stars)" - end - - return if Date.parse(metadata["created_at"]) <= (Date.today - 30) - - new_formula_problem "GitLab repository too new (<30 days old)" + new_formula_problem warning end def audit_bitbucket_repository user, repo = get_repo_data(%r{https?://bitbucket\.org/([^/]+)/([^/]+)/?.*}) return if user.nil? - api_url = "https://api.bitbucket.org/2.0/repositories/#{user}/#{repo}" - out, _, status= curl_output("--request", "GET", api_url) - return unless status.success? + warning = SharedAudits.bitbucket(user, repo) + return if warning.nil? - metadata = JSON.parse(out) - return if metadata.nil? - - new_formula_problem "Uses deprecated mercurial support in Bitbucket" if metadata["scm"] == "hg" - - new_formula_problem "Bitbucket fork (not canonical repository)" unless metadata["parent"].nil? - - if Date.parse(metadata["created_on"]) >= (Date.today - 30) - new_formula_problem "Bitbucket repository too new (<30 days old)" - end - - forks_out, _, forks_status= curl_output("--request", "GET", "#{api_url}/forks") - return unless forks_status.success? - - watcher_out, _, watcher_status= curl_output("--request", "GET", "#{api_url}/watchers") - return unless watcher_status.success? - - forks_metadata = JSON.parse(forks_out) - return if forks_metadata.nil? - - watcher_metadata = JSON.parse(watcher_out) - return if watcher_metadata.nil? - - return if (forks_metadata["size"] < 30) && (watcher_metadata["size"] < 75) - - new_formula_problem "Bitbucket repository not notable enough (<30 forks and <75 watchers)" + new_formula_problem warning end def get_repo_data(regex) @@ -608,7 +547,7 @@ module Homebrew _, user, repo = *regex.match(formula.homepage) unless user return if !user || !repo - repo.gsub!(/.git$/, "") + repo.delete_suffix!(".git") [user, repo] end @@ -730,7 +669,7 @@ module Homebrew .map(&:to_i) case (url = stable.url) - when /[\d\._-](alpha|beta|rc\d)/ + when /[\d._-](alpha|beta|rc\d)/ matched = Regexp.last_match(1) version_prefix = stable_version_string.sub(/\d+$/, "") return if UNSTABLE_WHITELIST[formula.name] == version_prefix @@ -758,7 +697,7 @@ module Homebrew .second begin - if (release = GitHub.open_api("#{GitHub::API_URL}/repos/#{owner}/#{repo}/releases/tags/#{tag}")) + if @online && (release = GitHub.open_api("#{GitHub::API_URL}/repos/#{owner}/#{repo}/releases/tags/#{tag}")) problem "#{tag} is a GitHub prerelease" if release["prerelease"] problem "#{tag} is a GitHub draft" if release["draft"] end @@ -864,7 +803,7 @@ module Homebrew end bin_names.each do |name| ["system", "shell_output", "pipe_output"].each do |cmd| - if text.to_s.match?(/test do.*#{cmd}[\(\s]+['"]#{Regexp.escape(name)}[\s'"]/m) + if text.to_s.match?(/test do.*#{cmd}[(\s]+['"]#{Regexp.escape(name)}[\s'"]/m) problem %Q(fully scope test #{cmd} calls, e.g. #{cmd} "\#{bin}/#{name}") end end @@ -984,7 +923,7 @@ module Homebrew except_audits = @except methods.map(&:to_s).grep(/^audit_/).each do |audit_method_name| - name = audit_method_name.gsub(/^audit_/, "") + name = audit_method_name.delete_prefix("audit_") if only_audits next unless only_audits.include?(name) elsif except_audits @@ -1052,15 +991,9 @@ module Homebrew end def audit_download_strategy - if url =~ %r{^(cvs|bzr|hg|fossil)://} || url =~ %r{^(svn)\+http://} - # TODO: check could be in RuboCop - problem "Use of the #{$&} scheme is deprecated, pass `:using => :#{Regexp.last_match(1)}` instead" - end - url_strategy = DownloadStrategyDetector.detect(url) if using == :git || url_strategy == GitDownloadStrategy - # TODO: check could be in RuboCop problem "Git should specify :revision when a :tag is specified." if specs[:tag] && !specs[:revision] end diff --git a/Library/Homebrew/dev-cmd/bottle.rb b/Library/Homebrew/dev-cmd/bottle.rb index a296594097..20fc41ed2a 100644 --- a/Library/Homebrew/dev-cmd/bottle.rb +++ b/Library/Homebrew/dev-cmd/bottle.rb @@ -321,7 +321,7 @@ module Homebrew if any_go_deps go_regex = Version.formula_optionally_versioned_regex(:go, full: false) - ignores << %r{#{Regexp.escape(HOMEBREW_CELLAR)}/#{go_regex}/[\d\.]+/libexec} + ignores << %r{#{Regexp.escape(HOMEBREW_CELLAR)}/#{go_regex}/[\d.]+/libexec} end relocatable = true diff --git a/Library/Homebrew/dev-cmd/bump-formula-pr.rb b/Library/Homebrew/dev-cmd/bump-formula-pr.rb index c08997c8aa..c3426f0ae3 100644 --- a/Library/Homebrew/dev-cmd/bump-formula-pr.rb +++ b/Library/Homebrew/dev-cmd/bump-formula-pr.rb @@ -79,7 +79,7 @@ module Homebrew origin_branch = "#{homebrew_core_remote}/#{homebrew_core_branch}" previous_branch = Utils.popen_read("git -C \"#{formula.tap.path}\" symbolic-ref -q --short HEAD").chomp previous_branch = "master" if previous_branch.empty? - formula_path = formula.path.to_s[%r{(Formula\/.*)}, 1] + formula_path = formula.path.to_s[%r{(Formula/.*)}, 1] if args.dry_run? ohai "git remote add #{homebrew_core_remote} #{homebrew_core_url}" @@ -89,7 +89,7 @@ module Homebrew return tap_full_name, origin_branch, previous_branch else formula.path.parent.cd do - unless Utils.popen_read("git remote -v").match?(%r{^homebrew.*Homebrew\/homebrew-core.*$}) + unless Utils.popen_read("git remote -v").match?(%r{^homebrew.*Homebrew/homebrew-core.*$}) ohai "Adding #{homebrew_core_remote} remote" safe_system "git", "remote", "add", homebrew_core_remote, homebrew_core_url end @@ -118,12 +118,6 @@ module Homebrew formula = args.formulae.first - if formula - tap_full_name, origin_branch, previous_branch = use_correct_linux_tap(formula) - check_for_duplicate_pull_requests(formula, tap_full_name) - checked_for_duplicates = true - end - new_url = args.url if new_url && !formula # Split the new URL on / and find any formulae that have the same URL @@ -152,7 +146,8 @@ module Homebrew end raise FormulaUnspecifiedError unless formula - check_for_duplicate_pull_requests(formula, tap_full_name) unless checked_for_duplicates + tap_full_name, origin_branch, previous_branch = use_correct_linux_tap(formula) + check_for_duplicate_pull_requests(formula, tap_full_name) requested_spec, formula_spec = if args.devel? devel_message = " (devel)" @@ -230,7 +225,7 @@ module Homebrew replacement_pairs += formula_spec.mirrors.map do |mirror| [ - / +mirror \"#{Regexp.escape(mirror)}\"\n/m, + / +mirror "#{Regexp.escape(mirror)}"\n/m, "", ] end @@ -263,7 +258,7 @@ module Homebrew if new_mirrors replacement_pairs << [ - /^( +)(url \"#{Regexp.escape(new_url)}\"\n)/m, + /^( +)(url "#{Regexp.escape(new_url)}"\n)/m, "\\1\\2\\1mirror \"#{new_mirrors.join("\"\n\\1mirror \"")}\"\n", ] end @@ -288,30 +283,30 @@ module Homebrew ] elsif new_mirrors [ - /^( +)(mirror \"#{Regexp.escape(new_mirrors.last)}\"\n)/m, + /^( +)(mirror "#{Regexp.escape(new_mirrors.last)}"\n)/m, "\\1\\2\\1version \"#{forced_version}\"\n", ] else [ - /^( +)(url \"#{Regexp.escape(new_url)}\"\n)/m, + /^( +)(url "#{Regexp.escape(new_url)}"\n)/m, "\\1\\2\\1version \"#{forced_version}\"\n", ] end elsif requested_spec == :devel replacement_pairs << [ - /( devel do.+?version \")#{old_formula_version}(\"\n.+?end\n)/m, + /( devel do.+?version ")#{old_formula_version}("\n.+?end\n)/m, "\\1#{forced_version}\\2", ] end elsif forced_version && forced_version == "0" if requested_spec == :stable replacement_pairs << [ - /^ version \"[\w\.\-\+]+\"\n/m, + /^ version "[\w.\-+]+"\n/m, "", ] elsif requested_spec == :devel replacement_pairs << [ - /( devel do.+?)^ +version \"[^\n]+\"\n(.+?end\n)/m, + /( devel do.+?)^ +version "[^\n]+"\n(.+?end\n)/m, "\\1\\2", ] end diff --git a/Library/Homebrew/dev-cmd/irb.rb b/Library/Homebrew/dev-cmd/irb.rb index e319acd972..e748e6fa19 100644 --- a/Library/Homebrew/dev-cmd/irb.rb +++ b/Library/Homebrew/dev-cmd/irb.rb @@ -19,7 +19,7 @@ module Homebrew def irb_args # work around IRB modifying ARGV. - Homebrew::CLI::Parser.new(ARGV.dup) do + Homebrew::CLI::Parser.new(ARGV.dup.freeze) do usage_banner <<~EOS `irb` [] @@ -38,7 +38,7 @@ module Homebrew if args.examples? puts "'v8'.f # => instance of the v8 formula" - puts ":hub.f.installed?" + puts ":hub.f.latest_version_installed?" puts ":lua.f.methods - 1.methods" puts ":mpd.f.recursive_dependencies.reject(&:installed?)" return diff --git a/Library/Homebrew/dev-cmd/pr-pull.rb b/Library/Homebrew/dev-cmd/pr-pull.rb index 039f52cc2a..48495a2b5d 100644 --- a/Library/Homebrew/dev-cmd/pr-pull.rb +++ b/Library/Homebrew/dev-cmd/pr-pull.rb @@ -60,7 +60,7 @@ module Homebrew rescue FormulaUnavailableError nil else - if gnupg.installed? + if gnupg.any_version_installed? path = PATH.new(ENV.fetch("PATH")) path.prepend(gnupg.installed_prefix/"bin") ENV["PATH"] = path diff --git a/Library/Homebrew/dev-cmd/pull.rb b/Library/Homebrew/dev-cmd/pull.rb index 4f1f988569..2c12404261 100644 --- a/Library/Homebrew/dev-cmd/pull.rb +++ b/Library/Homebrew/dev-cmd/pull.rb @@ -15,6 +15,7 @@ module Homebrew def pull_args Homebrew::CLI::Parser.new do + hide_from_man_page! usage_banner <<~EOS `pull` [] @@ -43,6 +44,8 @@ module Homebrew end def pull + odeprecated "brew pull", "hub checkout" + odie "You meant `git pull --rebase`." if ARGV[0] == "--rebase" pull_args.parse @@ -56,7 +59,7 @@ module Homebrew gnupg = Formula["gnupg"] rescue FormulaUnavailableError # rubocop:disable Lint/SuppressedException else - if gnupg.installed? + if gnupg.any_version_installed? path = PATH.new(ENV.fetch("PATH")) path.prepend(gnupg.installed_prefix/"bin") ENV["PATH"] = path @@ -333,7 +336,7 @@ module Homebrew def check_bintray_mirror(name, url) headers, = curl_output("--connect-timeout", "15", "--location", "--head", url) - status_code = headers.scan(%r{^HTTP\/.* (\d+)}).last.first + status_code = headers.scan(%r{^HTTP/.* (\d+)}).last.first return if status_code.start_with?("2") opoo "The Bintray mirror #{url} is not reachable (HTTP status code #{status_code})." diff --git a/Library/Homebrew/dev-cmd/tap-new.rb b/Library/Homebrew/dev-cmd/tap-new.rb index 5fb9dc4127..1ff92d0c7c 100644 --- a/Library/Homebrew/dev-cmd/tap-new.rb +++ b/Library/Homebrew/dev-cmd/tap-new.rb @@ -38,12 +38,6 @@ module Homebrew Or `brew tap #{tap}` and then `brew install `. - Or install via URL (which will not receive updates): - - ``` - brew install https://raw.githubusercontent.com/#{tap.user}/homebrew-#{tap.repo}/master/Formula/.rb - ``` - ## Documentation `brew help`, `man brew` or check [Homebrew's documentation](https://docs.brew.sh). MARKDOWN diff --git a/Library/Homebrew/diagnostic.rb b/Library/Homebrew/diagnostic.rb index cdf37ee2fe..ae7bb34fa9 100644 --- a/Library/Homebrew/diagnostic.rb +++ b/Library/Homebrew/diagnostic.rb @@ -3,6 +3,7 @@ require "keg" require "language/python" require "formula" +require "formulary" require "version" require "development_tools" require "utils/shell" @@ -832,6 +833,23 @@ module Homebrew EOS end + def check_deleted_formula + kegs = Keg.all + deleted_formulae = [] + kegs.each do |keg| + keg_name = keg.name + deleted_formulae << keg_name if Formulary.tap_paths(keg_name).blank? + end + return if deleted_formulae.blank? + + message = <<~EOS + Some installed formulae were deleted! + You should find replacements for the following formulae: + #{deleted_formulae.join("\n ")} + EOS + message + end + def all methods.map(&:to_s).grep(/^check_/) end diff --git a/Library/Homebrew/download_strategy.rb b/Library/Homebrew/download_strategy.rb index 3d8ca97571..e98b300828 100644 --- a/Library/Homebrew/download_strategy.rb +++ b/Library/Homebrew/download_strategy.rb @@ -221,7 +221,7 @@ class AbstractFileDownloadStrategy < AbstractDownloadStrategy end def basename - cached_location.basename.sub(/^[\da-f]{64}\-\-/, "") + cached_location.basename.sub(/^[\da-f]{64}--/, "") end private @@ -390,7 +390,7 @@ class CurlDownloadStrategy < AbstractFileDownloadStrategy filenames = lines.map(&parse_content_disposition).compact time = - lines.map { |line| line[/^Last\-Modified:\s*(.+)/i, 1] } + lines.map { |line| line[/^Last-Modified:\s*(.+)/i, 1] } .compact .map { |t| t.match?(/^\d+$/) ? Time.at(t.to_i) : Time.parse(t) } .last @@ -820,7 +820,7 @@ class GitHubGitDownloadStrategy < GitDownloadStrategy return unless status.success? - commit = output[/^ETag: \"(\h+)\"/, 1] + commit = output[/^ETag: "(\h+)"/, 1] version.update_commit(commit) if commit commit end diff --git a/Library/Homebrew/extend/ARGV.rb b/Library/Homebrew/extend/ARGV.rb deleted file mode 100644 index e72c01093b..0000000000 --- a/Library/Homebrew/extend/ARGV.rb +++ /dev/null @@ -1,63 +0,0 @@ -# frozen_string_literal: true - -module HomebrewArgvExtension - def value(name) - arg_prefix = "--#{name}=" - flag_with_value = find { |arg| arg.start_with?(arg_prefix) } - flag_with_value&.delete_prefix(arg_prefix) - end - - def debug? - flag?("--debug") || !ENV["HOMEBREW_DEBUG"].nil? - end - - def cc - value "cc" - end - - def env - value "env" - end - - private - - def options_only - select { |arg| arg.start_with?("-") } - end - - def flag?(flag) - options_only.include?(flag) || switch?(flag[2, 1]) - end - - # e.g. `foo -ns -i --bar` has three switches: `n`, `s` and `i` - def switch?(char) - return false if char.length > 1 - - options_only.any? { |arg| arg.scan("-").size == 1 && arg.include?(char) } - end - - def spec(default = :stable) - if include?("--HEAD") - :head - elsif include?("--devel") - :devel - else - default - end - end - - def named - self - options_only - end - - def downcased_unique_named - # Only lowercase names, not paths, bottle filenames or URLs - named.map do |arg| - if arg.include?("/") || arg.end_with?(".tar.gz") || File.exist?(arg) - arg - else - arg.downcase - end - end.uniq - end -end diff --git a/Library/Homebrew/extend/ENV.rb b/Library/Homebrew/extend/ENV.rb index 8b7ca32219..a3a2ecd088 100644 --- a/Library/Homebrew/extend/ENV.rb +++ b/Library/Homebrew/extend/ENV.rb @@ -6,7 +6,7 @@ require "extend/ENV/std" require "extend/ENV/super" def superenv? - ARGV.env != "std" && Superenv.bin + Homebrew.args.env != "std" && Superenv.bin end module EnvActivation diff --git a/Library/Homebrew/extend/ENV/shared.rb b/Library/Homebrew/extend/ENV/shared.rb index 36b84cf50b..6c995e8f16 100644 --- a/Library/Homebrew/extend/ENV/shared.rb +++ b/Library/Homebrew/extend/ENV/shared.rb @@ -162,7 +162,7 @@ module SharedEnvExtension # ENV.append_to_cflags "-I ./missing/includes" # end def compiler - @compiler ||= if (cc = ARGV.cc) + @compiler ||= if (cc = Homebrew.args.cc) warn_about_non_apple_gcc($&) if cc =~ GNU_GCC_REGEXP fetch_compiler(cc, "--cc") elsif (cc = homebrew_cc) diff --git a/Library/Homebrew/extend/os/linux/keg_relocate.rb b/Library/Homebrew/extend/os/linux/keg_relocate.rb index 0ec90cac9a..5371e2ab1e 100644 --- a/Library/Homebrew/extend/os/linux/keg_relocate.rb +++ b/Library/Homebrew/extend/os/linux/keg_relocate.rb @@ -19,6 +19,8 @@ class Keg return if !file.elf? || !file.dynamic_elf? patchelf = DevelopmentTools.locate "patchelf" + odie "Could not locate patchelf, please: brew install patchelf." if patchelf.nil? + cmd_rpath = [patchelf, "--print-rpath", file] old_rpath = Utils.popen_read(*cmd_rpath, err: :out).strip diff --git a/Library/Homebrew/extend/os/mac/diagnostic.rb b/Library/Homebrew/extend/os/mac/diagnostic.rb index 6e18a917bd..fe0bf0d5be 100644 --- a/Library/Homebrew/extend/os/mac/diagnostic.rb +++ b/Library/Homebrew/extend/os/mac/diagnostic.rb @@ -347,12 +347,13 @@ module Homebrew end def check_deprecated_caskroom_taps - tapped_caskroom_taps = Tap.select { |t| t.user == "caskroom" }.map(&:repo) + tapped_caskroom_taps = Tap.select { |t| t.user == "caskroom" || t.name == "phinze/cask" } + .map(&:name) return if tapped_caskroom_taps.empty? <<~EOS You have the following deprecated, cask taps tapped: - Caskroom/homebrew-#{tapped_caskroom_taps.join("\n Caskroom/homebrew-")} + #{tapped_caskroom_taps.join("\n ")} Untap them with `brew untap`. EOS end diff --git a/Library/Homebrew/extend/os/mac/extend/ENV/std.rb b/Library/Homebrew/extend/os/mac/extend/ENV/std.rb index 1bd5899bfd..ae04e62a8d 100644 --- a/Library/Homebrew/extend/os/mac/extend/ENV/std.rb +++ b/Library/Homebrew/extend/os/mac/extend/ENV/std.rb @@ -81,7 +81,7 @@ module Stdenv prepend "LDFLAGS", "-L#{HOMEBREW_PREFIX}/lib" sdk = formula ? MacOS.sdk_for_formula(formula, version) : MacOS.sdk(version) - return if !MacOS.sdk_root_needed? && sdk.source != :xcode + return if !MacOS.sdk_root_needed? && sdk&.source != :xcode sdk = sdk.path diff --git a/Library/Homebrew/extend/os/mac/extend/ENV/super.rb b/Library/Homebrew/extend/os/mac/extend/ENV/super.rb index 82b81a20f9..f1b92e5ce2 100644 --- a/Library/Homebrew/extend/os/mac/extend/ENV/super.rb +++ b/Library/Homebrew/extend/os/mac/extend/ENV/super.rb @@ -108,7 +108,7 @@ module Superenv # @private def setup_build_environment(formula = nil) sdk = formula ? MacOS.sdk_for_formula(formula) : MacOS.sdk - if MacOS.sdk_root_needed? || sdk.source == :xcode + if MacOS.sdk_root_needed? || sdk&.source == :xcode self["HOMEBREW_SDKROOT"] = sdk.path self["HOMEBREW_DEVELOPER_DIR"] = if sdk.source == :xcode MacOS::Xcode.prefix diff --git a/Library/Homebrew/extend/os/mac/keg_relocate.rb b/Library/Homebrew/extend/os/mac/keg_relocate.rb index 170b828a7c..d9a88c6584 100644 --- a/Library/Homebrew/extend/os/mac/keg_relocate.rb +++ b/Library/Homebrew/extend/os/mac/keg_relocate.rb @@ -106,10 +106,12 @@ class Keg bad_name.sub(PREFIX_PLACEHOLDER, HOMEBREW_PREFIX) elsif bad_name.start_with? CELLAR_PLACEHOLDER bad_name.sub(CELLAR_PLACEHOLDER, HOMEBREW_CELLAR) - elsif (file.dylib? || file.mach_o_bundle?) && (file.parent + bad_name).exist? + elsif (file.dylib? || file.mach_o_bundle?) && (file.dirname/bad_name).exist? "@loader_path/#{bad_name}" - elsif file.mach_o_executable? && (lib + bad_name).exist? + elsif file.mach_o_executable? && (lib/bad_name).exist? "#{lib}/#{bad_name}" + elsif file.mach_o_executable? && (libexec/"lib"/bad_name).exist? + "#{libexec}/lib/#{bad_name}" elsif bad_name.start_with?("@rpath") && ENV["HOMEBREW_RELOCATE_METAVARS"] expand_rpath file, bad_name elsif (abs_name = find_dylib(bad_name)) && abs_name.exist? diff --git a/Library/Homebrew/extend/pathname.rb b/Library/Homebrew/extend/pathname.rb index 98a8cfc1b1..e0c331f4dd 100644 --- a/Library/Homebrew/extend/pathname.rb +++ b/Library/Homebrew/extend/pathname.rb @@ -224,7 +224,7 @@ class Pathname return archive_ext if archive_ext # Don't treat version numbers as extname. - return "" if basename.match?(/\b\d+\.\d+[^\.]*\Z/) && !basename.end_with?(".7z") + return "" if basename.match?(/\b\d+\.\d+[^.]*\Z/) && !basename.end_with?(".7z") File.extname(basename) end @@ -398,15 +398,6 @@ class Pathname basename.to_s == ".DS_Store" end - # https://bugs.ruby-lang.org/issues/9915 - if RUBY_VERSION == "2.0.0" - prepend Module.new { - def inspect - super.force_encoding(@path.encoding) - end - } - end - def binary_executable? false end diff --git a/Library/Homebrew/extend/string.rb b/Library/Homebrew/extend/string.rb index a0dcb38776..903168af60 100644 --- a/Library/Homebrew/extend/string.rb +++ b/Library/Homebrew/extend/string.rb @@ -2,21 +2,6 @@ require "active_support/core_ext/object/blank" -class String - # String.chomp, but if result is empty: returns nil instead. - # Allows `chuzzle || foo` short-circuits. - # TODO: Deprecate. - def chuzzle - s = chomp - s unless s.empty? - end -end - -class NilClass - # TODO: Deprecate. - def chuzzle; end -end - # Used by the inreplace function (in `utils.rb`). module StringInreplaceExtension attr_accessor :errors @@ -41,7 +26,7 @@ module StringInreplaceExtension # Looks for Makefile style variable definitions and replaces the # value with "new_value", or removes the definition entirely. def change_make_var!(flag, new_value) - return if gsub!(/^#{Regexp.escape(flag)}[ \t]*[\\?\+\:\!]?=[ \t]*((?:.*\\\n)*.*)$/, "#{flag}=#{new_value}", false) + return if gsub!(/^#{Regexp.escape(flag)}[ \t]*[\\?+:!]?=[ \t]*((?:.*\\\n)*.*)$/, "#{flag}=#{new_value}", false) errors << "expected to change #{flag.inspect} to #{new_value.inspect}" end @@ -50,7 +35,7 @@ module StringInreplaceExtension def remove_make_var!(flags) Array(flags).each do |flag| # Also remove trailing \n, if present. - unless gsub!(/^#{Regexp.escape(flag)}[ \t]*[\\?\+\:\!]?=(?:.*\\\n)*.*$\n?/, "", false) + unless gsub!(/^#{Regexp.escape(flag)}[ \t]*[\\?+:!]?=(?:.*\\\n)*.*$\n?/, "", false) errors << "expected to remove #{flag.inspect}" end end @@ -58,6 +43,6 @@ module StringInreplaceExtension # Finds the specified variable def get_make_var(flag) - self[/^#{Regexp.escape(flag)}[ \t]*[\\?\+\:\!]?=[ \t]*((?:.*\\\n)*.*)$/, 1] + self[/^#{Regexp.escape(flag)}[ \t]*[\\?+:!]?=[ \t]*((?:.*\\\n)*.*)$/, 1] end end diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index ab90329020..1c027380f1 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -1172,7 +1172,7 @@ class Formula begin yield self, staging rescue - staging.retain! if Homebrew.args.interactive? || ARGV.debug? + staging.retain! if Homebrew.args.interactive? || Homebrew.args.debug? raise ensure cp Dir["config.log", "CMakeCache.txt"], logs @@ -1822,7 +1822,7 @@ class Formula end end rescue Exception # rubocop:disable Lint/RescueException - staging.retain! if ARGV.debug? + staging.retain! if Homebrew.args.debug? raise end end @@ -2090,7 +2090,6 @@ class Formula private def prepare_patches - active_spec.add_legacy_patches(patches) if respond_to?(:patches) patchlist.grep(DATAPatch) { |p| p.path = path } end @@ -2171,7 +2170,10 @@ class Formula raise "You cannot override Formula#brew in class #{name}" when :test define_method(:test_defined?) { true } + when :patches + odeprecated "a Formula#patches definition", "'patch do' block calls" when :options + odeprecated "a Formula#options definition", "'option do' block calls" instance = allocate specs.each do |spec| @@ -2385,6 +2387,7 @@ class Formula @devel ||= SoftwareSpec.new return @devel unless block_given? + odeprecated "'devel' blocks in formulae", "'head' blocks or @-versioned formulae" @devel.instance_eval(&block) end @@ -2668,7 +2671,7 @@ class Formula # regex /foo-(\d+(?:\.\d+)+)\.tar/ # end def livecheck(&block) - @livecheck ||= Livecheck.new + @livecheck ||= Livecheck.new(self) return @livecheck unless block_given? @livecheckable = true diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb index 20917292fc..41298db9e3 100644 --- a/Library/Homebrew/formula_installer.rb +++ b/Library/Homebrew/formula_installer.rb @@ -59,7 +59,7 @@ class FormulaInstaller @git = false @verbose = Homebrew.args.verbose? @quiet = Homebrew.args.quiet? - @debug = ARGV.debug? + @debug = Homebrew.args.debug? @installed_as_dependency = false @installed_on_request = true @options = Options.new @@ -100,7 +100,7 @@ class FormulaInstaller return false if !formula.bottled? && !formula.local_bottle_path return true if force_bottle? return false if build_from_source? || build_bottle? || interactive? - return false if ARGV.cc + return false if Homebrew.args.cc return false unless options.empty? return false if formula.bottle_disabled? @@ -141,7 +141,6 @@ class FormulaInstaller def prelude Tab.clear_cache verify_deps_exist unless ignore_deps? - lock check_install_sanity end @@ -221,6 +220,8 @@ class FormulaInstaller end def install + lock + start_time = Time.now if !formula.bottle_unneeded? && !pour_bottle? && DevelopmentTools.installed? Homebrew::Install.perform_build_from_source_checks @@ -417,7 +418,7 @@ class FormulaInstaller req_map.each_pair do |dependent, reqs| reqs.each do |req| - next if dependent.installed? && req.name == "maximummacos" + next if dependent.latest_version_installed? && req.name == "maximummacos" @requirement_messages << "#{dependent}: #{req.message}" fatals << req if req.fatal? @@ -453,13 +454,16 @@ class FormulaInstaller build = effective_build_options_for(dependent) install_bottle_for_dependent = install_bottle_for?(dependent, build) + keep_build_test = false + keep_build_test ||= runtime_requirements.include?(req) + keep_build_test ||= req.test? && include_test? && dependent == f + keep_build_test ||= req.build? && !install_bottle_for_dependent && !dependent.latest_version_installed? + if req.prune_from_option?(build) Requirement.prune elsif req.satisfied? Requirement.prune - elsif include_test? && req.test? - next - elsif !runtime_requirements.include?(req) && install_bottle_for_dependent + elsif (req.build? || req.test?) && !keep_build_test Requirement.prune elsif (dep = formula_deps_map[dependent.name]) && dep.build? Requirement.prune @@ -486,13 +490,13 @@ class FormulaInstaller inherited_options.fetch(dependent.name, []), ) + keep_build_test = false + keep_build_test ||= dep.test? && include_test? && Homebrew.args.include_formula_test_deps?(dependent) + keep_build_test ||= dep.build? && !install_bottle_for?(dependent, build) && !dependent.latest_version_installed? + if dep.prune_from_option?(build) Dependency.prune - elsif dep.test? && !dep.build? && !include_test? - Dependency.prune - elsif dep.build? && !dep.test? && install_bottle_for?(dependent, build) - Dependency.prune - elsif dep.prune_if_build_and_not_dependent?(dependent) + elsif (dep.build? || dep.test?) && !keep_build_test Dependency.prune elsif dep.satisfied?(inherited_options[dep.name]) Dependency.skip @@ -568,6 +572,7 @@ class FormulaInstaller fi.build_from_source = Homebrew.args.build_formula_from_source?(df) fi.force_bottle = false + fi.include_test = Homebrew.args.include_formula_test_deps?(df) fi.verbose = verbose? fi.quiet = quiet? fi.debug = debug? @@ -589,7 +594,7 @@ class FormulaInstaller linked_keg.unlink end - if df.installed? + if df.latest_version_installed? installed_keg = Keg.new(df.prefix) tmp_keg = Pathname.new("#{installed_keg}.tmp") installed_keg.rename(tmp_keg) @@ -610,6 +615,7 @@ class FormulaInstaller fi.options &= df.options fi.build_from_source = Homebrew.args.build_formula_from_source?(df) fi.force_bottle = false + fi.include_test = Homebrew.args.include_formula_test_deps?(df) fi.verbose = verbose? fi.quiet = quiet? fi.debug = debug? @@ -723,11 +729,11 @@ class FormulaInstaller args << "--interactive" if interactive? args << "--verbose" if verbose? args << "--debug" if debug? - args << "--cc=#{ARGV.cc}" if ARGV.cc + args << "--cc=#{Homebrew.args.cc}" if Homebrew.args.cc args << "--keep-tmp" if Homebrew.args.keep_tmp? - if ARGV.env - args << "--env=#{ARGV.env}" + if Homebrew.args.env.present? + args << "--env=#{Homebrew.args.env}" elsif formula.env.std? || formula.deps.select(&:build?).any? { |d| d.name == "scons" } args << "--env=std" end @@ -740,7 +746,7 @@ class FormulaInstaller formula.options.each do |opt| name = opt.name[/^([^=]+)=$/, 1] - value = ARGV.value(name) if name + value = Homebrew.args.value(name) if name args << "--#{name}=#{value}" if value end @@ -964,9 +970,10 @@ class FormulaInstaller end def fetch_dependencies - deps = compute_dependencies + return if ignore_deps? - return if deps.empty? || ignore_deps? + deps = compute_dependencies + return if deps.empty? deps.each { |dep, _options| fetch_dependency(dep) } end diff --git a/Library/Homebrew/formula_versions.rb b/Library/Homebrew/formula_versions.rb index a30313846c..1f8c3c19c3 100644 --- a/Library/Homebrew/formula_versions.rb +++ b/Library/Homebrew/formula_versions.rb @@ -44,7 +44,7 @@ class FormulaVersions rescue *IGNORED_EXCEPTIONS => e # We rescue these so that we can skip bad versions and # continue walking the history - odebug "#{e} in #{name} at revision #{rev}", e.backtrace if ARGV.debug? + odebug "#{e} in #{name} at revision #{rev}", e.backtrace if Homebrew.args.debug? rescue FormulaUnavailableError nil ensure diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb index b01973fab6..086d8ff61f 100644 --- a/Library/Homebrew/formulary.rb +++ b/Library/Homebrew/formulary.rb @@ -9,6 +9,8 @@ require "extend/cachable" module Formulary extend Cachable + URL_START_REGEX = %r{(https?|ftp|file)://}.freeze + def self.enable_factory_cache! @factory_cache = true end @@ -130,7 +132,7 @@ module Formulary private def load_file - $stderr.puts "#{$PROGRAM_NAME} (#{self.class.name}): loading #{path}" if ARGV.debug? + $stderr.puts "#{$PROGRAM_NAME} (#{self.class.name}): loading #{path}" if Homebrew.args.debug? raise FormulaUnavailableError, name unless path.file? Formulary.load_formula_from_path(name, path) @@ -141,7 +143,7 @@ module Formulary class BottleLoader < FormulaLoader def initialize(bottle_name) case bottle_name - when %r{(https?|ftp|file)://} + when URL_START_REGEX # The name of the formula is found between the last slash and the last hyphen. formula_name = File.basename(bottle_name)[/(.+)-/, 1] resource = Resource.new(formula_name) { url bottle_name } @@ -205,21 +207,20 @@ module Formulary def load_file if url =~ %r{githubusercontent.com/[\w-]+/[\w-]+/[a-f0-9]{40}(/Formula)?/([\w+-.@]+).rb} formula_name = Regexp.last_match(2) - opoo <<~EOS - Unsupported installation from a commit URL! - Consider using `brew extract #{formula_name} ...` instead!" - This will extract your desired #{formula_name} version to a stable tap instead of - installing from a commit URL that cannnot receive updates or fixes! - - EOS + odeprecated "Installation of #{formula_name} from a GitHub commit URL", + "'brew extract #{formula_name}' to stable tap on GitHub" + elsif url.match?(%r{^(https?|ftp)://}) + odeprecated "Non-checksummed download of #{name} formula file from an arbitrary URL", + "'brew extract' or 'brew create' and 'brew tap-new' to create a "\ + "formula file in a tap on GitHub" end HOMEBREW_CACHE_FORMULA.mkpath FileUtils.rm_f(path) curl_download url, to: path super rescue MethodDeprecatedError => e - if url =~ %r{github.com/([\w-]+)/homebrew-([\w-]+)/} - e.issues_url = "https://github.com/#{Regexp.last_match(1)}/homebrew-#{Regexp.last_match(2)}/issues/new" + if url =~ %r{github.com/([\w-]+)/([\w-]+)/} + e.issues_url = "https://github.com/#{Regexp.last_match(1)}/#{Regexp.last_match(2)}/issues/new" end raise end @@ -307,7 +308,7 @@ module Formulary end def klass - $stderr.puts "#{$PROGRAM_NAME} (#{self.class.name}): loading #{path}" if ARGV.debug? + $stderr.puts "#{$PROGRAM_NAME} (#{self.class.name}): loading #{path}" if Homebrew.args.debug? namespace = "FormulaNamespace#{Digest::MD5.hexdigest(contents)}" Formulary.load_formula(name, path, contents, namespace) end @@ -418,7 +419,7 @@ module Formulary case ref when Pathname::BOTTLE_EXTNAME_RX return BottleLoader.new(ref) - when %r{(https?|ftp|file)://} + when URL_START_REGEX return FromUrlLoader.new(ref) when HOMEBREW_TAP_FORMULA_REGEX return TapLoader.new(ref, from: from) @@ -483,20 +484,4 @@ module Formulary ]).find(&:file?) end.compact end - - def self.find_with_priority(ref, spec = :stable) - possible_pinned_tap_formulae = tap_paths(ref, Dir["#{HOMEBREW_LIBRARY}/PinnedTaps/*/*/"]).map(&:realpath) - raise TapFormulaAmbiguityError.new(ref, possible_pinned_tap_formulae) if possible_pinned_tap_formulae.size > 1 - - if possible_pinned_tap_formulae.size == 1 - selected_formula = factory(possible_pinned_tap_formulae.first, spec) - if core_path(ref).file? - odisabled "the brew tap-pin command", - "fully-scoped user/tap/formula naming when installing and in dependency references" - end - selected_formula - else - factory(ref, spec) - end - end end diff --git a/Library/Homebrew/global.rb b/Library/Homebrew/global.rb index b7067e7717..dbdca9a57c 100644 --- a/Library/Homebrew/global.rb +++ b/Library/Homebrew/global.rb @@ -35,13 +35,10 @@ require "env_config" require "config" require "os" -require "extend/ARGV" require "cli/args" require "messages" require "system_command" -ARGV.extend(HomebrewArgvExtension) - HOMEBREW_PRODUCT = ENV["HOMEBREW_PRODUCT"] HOMEBREW_VERSION = ENV["HOMEBREW_VERSION"] HOMEBREW_WWW = "https://brew.sh" diff --git a/Library/Homebrew/help.rb b/Library/Homebrew/help.rb index 7e45247b75..0e41977c72 100644 --- a/Library/Homebrew/help.rb +++ b/Library/Homebrew/help.rb @@ -103,7 +103,7 @@ module Homebrew help_lines = command_help_lines(path) return if help_lines.blank? - Formatter.wrap(help_lines.join.gsub(/^ /, ""), COMMAND_DESC_WIDTH) + Formatter.wrap(help_lines.join.delete_prefix(" "), COMMAND_DESC_WIDTH) .sub("@hide_from_man_page ", "") .sub(/^\* /, "#{Tty.bold}Usage: brew#{Tty.reset} ") .gsub(/`(.*?)`/m, "#{Tty.bold}\\1#{Tty.reset}") diff --git a/Library/Homebrew/install.rb b/Library/Homebrew/install.rb index 4a3f031327..18bc534d85 100644 --- a/Library/Homebrew/install.rb +++ b/Library/Homebrew/install.rb @@ -37,11 +37,11 @@ module Homebrew end def check_cc_argv - return unless ARGV.cc + return unless Homebrew.args.cc @checks ||= Diagnostic::Checks.new opoo <<~EOS - You passed `--cc=#{ARGV.cc}`. + You passed `--cc=#{Homebrew.args.cc}`. #{@checks.please_create_pull_requests} EOS end diff --git a/Library/Homebrew/keg_relocate.rb b/Library/Homebrew/keg_relocate.rb index b8028ceab5..bc9d32b879 100644 --- a/Library/Homebrew/keg_relocate.rb +++ b/Library/Homebrew/keg_relocate.rb @@ -117,6 +117,10 @@ class Keg path/"lib" end + def libexec + path/"libexec" + end + def text_files text_files = [] return text_files unless which("file") && which("xargs") diff --git a/Library/Homebrew/language/python.rb b/Library/Homebrew/language/python.rb index caaa6cb6a4..581ee82ac0 100644 --- a/Library/Homebrew/language/python.rb +++ b/Library/Homebrew/language/python.rb @@ -33,7 +33,7 @@ module Language next if build.without? python_formula.to_s version = major_minor_version python - ENV["PYTHONPATH"] = if python_formula.installed? + ENV["PYTHONPATH"] = if python_formula.latest_version_installed? nil else homebrew_site_packages(python) diff --git a/Library/Homebrew/livecheck.rb b/Library/Homebrew/livecheck.rb index f2bf621f1e..e040893961 100644 --- a/Library/Homebrew/livecheck.rb +++ b/Library/Homebrew/livecheck.rb @@ -10,7 +10,8 @@ class Livecheck # e.g. `Not maintained` attr_reader :skip_msg - def initialize + def initialize(formula) + @formula = formula @regex = nil @skip = false @skip_msg = nil @@ -44,7 +45,14 @@ class Livecheck def url(val = nil) return @url if val.nil? - @url = val + @url = case val + when :head, :stable, :devel + @formula.send(val).url + when :homepage + @formula.homepage + else + val + end end # Returns a Hash of all instance variable values. diff --git a/Library/Homebrew/locale.rb b/Library/Homebrew/locale.rb index c005e5296d..174c594ad9 100644 --- a/Library/Homebrew/locale.rb +++ b/Library/Homebrew/locale.rb @@ -8,7 +8,7 @@ class Locale REGION_REGEX = /(?:[A-Z]{2}|\d{3})/.freeze # ISO 3166-1 or UN M.49 SCRIPT_REGEX = /(?:[A-Z][a-z]{3})/.freeze # ISO 15924 - LOCALE_REGEX = /\A((?:#{LANGUAGE_REGEX}|#{REGION_REGEX}|#{SCRIPT_REGEX})(?:\-|$)){1,3}\Z/.freeze + LOCALE_REGEX = /\A((?:#{LANGUAGE_REGEX}|#{REGION_REGEX}|#{SCRIPT_REGEX})(?:-|$)){1,3}\Z/.freeze def self.parse(string) string = string.to_s @@ -16,7 +16,7 @@ class Locale raise ParserError, "'#{string}' cannot be parsed to a #{self}" unless string.match?(LOCALE_REGEX) scan = proc do |regex| - string.scan(/(?:\-|^)(#{regex})(?:\-|$)/).flatten.first + string.scan(/(?:-|^)(#{regex})(?:-|$)/).flatten.first end language = scan.call(LANGUAGE_REGEX) diff --git a/Library/Homebrew/manpages/brew.1.md.erb b/Library/Homebrew/manpages/brew.1.md.erb index ac68c57dc0..cea0745e33 100644 --- a/Library/Homebrew/manpages/brew.1.md.erb +++ b/Library/Homebrew/manpages/brew.1.md.erb @@ -97,11 +97,9 @@ can take several different forms: You can still access these formulae by using a special syntax, e.g. `homebrew/dupes/vim` or `homebrew/versions/node4`. - * An arbitrary file or URL: - Homebrew can install formulae via URL, e.g. - `https://raw.githubusercontent.com/Homebrew/homebrew-core/master/Formula/git.rb`, - or from a local path. It can point to either a formula file or a bottle. - In the case of a URL, the downloaded file will be cached for later use. + * An arbitrary file: + Homebrew can install formulae from a local path. It can point to either a + formula file or a bottle. ## ENVIRONMENT diff --git a/Library/Homebrew/migrator.rb b/Library/Homebrew/migrator.rb index 7b393d5127..3329e164bc 100644 --- a/Library/Homebrew/migrator.rb +++ b/Library/Homebrew/migrator.rb @@ -209,7 +209,7 @@ class Migrator rescue Exception => e # rubocop:disable Lint/RescueException onoe "Error occurred while migrating." puts e - puts e.backtrace if ARGV.debug? + puts e.backtrace if Homebrew.args.debug? puts "Backing up..." ignore_interrupts { backup_oldname } ensure @@ -318,7 +318,7 @@ class Migrator rescue Exception => e # rubocop:disable Lint/RescueException onoe "An unexpected error occurred during linking" puts e - puts e.backtrace if ARGV.debug? + puts e.backtrace if Homebrew.args.debug? ignore_interrupts { new_keg.unlink } raise end diff --git a/Library/Homebrew/os/linux.rb b/Library/Homebrew/os/linux.rb index b295005c3a..c035191168 100644 --- a/Library/Homebrew/os/linux.rb +++ b/Library/Homebrew/os/linux.rb @@ -42,11 +42,7 @@ module OS end def languages - @languages ||= [ - *ARGV.value("language")&.split(","), - *ENV["HOMEBREW_LANGUAGES"]&.split(","), - *ENV["LANG"]&.slice(/[a-z]+/), - ].uniq + @languages ||= [*ENV["LANG"]&.slice(/[a-z]+/)].uniq end def language diff --git a/Library/Homebrew/os/mac.rb b/Library/Homebrew/os/mac.rb index 3118edf50f..4e77f0cf25 100644 --- a/Library/Homebrew/os/mac.rb +++ b/Library/Homebrew/os/mac.rb @@ -60,9 +60,11 @@ module OS def languages @languages ||= [ - *ARGV.value("language")&.split(","), + *Homebrew.args.value("language")&.split(","), *ENV["HOMEBREW_LANGUAGES"]&.split(","), - *Open3.capture2("defaults", "read", "-g", "AppleLanguages")[0].scan(/[^ \n"(),]+/), + *Open3.capture2("defaults", "read", "-g", "AppleLanguages") + .first + .scan(/[^ \n"(),]+/), ].uniq end diff --git a/Library/Homebrew/os/mac/keg.rb b/Library/Homebrew/os/mac/keg.rb index 9cf35e39d9..90593712ff 100644 --- a/Library/Homebrew/os/mac/keg.rb +++ b/Library/Homebrew/os/mac/keg.rb @@ -5,7 +5,7 @@ class Keg return if file.dylib_id == id @require_relocation = true - odebug "Changing dylib ID of #{file}\n from #{file.dylib_id}\n to #{id}" if ARGV.debug? + odebug "Changing dylib ID of #{file}\n from #{file.dylib_id}\n to #{id}" if Homebrew.args.debug? MachO::Tools.change_dylib_id(file, id, strict: false) rescue MachO::MachOError onoe <<~EOS @@ -20,7 +20,7 @@ class Keg return if old == new @require_relocation = true - odebug "Changing install name in #{file}\n from #{old}\n to #{new}" if ARGV.debug? + odebug "Changing install name in #{file}\n from #{old}\n to #{new}" if Homebrew.args.debug? MachO::Tools.change_install_name(file, old, new, strict: false) rescue MachO::MachOError onoe <<~EOS diff --git a/Library/Homebrew/patch.rb b/Library/Homebrew/patch.rb index 1050e5bdf4..03aea114e4 100644 --- a/Library/Homebrew/patch.rb +++ b/Library/Homebrew/patch.rb @@ -169,6 +169,7 @@ end # Legacy patches have no checksum and are not cached. class LegacyPatch < ExternalPatch def initialize(strip, url) + odeprecated "legacy patches", "'patch do' blocks" super(strip) resource.url(url) resource.download_strategy = CurlDownloadStrategy diff --git a/Library/Homebrew/reinstall.rb b/Library/Homebrew/reinstall.rb index ff3c5707f2..be7f9c847e 100644 --- a/Library/Homebrew/reinstall.rb +++ b/Library/Homebrew/reinstall.rb @@ -35,8 +35,8 @@ module Homebrew fi.installed_as_dependency = tab.installed_as_dependency fi.installed_on_request = tab.installed_on_request end - fi.fetch fi.prelude + fi.fetch oh1 "Reinstalling #{Formatter.identifier(f.full_name)} #{options.to_a.join " "}" diff --git a/Library/Homebrew/requirements/java_requirement.rb b/Library/Homebrew/requirements/java_requirement.rb index 1c324df273..6d7c66c73c 100644 --- a/Library/Homebrew/requirements/java_requirement.rb +++ b/Library/Homebrew/requirements/java_requirement.rb @@ -111,7 +111,7 @@ class JavaRequirement < Requirement rescue FormulaUnavailableError nil end - javas << jdk.bin/"java" if jdk&.installed? + javas << jdk.bin/"java" if jdk&.latest_version_installed? javas << which("java") javas end diff --git a/Library/Homebrew/resource.rb b/Library/Homebrew/resource.rb index 082dd1a7a8..9053ac8b4d 100644 --- a/Library/Homebrew/resource.rb +++ b/Library/Homebrew/resource.rb @@ -72,7 +72,7 @@ class Resource # directory. Subclasses that override stage should implement the tmp # dir using {Mktemp} so that works with all subtypes. def stage(target = nil, &block) - raise ArgumentError, "target directory or block is required" if target.blank? && block.blank? + raise ArgumentError, "target directory or block is required" if !target && block.blank? prepare_patches fetch_patches(skip_downloaded: true) diff --git a/Library/Homebrew/rubocops/cask/homepage_matches_url.rb b/Library/Homebrew/rubocops/cask/homepage_matches_url.rb index b260d5c730..d142ad7170 100644 --- a/Library/Homebrew/rubocops/cask/homepage_matches_url.rb +++ b/Library/Homebrew/rubocops/cask/homepage_matches_url.rb @@ -129,7 +129,7 @@ module RuboCop string = stanza.stanza_node.children[2] return string.str_content if string.str_type? - string.to_s.gsub(%r{.*"([a-z0-9]+\:\/\/[^"]+)".*}m, '\1') + string.to_s.gsub(%r{.*"([a-z0-9]+://[^"]+)".*}m, '\1') end def url_match_homepage?(stanza) diff --git a/Library/Homebrew/rubocops/components_order.rb b/Library/Homebrew/rubocops/components_order.rb index 5049598b4b..155bd18e72 100644 --- a/Library/Homebrew/rubocops/components_order.rb +++ b/Library/Homebrew/rubocops/components_order.rb @@ -10,6 +10,11 @@ module RuboCop # - `component_precedence_list` has component hierarchy in a nested list # where each sub array contains components' details which are at same precedence level class ComponentsOrder < FormulaCop + # `aspell`: options and resources should be grouped by language + COMPONENT_WHITELIST = %w[ + aspell + ].freeze + def audit_formula(_node, _class_node, _parent_class_node, body_node) component_precedence_list = [ [{ name: :include, type: :method_call }], @@ -34,6 +39,8 @@ module RuboCop [{ name: :deprecated_option, type: :method_call }], [{ name: :depends_on, type: :method_call }], [{ name: :uses_from_macos, type: :method_call }], + [{ name: :on_macos, type: :block_call }], + [{ name: :on_linux, type: :block_call }], [{ name: :conflicts_with, type: :method_call }], [{ name: :skip_clean, type: :method_call }], [{ name: :cxxstdlib_check, type: :method_call }], @@ -49,50 +56,115 @@ module RuboCop [{ name: :test, type: :block_call }], ] - @present_components = component_precedence_list.map do |components| - relevant_components = [] - components.each do |component| - case component[:type] - when :method_call - relevant_components += find_method_calls_by_name(body_node, component[:name]).to_a - when :block_call - relevant_components += find_blocks(body_node, component[:name]).to_a - when :method_definition - relevant_components << find_method_def(body_node, component[:name]) - end - end - relevant_components.delete_if(&:nil?) + @present_components, @offensive_nodes = check_order(component_precedence_list, body_node) + + component_problem @offensive_nodes[0], @offensive_nodes[1] if @offensive_nodes + + component_precedence_list = [ + [{ name: :depends_on, type: :method_call }], + [{ name: :resource, type: :block_call }], + [{ name: :patch, type: :method_call }, { name: :patch, type: :block_call }], + ] + + on_macos_blocks = find_blocks(body_node, :on_macos) + + if on_macos_blocks.length > 1 + @offensive_node = on_macos_blocks.second + @offense_source_range = on_macos_blocks.second.source_range + problem "there can only be one `on_macos` block in a formula." end - # Check if each present_components is above rest of the present_components - @present_components.take(@present_components.size - 1).each_with_index do |preceding_component, p_idx| - next if preceding_component.empty? + check_on_os_block_content(component_precedence_list, on_macos_blocks.first) if on_macos_blocks.any? - @present_components.drop(p_idx + 1).each do |succeeding_component| - next if succeeding_component.empty? + on_linux_blocks = find_blocks(body_node, :on_linux) - @offensive_nodes = check_precedence(preceding_component, succeeding_component) - component_problem @offensive_nodes[0], @offensive_nodes[1] if @offensive_nodes + if on_linux_blocks.length > 1 + @offensive_node = on_linux_blocks.second + @offense_source_range = on_linux_blocks.second.source_range + problem "there can only be one `on_linux` block in a formula." + end + + check_on_os_block_content(component_precedence_list, on_linux_blocks.first) if on_linux_blocks.any? + + resource_blocks = find_blocks(body_node, :resource) + resource_blocks.each do |resource_block| + on_macos_blocks = find_blocks(resource_block.body, :on_macos) + on_linux_blocks = find_blocks(resource_block.body, :on_linux) + + if on_macos_blocks.length.zero? && on_linux_blocks.length.zero? + # Found nothing. Try without .body as depending on the code, + # on_macos or on_linux might be in .body or not ... + on_macos_blocks = find_blocks(resource_block, :on_macos) + on_linux_blocks = find_blocks(resource_block, :on_linux) + + next if on_macos_blocks.length.zero? && on_linux_blocks.length.zero? + end + + @offensive_node = resource_block + @offense_source_range = resource_block.source_range + + if on_macos_blocks.length > 1 + problem "there can only be one `on_macos` block in a resource block." + next + end + + if on_linux_blocks.length > 1 + problem "there can only be one `on_linux` block in a resource block." + next + end + + if on_macos_blocks.length == 1 && on_linux_blocks.length.zero? + problem "you need to define an `on_linux` block within your resource block." + next + end + + if on_macos_blocks.length.zero? && on_linux_blocks.length == 1 + problem "you need to define an `on_macos` block within your resource block." + next + end + + on_macos_block = on_macos_blocks.first + on_linux_block = on_linux_blocks.first + + child_nodes = on_macos_block.body.child_nodes + if child_nodes[0].method_name.to_s != "url" && child_nodes[1].method_name.to_s != "sha256" + problem "only an url and a sha256 (in the right order) are allowed in a `on_macos` " \ + "block within a resource block." + next + end + + child_nodes = on_linux_block.body.child_nodes + if child_nodes[0].method_name.to_s != "url" && child_nodes[1].method_name.to_s != "sha256" + problem "only an url and a sha256 (in the right order) are allowed in a `on_linux` " \ + "block within a resource block." end end end - # `aspell`: options and resources should be grouped by language - WHITELIST = %w[ - aspell - ].freeze + def check_on_os_block_content(component_precedence_list, on_os_block) + _, offensive_node = check_order(component_precedence_list, on_os_block.body) + component_problem(*offensive_node) if offensive_node + on_os_block.body.child_nodes.each do |child| + valid_node = depends_on_node?(child) + # Check for RuboCop::AST::SendNode instances only, as we are checking the + # method_name for patches and resources. + next unless child.instance_of? RuboCop::AST::SendNode - # Method to format message for reporting component precedence violations - def component_problem(c1, c2) - return if WHITELIST.include?(@formula_name) + valid_node ||= child.method_name.to_s == "patch" + valid_node ||= child.method_name.to_s == "resource" - problem "`#{format_component(c1)}` (line #{line_number(c1)}) " \ - "should be put before `#{format_component(c2)}` " \ - "(line #{line_number(c2)})" + @offensive_node = on_os_block + @offense_source_range = on_os_block.source_range + unless valid_node + problem "`#{on_os_block.method_name}` can only include `depends_on`, `patch` and `resource` nodes." + end + end end # autocorrect method gets called just after component_problem method call def autocorrect(_node) + return if @offensive_nodes.nil? + succeeding_node = @offensive_nodes[0] preceding_node = @offensive_nodes[1] lambda do |corrector| @@ -130,6 +202,52 @@ module RuboCop return [idx, comp.index(node1), comp] if comp.member?(node1) end end + + def check_order(component_precedence_list, body_node) + present_components = component_precedence_list.map do |components| + components.flat_map do |component| + case component[:type] + when :method_call + find_method_calls_by_name(body_node, component[:name]).to_a + when :block_call + find_blocks(body_node, component[:name]).to_a + when :method_definition + find_method_def(body_node, component[:name]) + end + end.compact + end + + # Check if each present_components is above rest of the present_components + offensive_nodes = nil + present_components.take(present_components.size - 1).each_with_index do |preceding_component, p_idx| + next if preceding_component.empty? + + present_components.drop(p_idx + 1).each do |succeeding_component| + next if succeeding_component.empty? + + offensive_nodes = check_precedence(preceding_component, succeeding_component) + break if offensive_nodes + end + end + + [present_components, offensive_nodes] + end + + # Method to format message for reporting component precedence violations + def component_problem(c1, c2) + return if COMPONENT_WHITELIST.include?(@formula_name) + + problem "`#{format_component(c1)}` (line #{line_number(c1)}) " \ + "should be put before `#{format_component(c2)}` " \ + "(line #{line_number(c2)})" + end + + # Node pattern method to match + # `depends_on` variants + def_node_matcher :depends_on_node?, <<~EOS + {(if _ (send nil? :depends_on ...) nil?) + (send nil? :depends_on ...)} + EOS end end end diff --git a/Library/Homebrew/rubocops/lines.rb b/Library/Homebrew/rubocops/lines.rb index 5ed08a2e03..7de4690695 100644 --- a/Library/Homebrew/rubocops/lines.rb +++ b/Library/Homebrew/rubocops/lines.rb @@ -153,7 +153,7 @@ module RuboCop find_instance_method_call(body_node, :build, :include?) do |method| arg = parameters(method).first - next unless match = regex_match_group(arg, /^\-\-(.*)$/) + next unless match = regex_match_group(arg, /^--(.*)$/) problem "Reference '#{match[1]}' without dashes" end @@ -403,7 +403,7 @@ module RuboCop path = parameters(method).first next unless path.str_type? - next unless match = regex_match_group(path, /^[^\*{},]+$/) + next unless match = regex_match_group(path, /^[^*{},]+$/) problem "Dir([\"#{string_content(path)}\"]) is unnecessary; just use \"#{match[0]}\"" end diff --git a/Library/Homebrew/rubocops/urls.rb b/Library/Homebrew/rubocops/urls.rb index 33d471a33a..f0872b3c1f 100644 --- a/Library/Homebrew/rubocops/urls.rb +++ b/Library/Homebrew/rubocops/urls.rb @@ -13,11 +13,12 @@ module RuboCop https://downloads.sourceforge.net/project/bittwist/ https://downloads.sourceforge.net/project/launch4j/ https://github.com/ChrisJohnsen/tmux-MacOSX-pasteboard/archive/ - https://github.com/obihann/archey-osx/archive/ + https://github.com/obihann/archey-osx https://github.com/sindresorhus/macos-wallpaper/archive/ https://raw.githubusercontent.com/liyanage/macosx-shell-scripts/ https://osxbook.com/book/bonus/chapter8/core/download/gcore https://naif.jpl.nasa.gov/pub/naif/toolkit/C/MacIntel_OSX_AppleC_64bit/packages/ + https://artifacts.videolan.org/x264/release-macos/ ].freeze # These are formulae that, sadly, require an upstream binary to bootstrap. @@ -48,6 +49,12 @@ module RuboCop urls = find_every_func_call_by_name(body_node, :url) mirrors = find_every_func_call_by_name(body_node, :mirror) + # Identify livecheck urls, to skip some checks for them + livecheck_url = if (livecheck = find_every_func_call_by_name(body_node, :livecheck).first) && + (livecheck_url = find_every_func_call_by_name(livecheck.parent, :url).first) + string_content(parameters(livecheck_url).first) + end + # GNU urls; doesn't apply to mirrors gnu_pattern = %r{^(?:https?|ftp)://ftpmirror.gnu.org/(.*)} audit_urls(urls, gnu_pattern) do |match, url| @@ -63,9 +70,21 @@ module RuboCop apache_pattern = %r{^https?://(?:[^/]*\.)?apache\.org/(?:dyn/closer\.cgi\?path=/?|dist/)(.*)}i audit_urls(urls, apache_pattern) do |match, url| + next if url == livecheck_url + problem "#{url} should be `https://www.apache.org/dyn/closer.lua?path=#{match[1]}`" end + version_control_pattern = %r{^(cvs|bzr|hg|fossil)://} + audit_urls(urls, version_control_pattern) do |match, _| + problem "Use of the #{match[1]}:// scheme is deprecated, pass `:using => :#{match[1]}` instead" + end + + svn_pattern = %r{^svn\+http://} + audit_urls(urls, svn_pattern) do |_, _| + problem "Use of the svn+http:// scheme is deprecated, pass `:using => :svn` instead" + end + audit_urls(mirrors, /.*/) do |_, mirror| urls.each do |url| url_string = string_content(parameters(url).first) @@ -148,7 +167,7 @@ module RuboCop problem "Don't use /download in SourceForge urls (url is #{url})." if url.end_with?("/download") - if url.match?(%r{^https?://sourceforge\.}) + if url.match?(%r{^https?://sourceforge\.}) && url != livecheck_url problem "Use https://downloads.sourceforge.net to get geolocation (url is #{url})." end @@ -220,7 +239,7 @@ module RuboCop # Use new-style archive downloads archive_gh_pattern = %r{https://.*github.*/(?:tar|zip)ball/} audit_urls(urls, archive_gh_pattern) do |_, url| - next if url.match?(/\.git$/) + next if url.end_with?(".git") problem "Use /archive/ URLs for GitHub tarballs (url is #{url})." end diff --git a/Library/Homebrew/software_spec.rb b/Library/Homebrew/software_spec.rb index 0e31f23b9f..72da2a2da1 100644 --- a/Library/Homebrew/software_spec.rb +++ b/Library/Homebrew/software_spec.rb @@ -221,6 +221,7 @@ class SoftwareSpec end end + # TODO def add_legacy_patches(list) list = Patch.normalize_legacy_patches(list) list.each { |p| p.owner = self } diff --git a/Library/Homebrew/style.rb b/Library/Homebrew/style.rb index 4c2c57d0ec..9ed95d53e8 100644 --- a/Library/Homebrew/style.rb +++ b/Library/Homebrew/style.rb @@ -77,7 +77,7 @@ module Homebrew case output_type when :print - args << "--debug" if ARGV.debug? + args << "--debug" if Homebrew.args.debug? args << "--display-cop-names" if Homebrew.args.display_cop_names? args << "--format" << "simple" if files system(cache_env, "rubocop", *args) diff --git a/Library/Homebrew/system_command.rb b/Library/Homebrew/system_command.rb index f21fa78e4c..fb05c7bd8b 100644 --- a/Library/Homebrew/system_command.rb +++ b/Library/Homebrew/system_command.rb @@ -34,7 +34,7 @@ class SystemCommand end def run! - puts redact_secrets(command.shelljoin.gsub('\=', "="), @secrets) if verbose? || ARGV.debug? + puts redact_secrets(command.shelljoin.gsub('\=', "="), @secrets) if verbose? || Homebrew.args.debug? @output = [] diff --git a/Library/Homebrew/system_config.rb b/Library/Homebrew/system_config.rb index def1702154..75fff1db24 100644 --- a/Library/Homebrew/system_config.rb +++ b/Library/Homebrew/system_config.rb @@ -88,7 +88,7 @@ class SystemConfig _, err, status = system_command("java", args: ["-version"], print_stderr: false) return "N/A" unless status.success? - err[/java version "([\d\._]+)"/, 1] || "N/A" + err[/java version "([\d._]+)"/, 1] || "N/A" end def describe_git @@ -100,7 +100,7 @@ class SystemConfig def describe_curl out, = system_command(curl_executable, args: ["--version"]) - if /^curl (?[\d\.]+)/ =~ out + if /^curl (?[\d.]+)/ =~ out "#{curl_version} => #{curl_executable}" else "N/A" diff --git a/Library/Homebrew/test/ARGV_spec.rb b/Library/Homebrew/test/ARGV_spec.rb deleted file mode 100644 index dd1699af31..0000000000 --- a/Library/Homebrew/test/ARGV_spec.rb +++ /dev/null @@ -1,89 +0,0 @@ -# frozen_string_literal: true - -require "extend/ARGV" - -describe HomebrewArgvExtension do - subject { argv.extend(described_class) } - - let(:argv) { ["mxcl"] } - - describe "#named" do - let(:argv) { ["foo", "--debug", "-v"] } - - it "returns an array of non-option arguments" do - expect(subject.send(:named)).to eq ["foo"] - end - - context "when there are no named arguments" do - let(:argv) { [] } - - it "returns an empty array" do - expect(subject.send(:named)).to be_empty - end - end - end - - describe "#options_only" do - let(:argv) { ["--foo", "-vds", "a", "b", "cdefg"] } - - it "returns an array of option arguments" do - expect(subject.send("options_only")).to eq ["--foo", "-vds"] - end - end - - describe "#empty?" do - let(:argv) { [] } - - it "returns true if it is empty" do - expect(subject).to be_empty - end - end - - describe "#switch?" do - let(:argv) { ["-ns", "-i", "--bar", "-a-bad-arg"] } - - it "returns true if the given string is a switch" do - %w[n s i].each do |s| - expect(subject.send("switch?", s)).to be true - end - end - - it "returns false if the given string is not a switch" do - %w[b ns bar --bar -n a bad arg].each do |s| - expect(subject.send("switch?", s)).to be false - end - end - end - - describe "#flag?" do - let(:argv) { ["--foo", "-bq", "--bar"] } - - it "returns true if the given string is a flag" do - expect(subject.send("flag?", "--foo")).to eq true - expect(subject.send("flag?", "--bar")).to eq true - end - - it "returns true if there is a switch with the same initial character" do - expect(subject.send("flag?", "--baz")).to eq true - expect(subject.send("flag?", "--qux")).to eq true - end - - it "returns false if there is no matching flag" do - expect(subject.send("flag?", "--frotz")).to eq false - expect(subject.send("flag?", "--debug")).to eq false - end - end - - describe "#value" do - let(:argv) { ["--foo=", "--bar=ab"] } - - it "returns the value for a given string" do - expect(subject.value("foo")).to eq "" - expect(subject.value("bar")).to eq "ab" - end - - it "returns nil if there is no matching argument" do - expect(subject.value("baz")).to be nil - end - end -end diff --git a/Library/Homebrew/test/cask/audit_spec.rb b/Library/Homebrew/test/cask/audit_spec.rb index 48e984e476..4533bf825c 100644 --- a/Library/Homebrew/test/cask/audit_spec.rb +++ b/Library/Homebrew/test/cask/audit_spec.rb @@ -39,12 +39,12 @@ describe Cask::Audit, :cask do let(:cask) { instance_double(Cask::Cask) } let(:download) { false } - let(:check_token_conflicts) { false } + let(:token_conflicts) { false } let(:fake_system_command) { class_double(SystemCommand) } let(:audit) { - described_class.new(cask, download: download, - check_token_conflicts: check_token_conflicts, - command: fake_system_command) + described_class.new(cask, download: download, + token_conflicts: token_conflicts, + command: fake_system_command) } describe "#result" do @@ -517,7 +517,7 @@ describe Cask::Audit, :cask do describe "token conflicts" do let(:cask_token) { "with-binary" } - let(:check_token_conflicts) { true } + let(:token_conflicts) { true } context "when cask token conflicts with a core formula" do let(:formula_names) { %w[with-binary other-formula] } diff --git a/Library/Homebrew/test/cask/cmd/audit_spec.rb b/Library/Homebrew/test/cask/cmd/audit_spec.rb index cc83e7b10d..0411531760 100644 --- a/Library/Homebrew/test/cask/cmd/audit_spec.rb +++ b/Library/Homebrew/test/cask/cmd/audit_spec.rb @@ -21,7 +21,13 @@ describe Cask::Cmd::Audit, :cask do expect(Cask::CaskLoader).to receive(:load).with(cask_token).and_return(cask) expect(Cask::Auditor).to receive(:audit) - .with(cask, audit_download: false, audit_appcast: false, check_token_conflicts: false, quarantine: true) + .with(cask, audit_download: false, + audit_appcast: false, + audit_token_conflicts: false, + audit_new_cask: false, + audit_online: false, + audit_strict: false, + quarantine: true) .and_return(true) described_class.run(cask_token) @@ -32,7 +38,13 @@ describe Cask::Cmd::Audit, :cask do it "does not download the Cask per default" do allow(Cask::CaskLoader).to receive(:load).and_return(cask) expect(Cask::Auditor).to receive(:audit) - .with(cask, audit_download: false, audit_appcast: false, check_token_conflicts: false, quarantine: true) + .with(cask, audit_download: false, + audit_appcast: false, + audit_token_conflicts: false, + audit_new_cask: false, + audit_online: false, + audit_strict: false, + quarantine: true) .and_return(true) described_class.run("casktoken") @@ -41,7 +53,13 @@ describe Cask::Cmd::Audit, :cask do it "download a Cask if --download flag is set" do allow(Cask::CaskLoader).to receive(:load).and_return(cask) expect(Cask::Auditor).to receive(:audit) - .with(cask, audit_download: true, audit_appcast: false, check_token_conflicts: false, quarantine: true) + .with(cask, audit_download: true, + audit_appcast: false, + audit_token_conflicts: false, + audit_new_cask: false, + audit_online: false, + audit_strict: false, + quarantine: true) .and_return(true) described_class.run("casktoken", "--download") @@ -52,7 +70,13 @@ describe Cask::Cmd::Audit, :cask do it "does not check for token conflicts per default" do allow(Cask::CaskLoader).to receive(:load).and_return(cask) expect(Cask::Auditor).to receive(:audit) - .with(cask, audit_download: false, audit_appcast: false, check_token_conflicts: false, quarantine: true) + .with(cask, audit_download: false, + audit_appcast: false, + audit_token_conflicts: false, + audit_new_cask: false, + audit_online: false, + audit_strict: false, + quarantine: true) .and_return(true) described_class.run("casktoken") @@ -61,10 +85,112 @@ describe Cask::Cmd::Audit, :cask do it "checks for token conflicts if --token-conflicts flag is set" do allow(Cask::CaskLoader).to receive(:load).and_return(cask) expect(Cask::Auditor).to receive(:audit) - .with(cask, audit_download: false, audit_appcast: false, check_token_conflicts: true, quarantine: true) + .with(cask, audit_download: false, + audit_appcast: false, + audit_token_conflicts: true, + audit_new_cask: false, + audit_online: false, + audit_strict: false, + quarantine: true) .and_return(true) described_class.run("casktoken", "--token-conflicts") end end + + describe "rules for checking strictly" do + it "does not check strictly per default" do + allow(Cask::CaskLoader).to receive(:load).and_return(cask) + expect(Cask::Auditor).to receive(:audit) + .with(cask, audit_download: false, + audit_appcast: false, + audit_token_conflicts: false, + audit_new_cask: false, + audit_online: false, + audit_strict: false, + quarantine: true) + .and_return(true) + + described_class.run("casktoken") + end + + it "checks strictly if --strict flag is set" do + allow(Cask::CaskLoader).to receive(:load).and_return(cask) + expect(Cask::Auditor).to receive(:audit) + .with(cask, audit_download: false, + audit_appcast: false, + audit_token_conflicts: true, + audit_new_cask: false, + audit_online: false, + audit_strict: true, + quarantine: true) + .and_return(true) + + described_class.run("casktoken", "--strict") + end + end + + describe "rules for checking online" do + it "does not check online per default" do + allow(Cask::CaskLoader).to receive(:load).and_return(cask) + expect(Cask::Auditor).to receive(:audit) + .with(cask, audit_download: false, + audit_appcast: false, + audit_token_conflicts: false, + audit_new_cask: false, + audit_online: false, + audit_strict: false, + quarantine: true) + .and_return(true) + + described_class.run("casktoken") + end + + it "checks online if --online flag is set" do + allow(Cask::CaskLoader).to receive(:load).and_return(cask) + expect(Cask::Auditor).to receive(:audit) + .with(cask, audit_download: true, + audit_appcast: true, + audit_token_conflicts: false, + audit_new_cask: false, + audit_online: true, + audit_strict: false, + quarantine: true) + .and_return(true) + + described_class.run("casktoken", "--online") + end + end + + describe "rules for checking new casks" do + it "does not check new casks per default" do + allow(Cask::CaskLoader).to receive(:load).and_return(cask) + expect(Cask::Auditor).to receive(:audit) + .with(cask, audit_download: false, + audit_appcast: false, + audit_token_conflicts: false, + audit_new_cask: false, + audit_online: false, + audit_strict: false, + quarantine: true) + .and_return(true) + + described_class.run("casktoken") + end + + it "checks new casks if --new-cask flag is set" do + allow(Cask::CaskLoader).to receive(:load).and_return(cask) + expect(Cask::Auditor).to receive(:audit) + .with(cask, audit_download: true, + audit_appcast: true, + audit_token_conflicts: true, + audit_new_cask: true, + audit_online: true, + audit_strict: true, + quarantine: true) + .and_return(true) + + described_class.run("casktoken", "--new-cask") + end + end end diff --git a/Library/Homebrew/test/cask/cmd/info_spec.rb b/Library/Homebrew/test/cask/cmd/info_spec.rb index 01fd90d27a..7d529f7112 100644 --- a/Library/Homebrew/test/cask/cmd/info_spec.rb +++ b/Library/Homebrew/test/cask/cmd/info_spec.rb @@ -2,6 +2,7 @@ require_relative "shared_examples/requires_cask_token" require_relative "shared_examples/invalid_option" +require "utils" describe Cask::Cmd::Info, :cask do it_behaves_like "a command that requires a Cask token" @@ -139,7 +140,16 @@ describe Cask::Cmd::Info, :cask do EOS end - it "can run be run with a url twice", :needs_network do + it "can run be run with a url twice and returns analytics", :needs_network do + analytics = { + "analytics" => { + "install" => { + "30d" => { "docker" => 1000 }, "90d" => { "docker" => 2000 }, "365d" => { "docker" => 3000 } + }, + }, + } + expect(Utils::Analytics).to receive(:formulae_brew_sh_json).twice.with("cask/docker.json") + .and_return(analytics) expect { described_class.run("https://raw.githubusercontent.com/Homebrew/homebrew-cask" \ "/d0b2c58652ae5eff20a7a4ac93292a08b250912b/Casks/docker.rb") @@ -155,6 +165,8 @@ describe Cask::Cmd::Info, :cask do Docker CE ==> Artifacts Docker.app (App) + ==> Analytics + install: 1,000 (30 days), 2,000 (90 days), 3,000 (365 days) ==> Downloading https://raw.githubusercontent.com/Homebrew/homebrew-cask/d0b2c58652ae5eff20a7a4ac93292a08b250912b/Casks/docker.rb. docker: 2.0.0.2-ce-mac81,30215 (auto_updates) https://www.docker.com/community-edition @@ -164,6 +176,8 @@ describe Cask::Cmd::Info, :cask do Docker CE ==> Artifacts Docker.app (App) + ==> Analytics + install: 1,000 (30 days), 2,000 (90 days), 3,000 (365 days) EOS end end diff --git a/Library/Homebrew/test/cmd/--cache_spec.rb b/Library/Homebrew/test/cmd/--cache_spec.rb index d682565306..42b452ec60 100644 --- a/Library/Homebrew/test/cmd/--cache_spec.rb +++ b/Library/Homebrew/test/cmd/--cache_spec.rb @@ -9,7 +9,7 @@ end describe "brew --cache", :integration_test do it "prints all cache files for a given Formula" do expect { brew "--cache", testball } - .to output(%r{#{HOMEBREW_CACHE}/downloads/[\da-f]{64}\-\-testball\-}).to_stdout + .to output(%r{#{HOMEBREW_CACHE}/downloads/[\da-f]{64}--testball-}).to_stdout .and not_to_output.to_stderr .and be_a_success end diff --git a/Library/Homebrew/test/cmd/install_spec.rb b/Library/Homebrew/test/cmd/install_spec.rb index b0623567a3..70ba941c78 100644 --- a/Library/Homebrew/test/cmd/install_spec.rb +++ b/Library/Homebrew/test/cmd/install_spec.rb @@ -68,7 +68,7 @@ describe "brew install", :integration_test do # and there will be the git requirement, but we cannot instantiate git # formula since we only have testball1 formula. expect { brew "install", "testball1", "--HEAD", "--ignore-dependencies" } - .to output(%r{#{HOMEBREW_CELLAR}/testball1/HEAD\-d5eb689}).to_stdout + .to output(%r{#{HOMEBREW_CELLAR}/testball1/HEAD-d5eb689}).to_stdout .and output(/Cloning into/).to_stderr .and be_a_success expect(HOMEBREW_CELLAR/"testball1/HEAD-d5eb689/foo/test").not_to be_a_file diff --git a/Library/Homebrew/test/cmd/shared_examples/args_parse.rb b/Library/Homebrew/test/cmd/shared_examples/args_parse.rb index 9cc16d455a..c9e8cc1d80 100644 --- a/Library/Homebrew/test/cmd/shared_examples/args_parse.rb +++ b/Library/Homebrew/test/cmd/shared_examples/args_parse.rb @@ -3,11 +3,12 @@ shared_examples "parseable arguments" do subject(:method_name) do |example| example.metadata[:example_group][:parent_example_group][:description] - .gsub(/^Homebrew\./, "") + .delete_prefix("Homebrew.") end let(:command_name) do - method_name.gsub(/_args$/, "").tr("_", "-") + method_name.delete_suffix("_args") + .tr("_", "-") end it "can parse arguments" do diff --git a/Library/Homebrew/test/formula_installer_bottle_spec.rb b/Library/Homebrew/test/formula_installer_bottle_spec.rb index b5e715260f..87842ff27b 100644 --- a/Library/Homebrew/test/formula_installer_bottle_spec.rb +++ b/Library/Homebrew/test/formula_installer_bottle_spec.rb @@ -4,6 +4,7 @@ require "formula" require "formula_installer" require "keg" require "tab" +require "cmd/install" require "test/support/fixtures/testball" require "test/support/fixtures/testball_bottle" @@ -49,7 +50,7 @@ describe FormulaInstaller do specify "basic bottle install" do allow(DevelopmentTools).to receive(:installed?).and_return(false) - + Homebrew.install_args.parse("testball_bottle") temporarily_install_bottle(TestballBottle.new) do |f| # Copied directly from formula_installer_spec.rb # as we expect the same behavior. diff --git a/Library/Homebrew/test/formula_installer_spec.rb b/Library/Homebrew/test/formula_installer_spec.rb index cd5856a0bf..cf15e5ba1a 100644 --- a/Library/Homebrew/test/formula_installer_spec.rb +++ b/Library/Homebrew/test/formula_installer_spec.rb @@ -4,6 +4,7 @@ require "formula" require "formula_installer" require "keg" require "tab" +require "cmd/install" require "test/support/fixtures/testball" require "test/support/fixtures/testball_bottle" require "test/support/fixtures/failball" @@ -47,8 +48,6 @@ describe FormulaInstaller do end specify "basic installation" do - ARGV << "--with-invalid_flag" # added to ensure it doesn't fail install - temporary_install(Testball.new) do |f| # Test that things made it into the Keg expect(f.prefix/"readme").to exist @@ -90,11 +89,8 @@ describe FormulaInstaller do end specify "Formula is not poured from bottle when compiler specified" do - expect(ARGV.cc).to be nil - - cc_arg = "--cc=clang" - ARGV << cc_arg - + expect(Homebrew.args.cc).to be nil + Homebrew.install_args.parse(["--cc=clang", "testball_bottle"]) temporary_install(TestballBottle.new) do |f| tab = Tab.for_formula(f) expect(tab.compiler).to eq("clang") diff --git a/Library/Homebrew/test/formula_spec.rb b/Library/Homebrew/test/formula_spec.rb index 6daf45f1ab..e198291e19 100644 --- a/Library/Homebrew/test/formula_spec.rb +++ b/Library/Homebrew/test/formula_spec.rb @@ -303,18 +303,11 @@ describe Formula do formula do url "foo" version "1.9" - head "foo" - - devel do - url "foo" - version "2.1-devel" - end end end let(:stable_prefix) { HOMEBREW_CELLAR/f.name/f.version } - let(:devel_prefix) { HOMEBREW_CELLAR/f.name/f.devel.version } let(:head_prefix) { HOMEBREW_CELLAR/f.name/f.head.version } it "is the same as #prefix by default" do @@ -326,11 +319,6 @@ describe Formula do expect(f.installed_prefix).to eq(stable_prefix) end - it "returns the devel prefix if it is installed" do - devel_prefix.mkpath - expect(f.installed_prefix).to eq(devel_prefix) - end - it "returns the head prefix if it is installed" do head_prefix.mkpath expect(f.installed_prefix).to eq(head_prefix) @@ -347,22 +335,6 @@ describe Formula do expect(f.installed_prefix).to eq(stable_prefix) end - it "returns the stable prefix if head and devel are outdated" do - head_prefix.mkpath - - tab = Tab.empty - tab.tabfile = head_prefix/Tab::FILENAME - tab.source["versions"] = { "stable" => "1.9", "devel" => "2.0" } - tab.write - - expect(f.installed_prefix).to eq(stable_prefix) - end - - it "returns the devel prefix if the active specification is :devel" do - f.active_spec = :devel - expect(f.installed_prefix).to eq(devel_prefix) - end - it "returns the head prefix if the active specification is :head" do f.active_spec = :head expect(f.installed_prefix).to eq(head_prefix) @@ -519,19 +491,12 @@ describe Formula do sha256 TEST_SHA256 head "https://brew.sh/test.git", tag: "foo" - - devel do - url "https://brew.sh/test-0.2.tbz" - mirror "https://example.org/test-0.2.tbz" - sha256 TEST_SHA256 - end end expect(f.homepage).to eq("https://brew.sh") expect(f.version).to eq(Version.create("0.1")) expect(f).to be_stable expect(f.stable.version).to eq(Version.create("0.1")) - expect(f.devel.version).to eq(Version.create("0.2")) expect(f.head.version).to eq(Version.create("HEAD")) end @@ -540,22 +505,12 @@ describe Formula do url "foo" version "1.0" revision 1 - - devel do - url "foo" - version "1.0beta" - end end expect(f.active_spec_sym).to eq(:stable) expect(f.send(:active_spec)).to eq(f.stable) expect(f.pkg_version.to_s).to eq("1.0_1") - f.active_spec = :devel - - expect(f.active_spec_sym).to eq(:devel) - expect(f.send(:active_spec)).to eq(f.devel) - expect(f.pkg_version.to_s).to eq("1.0beta_1") expect { f.active_spec = :head }.to raise_error(FormulaSpecificationError) end @@ -565,7 +520,6 @@ describe Formula do end expect(f.class.stable).to be_kind_of(SoftwareSpec) - expect(f.class.devel).to be_kind_of(SoftwareSpec) expect(f.class.head).to be_kind_of(SoftwareSpec) end @@ -574,7 +528,6 @@ describe Formula do url "foo-1.0" end - expect(f.devel).to be nil expect(f.head).to be nil end @@ -583,14 +536,9 @@ describe Formula do url "foo-1.0" depends_on "foo" - - devel do - url "foo-1.1" - end end expect(f.class.stable.deps.first.name).to eq("foo") - expect(f.class.devel.deps.first.name).to eq("foo") expect(f.class.head.deps.first.name).to eq("foo") end @@ -644,25 +592,6 @@ describe Formula do expect(f.head.version).to eq(Version.create("HEAD-5658946")) end - specify "legacy options" do - f = formula do - url "foo-1.0" - - def options - [ - ["--foo", "desc"], - ["--bar", "desc"], - ] - end - - option("baz") - end - - expect(f).to have_option_defined("foo") - expect(f).to have_option_defined("bar") - expect(f).to have_option_defined("baz") - end - specify "#desc" do f = formula do desc "a formula" @@ -673,23 +602,6 @@ describe Formula do expect(f.desc).to eq("a formula") end - specify "#test_defined?" do - f1 = formula do - url "foo-1.0" - - def test - # do nothing - end - end - - f2 = formula do - url "foo-1.0" - end - - expect(f1).to have_test_defined - expect(f2).not_to have_test_defined - end - specify "test fixtures" do f1 = formula do url "foo-1.0" @@ -704,14 +616,14 @@ describe Formula do livecheck do skip "foo" url "https://brew.sh/test/releases" - regex(/test-(\d+(?:\.\d+)+)\.tbz/) + regex(/test-v?(\d+(?:\.\d+)+)\.t/i) end end expect(f.livecheck.skip?).to be true expect(f.livecheck.skip_msg).to eq("foo") expect(f.livecheck.url).to eq("https://brew.sh/test/releases") - expect(f.livecheck.regex).to eq(/test-(\d+(?:\.\d+)+)\.tbz/) + expect(f.livecheck.regex).to eq(/test-v?(\d+(?:\.\d+)+)\.t/i) end describe "#livecheckable?" do @@ -727,12 +639,26 @@ describe Formula do f = formula do url "https://brew.sh/test-1.0.tbz" livecheck do - regex(/test-(\d+(?:.\d+)+).tbz/) + regex(/test-v?(\d+(?:\.\d+)+)\.t/i) end end expect(f.livecheckable?).to be true end + + specify "livecheck references Formula URL" do + f = formula do + homepage "https://brew.sh/test" + + url "https://brew.sh/test-1.0.tbz" + livecheck do + url :homepage + regex(/test-v?(\d+(?:\.\d+)+)\.t/i) + end + end + + expect(f.livecheck.url).to eq("https://brew.sh/test") + end end specify "dependencies" do diff --git a/Library/Homebrew/test/formula_spec_selection_spec.rb b/Library/Homebrew/test/formula_spec_selection_spec.rb index 98fb361718..bdaed0ddd1 100644 --- a/Library/Homebrew/test/formula_spec_selection_spec.rb +++ b/Library/Homebrew/test/formula_spec_selection_spec.rb @@ -7,7 +7,6 @@ describe Formula do it "selects stable by default" do f = formula do url "foo-1.0" - devel { url "foo-1.1a" } head "foo" end @@ -19,20 +18,6 @@ describe Formula do expect(f).to be_stable end - it "selects devel before HEAD" do - f = formula do - devel { url "foo-1.1a" } - head "foo" - end - - expect(f).to be_devel - end - - it "selects devel when exclusive" do - f = formula { devel { url "foo-1.1a" } } - expect(f).to be_devel - end - it "selects HEAD when exclusive" do f = formula { head "foo" } expect(f).to be_head @@ -51,49 +36,25 @@ describe Formula do it "does not set an incomplete stable spec" do f = formula do sha256 TEST_SHA256 - devel { url "foo-1.1a" } head "foo" end expect(f.stable).to be nil - expect(f).to be_devel + expect(f).to be_head end it "selects HEAD when requested" do f = formula("test", spec: :head) do url "foo-1.0" - devel { url "foo-1.1a" } head "foo" end expect(f).to be_head end - it "selects devel when requested" do - f = formula("test", spec: :devel) do - url "foo-1.0" - devel { url "foo-1.1a" } - head "foo" - end - - expect(f).to be_devel - end - - it "does not set an incomplete devel spec" do - f = formula do - url "foo-1.0" - devel { version "1.1a" } - head "foo" - end - - expect(f.devel).to be nil - expect(f).to be_stable - end - it "does not raise an error for a missing spec" do - f = formula("test", spec: :devel) do + f = formula("test", spec: :head) do url "foo-1.0" - head "foo" end expect(f).to be_stable diff --git a/Library/Homebrew/test/formula_validation_spec.rb b/Library/Homebrew/test/formula_validation_spec.rb index 0bf4a19523..c178201585 100644 --- a/Library/Homebrew/test/formula_validation_spec.rb +++ b/Library/Homebrew/test/formula_validation_spec.rb @@ -70,17 +70,6 @@ describe Formula do }.to fail_with_invalid :version end - specify "devel-only is valid" do - f = formula do - devel do - url "foo" - version "1.0" - end - end - - expect(f).to be_devel - end - specify "head-only is valid" do f = formula do head "foo" diff --git a/Library/Homebrew/test/formulary_spec.rb b/Library/Homebrew/test/formulary_spec.rb index 157b608050..5458fc6e02 100644 --- a/Library/Homebrew/test/formulary_spec.rb +++ b/Library/Homebrew/test/formulary_spec.rb @@ -234,22 +234,6 @@ describe Formulary do end end - describe "::find_with_priority" do - let(:core_path) { CoreTap.new.formula_dir/"#{formula_name}.rb" } - let(:tap) { Tap.new("homebrew", "foo") } - let(:tap_path) { tap.path/"#{formula_name}.rb" } - - before do - core_path.write formula_content - tap_path.write formula_content - end - - it "prioritizes core Formulae" do - formula = described_class.find_with_priority(formula_name) - expect(formula.path).to eq(core_path) - end - end - describe "::core_path" do it "returns the path to a Formula in the core tap" do name = "foo-bar" diff --git a/Library/Homebrew/test/livecheck_spec.rb b/Library/Homebrew/test/livecheck_spec.rb index f975548cda..4a326066d3 100644 --- a/Library/Homebrew/test/livecheck_spec.rb +++ b/Library/Homebrew/test/livecheck_spec.rb @@ -1,9 +1,15 @@ # frozen_string_literal: true +require "formula" require "livecheck" describe Livecheck do - subject(:livecheckable) { described_class.new } + let(:f) do + formula do + url "https://brew.sh/test-0.1.tbz" + end + end + let(:livecheckable) { described_class.new(f) } describe "#regex" do it "returns nil if unset" do diff --git a/Library/Homebrew/test/patch_spec.rb b/Library/Homebrew/test/patch_spec.rb index 463894ff4c..fff1fc48b2 100644 --- a/Library/Homebrew/test/patch_spec.rb +++ b/Library/Homebrew/test/patch_spec.rb @@ -74,74 +74,6 @@ describe Patch do expect(subject.patch_files.count).to eq(7) end end - - describe "#normalize_legacy_patches" do - it "can create a patch from a single string" do - patches = described_class.normalize_legacy_patches("https://brew.sh/patch.diff") - expect(patches.length).to eq(1) - expect(patches.first.strip).to eq(:p1) - end - - it "can create patches from an array" do - patches = described_class.normalize_legacy_patches( - %w[https://brew.sh/patch1.diff https://brew.sh/patch2.diff], - ) - - expect(patches.length).to eq(2) - expect(patches.first.strip).to eq(:p1) - expect(patches.second.strip).to eq(:p1) - end - - it "can create patches from a :p0 hash" do - patches = described_class.normalize_legacy_patches( - p0: "https://brew.sh/patch.diff", - ) - - expect(patches.length).to eq(1) - expect(patches.first.strip).to eq(:p0) - end - - it "can create patches from a :p1 hash" do - patches = described_class.normalize_legacy_patches( - p1: "https://brew.sh/patch.diff", - ) - - expect(patches.length).to eq(1) - expect(patches.first.strip).to eq(:p1) - end - - it "can create patches from a mixed hash" do - patches = described_class.normalize_legacy_patches( - p1: "https://brew.sh/patch1.diff", - p0: "https://brew.sh/patch0.diff", - ) - - expect(patches.length).to eq(2) - expect(patches.count { |p| p.strip == :p0 }).to eq(1) - expect(patches.count { |p| p.strip == :p1 }).to eq(1) - end - - it "can create patches from a mixed hash with array" do - patches = described_class.normalize_legacy_patches( - p1: [ - "https://brew.sh/patch10.diff", - "https://brew.sh/patch11.diff", - ], - p0: [ - "https://brew.sh/patch00.diff", - "https://brew.sh/patch01.diff", - ], - ) - - expect(patches.length).to eq(4) - expect(patches.count { |p| p.strip == :p0 }).to eq(2) - expect(patches.count { |p| p.strip == :p1 }).to eq(2) - end - - it "returns an empty array if given nil" do - expect(described_class.normalize_legacy_patches(nil)).to be_empty - end - end end describe EmbeddedPatch do diff --git a/Library/Homebrew/test/patching_spec.rb b/Library/Homebrew/test/patching_spec.rb index b921bb5d76..ffdf1027dc 100644 --- a/Library/Homebrew/test/patching_spec.rb +++ b/Library/Homebrew/test/patching_spec.rb @@ -65,16 +65,6 @@ describe "patching" do end end - specify "single_patch" do - expect( - formula do - def patches - PATCH_URL_A - end - end, - ).to be_patched - end - specify "single_patch_dsl" do expect( formula do @@ -199,46 +189,6 @@ describe "patching" do ).to be_patched end - specify "patch_p0" do - expect( - formula do - def patches - { p0: PATCH_URL_B } - end - end, - ).to be_patched - end - - specify "patch_array" do - expect( - formula do - def patches - [PATCH_URL_A] - end - end, - ).to be_patched - end - - specify "patch_hash" do - expect( - formula do - def patches - { p1: PATCH_URL_A } - end - end, - ).to be_patched - end - - specify "patch_hash_array" do - expect( - formula do - def patches - { p1: [PATCH_URL_A] } - end - end, - ).to be_patched - end - specify "patch_string" do expect(formula { patch PATCH_A_CONTENTS }).to be_patched end @@ -247,26 +197,6 @@ describe "patching" do expect(formula { patch :p0, PATCH_B_CONTENTS }).to be_patched end - specify "patch_data_constant" do - expect( - formula("test", path: Pathname.new(__FILE__).expand_path) do - def patches - :DATA - end - end, - ).to be_patched - end - - specify "single_patch_missing_apply_fail" do - expect( - formula do - def patches - TESTBALL_PATCHES_URL - end - end, - ).to miss_apply - end - specify "single_patch_dsl_missing_apply_fail" do expect( formula do diff --git a/Library/Homebrew/test/rubocops/components_order_spec.rb b/Library/Homebrew/test/rubocops/components_order_spec.rb index 821cbd64a1..53e04e01bf 100644 --- a/Library/Homebrew/test/rubocops/components_order_spec.rb +++ b/Library/Homebrew/test/rubocops/components_order_spec.rb @@ -90,6 +90,47 @@ describe RuboCop::Cop::FormulaAudit::ComponentsOrder do end RUBY end + + it "the on_macos block is not after uses_from_macos" do + expect_offense(<<~RUBY) + class Foo < Formula + url "https://brew.sh/foo-1.0.tgz" + on_macos do + depends_on "readline" + end + uses_from_macos "bar" + ^^^^^^^^^^^^^^^^^^^^^ `uses_from_macos` (line 6) should be put before `on_macos` (line 3) + end + RUBY + end + + it "the on_linux block is not after uses_from_macos" do + expect_offense(<<~RUBY) + class Foo < Formula + url "https://brew.sh/foo-1.0.tgz" + on_linux do + depends_on "readline" + end + uses_from_macos "bar" + ^^^^^^^^^^^^^^^^^^^^^ `uses_from_macos` (line 6) should be put before `on_linux` (line 3) + end + RUBY + end + + it "the on_linux block is not after the on_macos block" do + expect_offense(<<~RUBY) + class Foo < Formula + url "https://brew.sh/foo-1.0.tgz" + on_linux do + depends_on "vim" + end + on_macos do + ^^^^^^^^^^^ `on_macos` (line 6) should be put before `on_linux` (line 3) + depends_on "readline" + end + end + RUBY + end end context "When auditing formula components order with autocorrect" do @@ -141,4 +182,301 @@ describe RuboCop::Cop::FormulaAudit::ComponentsOrder do expect(corrected_source).to eq(correct_source) end end + + context "no on_os_block" do + it "does not fail when there is no on_os block" do + expect_no_offenses(<<~RUBY) + class Foo < Formula + homepage "https://brew.sh" + + depends_on "pkg-config" => :build + + def install + end + end + RUBY + end + end + + context "on_os_block" do + it "correctly uses on_macos and on_linux blocks" do + expect_no_offenses(<<~RUBY) + class Foo < Formula + homepage "https://brew.sh" + + depends_on "pkg-config" => :build + + uses_from_macos "libxml2" + + on_macos do + depends_on "perl" + + resource "resource1" do + url "https://brew.sh/resource1.tar.gz" + sha256 "a2f5650770e1c87fb335af19a9b7eb73fc05ccf22144eb68db7d00cd2bcb0902" + + patch do + url "https://raw.githubusercontent.com/Homebrew/formula-patches/0ae366e6/patch3.diff" + sha256 "89fa3c95c329ec326e2e76493471a7a974c673792725059ef121e6f9efb05bf4" + end + end + + resource "resource2" do + url "https://brew.sh/resource2.tar.gz" + sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35" + end + + patch do + url "https://raw.githubusercontent.com/Homebrew/formula-patches/0ae366e6/patch1.diff" + sha256 "89fa3c95c329ec326e2e76493471a7a974c673792725059ef121e6f9efb05bf4" + end + + patch do + url "https://raw.githubusercontent.com/Homebrew/formula-patches/0ae366e6/patch2.diff" + sha256 "89fa3c95c329ec326e2e76493471a7a974c673792725059ef121e6f9efb05bf4" + end + end + + on_linux do + depends_on "readline" + end + + def install + end + end + RUBY + end + end + + context "on_macos_block" do + it "correctly uses as single on_macos block" do + expect_no_offenses(<<~RUBY) + class Foo < Formula + homepage "https://brew.sh" + + on_macos do + depends_on "readline" + end + + def install + end + end + RUBY + end + end + + context "on_linux_block" do + it "correctly uses as single on_linux block" do + expect_no_offenses(<<~RUBY) + class Foo < Formula + homepage "https://brew.sh" + + on_linux do + depends_on "readline" + end + + def install + end + end + RUBY + end + end + + it "there can only be one on_macos block" do + expect_offense(<<~RUBY) + class Foo < Formula + url "https://brew.sh/foo-1.0.tgz" + on_macos do + depends_on "readline" + end + + on_macos do + ^^^^^^^^^^^ there can only be one `on_macos` block in a formula. + depends_on "foo" + end + end + RUBY + end + + it "there can only be one on_linux block" do + expect_offense(<<~RUBY) + class Foo < Formula + url "https://brew.sh/foo-1.0.tgz" + on_linux do + depends_on "readline" + end + + on_linux do + ^^^^^^^^^^^ there can only be one `on_linux` block in a formula. + depends_on "foo" + end + end + RUBY + end + + it "the on_macos block can only contain depends_on, patch and resource nodes" do + expect_offense(<<~RUBY) + class Foo < Formula + url "https://brew.sh/foo-1.0.tgz" + on_macos do + ^^^^^^^^^^^ `on_macos` can only include `depends_on`, `patch` and `resource` nodes. + depends_on "readline" + uses_from_macos "ncurses" + end + end + RUBY + end + + it "the on_linux block can only contain depends_on, patch and resource nodes" do + expect_offense(<<~RUBY) + class Foo < Formula + url "https://brew.sh/foo-1.0.tgz" + on_linux do + ^^^^^^^^^^^ `on_linux` can only include `depends_on`, `patch` and `resource` nodes. + depends_on "readline" + uses_from_macos "ncurses" + end + end + RUBY + end + + context "resource" do + it "correctly uses an on_macos and on_linux block" do + expect_no_offenses(<<~RUBY) + class Foo < Formula + homepage "https://brew.sh" + + resource do + on_macos do + url "https://brew.sh/resource1.tar.gz" + sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35" + end + + on_linux do + url "https://brew.sh/resource2.tar.gz" + sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35" + end + end + end + RUBY + end + + it "there are two on_macos blocks, which is not allowed" do + expect_offense(<<~RUBY) + class Foo < Formula + url "https://brew.sh/foo-1.0.tgz" + + resource do + ^^^^^^^^^^^ there can only be one `on_macos` block in a resource block. + on_macos do + url "https://brew.sh/resource1.tar.gz" + sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35" + end + + on_macos do + url "https://brew.sh/resource2.tar.gz" + sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35" + end + end + end + RUBY + end + + it "there are two on_linux blocks, which is not allowed" do + expect_offense(<<~RUBY) + class Foo < Formula + url "https://brew.sh/foo-1.0.tgz" + + resource do + ^^^^^^^^^^^ there can only be one `on_linux` block in a resource block. + on_linux do + url "https://brew.sh/resource1.tar.gz" + sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35" + end + + on_linux do + url "https://brew.sh/resource2.tar.gz" + sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35" + end + end + end + RUBY + end + + it "there is a on_macos block but no on_linux block" do + expect_offense(<<~RUBY) + class Foo < Formula + url "https://brew.sh/foo-1.0.tgz" + + resource do + ^^^^^^^^^^^ you need to define an `on_linux` block within your resource block. + on_macos do + url "https://brew.sh/resource1.tar.gz" + sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35" + end + end + end + RUBY + end + + it "there is a on_linux block but no on_macos block" do + expect_offense(<<~RUBY) + class Foo < Formula + url "https://brew.sh/foo-1.0.tgz" + + resource do + ^^^^^^^^^^^ you need to define an `on_macos` block within your resource block. + on_linux do + url "https://brew.sh/resource1.tar.gz" + sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35" + end + end + end + RUBY + end + + it "the content of the on_macos block is wrong in a resource block" do + expect_offense(<<~RUBY) + class Foo < Formula + url "https://brew.sh/foo-1.0.tgz" + + resource do + ^^^^^^^^^^^ only an url and a sha256 (in the right order) are allowed in a `on_macos` block within a resource block. + on_macos do + sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35" + url "https://brew.sh/resource2.tar.gz" + end + + on_linux do + url "https://brew.sh/resource2.tar.gz" + sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35" + end + end + end + RUBY + end + + it "the content of the on_linux block is wrong in a resource block" do + expect_offense(<<~RUBY) + class Foo < Formula + url "https://brew.sh/foo-1.0.tgz" + + resource do + ^^^^^^^^^^^ only an url and a sha256 (in the right order) are allowed in a `on_linux` block within a resource block. + on_macos do + url "https://brew.sh/resource2.tar.gz" + sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35" + end + + on_linux do + sha256 "586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35" + url "https://brew.sh/resource2.tar.gz" + end + end + end + RUBY + end + + include_examples "formulae exist", described_class::COMPONENT_WHITELIST + end end diff --git a/Library/Homebrew/test/rubocops/homepage_spec.rb b/Library/Homebrew/test/rubocops/homepage_spec.rb index cfeff7f5bb..033cd0a0bb 100644 --- a/Library/Homebrew/test/rubocops/homepage_spec.rb +++ b/Library/Homebrew/test/rubocops/homepage_spec.rb @@ -73,7 +73,7 @@ describe RuboCop::Cop::FormulaAudit::Homepage do RUBY inspect_source(source) - if homepage.match?(%r{http:\/\/www\.freedesktop\.org}) + if homepage.match?(%r{http://www\.freedesktop\.org}) if homepage.match?(/Software/) expected_offenses = [{ message: "#{homepage} should be styled " \ "`https://wiki.freedesktop.org/www/Software/project_name`", @@ -89,7 +89,7 @@ describe RuboCop::Cop::FormulaAudit::Homepage do column: 2, source: source }] end - elsif homepage.match?(%r{https:\/\/code\.google\.com}) + elsif homepage.match?(%r{https://code\.google\.com}) expected_offenses = [{ message: "#{homepage} should end with a slash", severity: :convention, line: 2, diff --git a/Library/Homebrew/test/rubocops/patches_spec.rb b/Library/Homebrew/test/rubocops/patches_spec.rb index d2ed6ce03a..f2a0fc25a7 100644 --- a/Library/Homebrew/test/rubocops/patches_spec.rb +++ b/Library/Homebrew/test/rubocops/patches_spec.rb @@ -68,7 +68,7 @@ describe RuboCop::Cop::FormulaAudit::Patches do line: 5, column: 33, source: source }] - elsif patch_url.match?(%r{^http://trac\.macports\.org}) + elsif patch_url.start_with?("http://trac.macports.org") [{ message: <<~EOS.chomp, Patches from MacPorts Trac should be https://, not http: @@ -78,7 +78,7 @@ describe RuboCop::Cop::FormulaAudit::Patches do line: 5, column: 5, source: source }] - elsif patch_url.match?(%r{^http://bugs\.debian\.org}) + elsif patch_url.start_with?("http://bugs.debian.org") [{ message: <<~EOS.chomp, Patches from Debian should be https://, not http: @@ -205,7 +205,7 @@ describe RuboCop::Cop::FormulaAudit::Patches do line: 5, column: 37, source: source }] - elsif patch_url.match?(%r{^http://trac\.macports\.org}) + elsif patch_url.start_with?("http://trac.macports.org") [{ message: <<~EOS.chomp, Patches from MacPorts Trac should be https://, not http: @@ -215,7 +215,7 @@ describe RuboCop::Cop::FormulaAudit::Patches do line: 5, column: 9, source: source }] - elsif patch_url.match?(%r{^http://bugs\.debian\.org}) + elsif patch_url.start_with?("http://bugs.debian.org") [{ message: <<~EOS.chomp, Patches from Debian should be https://, not http: diff --git a/Library/Homebrew/test/rubocops/urls_spec.rb b/Library/Homebrew/test/rubocops/urls_spec.rb index c3a547f435..24c33cf60a 100644 --- a/Library/Homebrew/test/rubocops/urls_spec.rb +++ b/Library/Homebrew/test/rubocops/urls_spec.rb @@ -159,6 +159,26 @@ describe RuboCop::Cop::FormulaAudit::Urls do "not a source archive; homebrew/core is source-only.", "col" => 2, "formula_tap" => "homebrew-core", + }, { + "url" => "cvs://brew.sh/foo/bar", + "msg" => "Use of the cvs:// scheme is deprecated, pass `:using => :cvs` instead", + "col" => 2, + }, { + "url" => "bzr://brew.sh/foo/bar", + "msg" => "Use of the bzr:// scheme is deprecated, pass `:using => :bzr` instead", + "col" => 2, + }, { + "url" => "hg://brew.sh/foo/bar", + "msg" => "Use of the hg:// scheme is deprecated, pass `:using => :hg` instead", + "col" => 2, + }, { + "url" => "fossil://brew.sh/foo/bar", + "msg" => "Use of the fossil:// scheme is deprecated, pass `:using => :fossil` instead", + "col" => 2, + }, { + "url" => "svn+http://brew.sh/foo/bar", + "msg" => "Use of the svn+http:// scheme is deprecated, pass `:using => :svn` instead", + "col" => 2, }] } diff --git a/Library/Homebrew/test/searchable_spec.rb b/Library/Homebrew/test/searchable_spec.rb index aaf88c2eaf..6fdb4557d7 100644 --- a/Library/Homebrew/test/searchable_spec.rb +++ b/Library/Homebrew/test/searchable_spec.rb @@ -19,7 +19,7 @@ describe Searchable do context "when given a regex" do it "does not simplify strings" do - expect(subject.search(/with\-dashes/)).to eq ["with-dashes"] + expect(subject.search(/with-dashes/)).to eq ["with-dashes"] end end diff --git a/Library/Homebrew/test/spec_helper.rb b/Library/Homebrew/test/spec_helper.rb index f40e98cb25..fc3fbd8387 100644 --- a/Library/Homebrew/test/spec_helper.rb +++ b/Library/Homebrew/test/spec_helper.rb @@ -172,7 +172,6 @@ RSpec.configure do |config| @__files_before_test = find_files - @__argv = ARGV.dup @__env = ENV.to_hash # dup doesn't work on ENV @__stdout = $stdout.clone @@ -187,7 +186,6 @@ RSpec.configure do |config| rescue SystemExit => e raise "Unexpected exit with status #{e.status}." ensure - ARGV.replace(@__argv) ENV.replace(@__env) $stdout.reopen(@__stdout) 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 3f4468a3a7..cbc933817d 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 @@ -176,8 +176,8 @@ RSpec.shared_context "integration test" do setup_test_formula(name, content) fi = FormulaInstaller.new(Formula[name]) fi.build_bottle = build_bottle - fi.fetch fi.prelude + fi.fetch fi.install fi.finish end diff --git a/Library/Homebrew/test/utils/bottles/collector_spec.rb b/Library/Homebrew/test/utils/bottles/collector_spec.rb index 91a1a25b34..5df7bd45a5 100644 --- a/Library/Homebrew/test/utils/bottles/collector_spec.rb +++ b/Library/Homebrew/test/utils/bottles/collector_spec.rb @@ -35,7 +35,7 @@ describe Utils::Bottles::Collector do end it "ignores HOMEBREW_SKIP_OR_LATER_BOTTLES on release versions", :needs_macos do - allow(ARGV).to receive(:skip_or_later_bottles?).and_return(true) + allow(Homebrew::EnvConfig).to receive(:skip_or_later_bottles?).and_return(true) allow(OS::Mac).to receive(:prerelease?).and_return(false) subject[:mavericks] = "foo" expect(subject.send(:find_matching_tag, :mavericks)).to eq(:mavericks) diff --git a/Library/Homebrew/test/utils_spec.rb b/Library/Homebrew/test/utils_spec.rb index d27290ef47..977852b6b2 100644 --- a/Library/Homebrew/test/utils_spec.rb +++ b/Library/Homebrew/test/utils_spec.rb @@ -253,7 +253,7 @@ describe "globally-scoped helper methods" do ) }.to raise_error( MethodDeprecatedError, - %r{method.*replacement.*homebrew/core.*\/Taps\/homebrew\/homebrew-core\/}m, + %r{method.*replacement.*homebrew/core.*/Taps/homebrew/homebrew-core/}m, ) end end diff --git a/Library/Homebrew/utils.rb b/Library/Homebrew/utils.rb index d4e8fa2536..3ddf50c79c 100644 --- a/Library/Homebrew/utils.rb +++ b/Library/Homebrew/utils.rb @@ -96,7 +96,7 @@ module Kernel end def odebug(title, *sput) - return unless ARGV.debug? + return unless Homebrew.args.debug? puts Formatter.headline(title, color: :magenta) puts sput unless sput.empty? @@ -168,7 +168,7 @@ module Kernel tap = Tap.fetch(match[:user], match[:repo]) tap_message = +"\nPlease report this issue to the #{tap} tap (not Homebrew/brew or Homebrew/core)" tap_message += ", or even better, submit a PR to fix it" if replacement - tap_message << ":\n #{line.sub(/^(.*\:\d+)\:.*$/, '\1')}\n\n" + tap_message << ":\n #{line.sub(/^(.*:\d+):.*$/, '\1')}\n\n" break end @@ -437,13 +437,13 @@ module Kernel n_back_bytes = max_bytes_in - n_front_bytes if n_front_bytes.zero? front = bytes[1..0] - back = bytes[-max_bytes_in..-1] + back = bytes[-max_bytes_in..] elsif n_back_bytes.zero? front = bytes[0..(max_bytes_in - 1)] back = bytes[1..0] else front = bytes[0..(n_front_bytes - 1)] - back = bytes[-n_back_bytes..-1] + back = bytes[-n_back_bytes..] end out = front + glue_bytes + back out.force_encoding("UTF-8") diff --git a/Library/Homebrew/utils/analytics.rb b/Library/Homebrew/utils/analytics.rb index c3a8bc03c9..3c27ae4e9d 100644 --- a/Library/Homebrew/utils/analytics.rb +++ b/Library/Homebrew/utils/analytics.rb @@ -119,7 +119,7 @@ module Utils def output(filter: nil) days = Homebrew.args.days || "30" category = Homebrew.args.category || "install" - json = formulae_api_json("analytics/#{category}/#{days}d.json") + json = formulae_brew_sh_json("analytics/#{category}/#{days}d.json") return if json.blank? || json["items"].blank? os_version = category == "os-version" @@ -147,10 +147,7 @@ module Utils table_output(category, days, results, os_version: os_version, cask_install: cask_install) end - def formula_output(f) - json = formulae_api_json("#{formula_path}/#{f}.json") - return if json.blank? || json["analytics"].blank? - + def get_analytics(json) full_analytics = Homebrew.args.analytics? || Homebrew.args.verbose? ohai "Analytics" @@ -179,6 +176,20 @@ module Utils end end + def formula_output(f) + json = formulae_brew_sh_json("#{formula_path}/#{f}.json") + return if json.blank? || json["analytics"].blank? + + get_analytics(json) + end + + def cask_output(cask) + json = formulae_brew_sh_json("#{cask_path}/#{cask}.json") + return if json.blank? || json["analytics"].blank? + + get_analytics(json) + end + def custom_prefix_label "custom-prefix" end @@ -307,7 +318,7 @@ module Utils end end - def formulae_api_json(endpoint) + def formulae_brew_sh_json(endpoint) return if Homebrew::EnvConfig.no_analytics? || Homebrew::EnvConfig.no_github_api? output, = curl_output("--max-time", "5", @@ -336,6 +347,10 @@ module Utils "analytics" end alias generic_analytics_path analytics_path + + def cask_path + "cask" + end end end end diff --git a/Library/Homebrew/utils/bottles.rb b/Library/Homebrew/utils/bottles.rb index c886ae1c2f..250cb00126 100644 --- a/Library/Homebrew/utils/bottles.rb +++ b/Library/Homebrew/utils/bottles.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require "tab" -require "extend/ARGV" module Utils class Bottles diff --git a/Library/Homebrew/utils/curl.rb b/Library/Homebrew/utils/curl.rb index 25d5e2235b..7503e16822 100644 --- a/Library/Homebrew/utils/curl.rb +++ b/Library/Homebrew/utils/curl.rb @@ -196,7 +196,7 @@ def curl_http_content_headers_and_checksum(url, hash_needed: false, user_agent: status_code = :unknown while status_code == :unknown || status_code.to_s.start_with?("3") headers, _, output = output.partition("\r\n\r\n") - status_code = headers[%r{HTTP\/.* (\d+)}, 1] + status_code = headers[%r{HTTP/.* (\d+)}, 1] final_url = headers[/^Location:\s*(.*)$/i, 1]&.chomp end @@ -208,7 +208,7 @@ def curl_http_content_headers_and_checksum(url, hash_needed: false, user_agent: url: url, final_url: final_url, status: status_code, - etag: headers[%r{ETag: ([wW]\/)?"(([^"]|\\")*)"}, 2], + etag: headers[%r{ETag: ([wW]/)?"(([^"]|\\")*)"}, 2], content_length: headers[/Content-Length: (\d+)/, 1], file_hash: output_hash, file: output, diff --git a/Library/Homebrew/utils/gems.rb b/Library/Homebrew/utils/gems.rb index 167383f0df..8fba9b3096 100644 --- a/Library/Homebrew/utils/gems.rb +++ b/Library/Homebrew/utils/gems.rb @@ -39,17 +39,18 @@ module Homebrew end def setup_gem_environment!(gem_home: nil, gem_bindir: nil) + require "rubygems" + # Match where our bundler gems are. gem_home ||= "#{ENV["HOMEBREW_LIBRARY"]}/Homebrew/vendor/bundle/ruby/#{RbConfig::CONFIG["ruby_version"]}" ENV["GEM_HOME"] = gem_home - ENV["GEM_PATH"] = ENV["GEM_HOME"] + ENV["GEM_PATH"] = "#{ENV["GEM_HOME"]}:#{Gem.default_dir}" # Set TMPDIR so Xcode's `make` doesn't fall back to `/var/tmp/`, # which may be not user-writable. ENV["TMPDIR"] = ENV["HOMEBREW_TEMP"] # Make RubyGems notice environment changes. - require "rubygems" Gem.clear_paths Gem::Specification.reset @@ -65,12 +66,10 @@ module Homebrew setup_gem_environment! if setup_gem_environment return unless Gem::Specification.find_all_by_name(name, version).empty? - # Shell out to `gem` to avoid RubyGems requires for e.g. loading JSON. ohai_if_defined "Installing '#{name}' gem" - install_args = %W[--no-document #{name}] - install_args << "--version" << version if version - return if system "#{ruby_bindir}/gem", "install", *install_args - + # document: [] , is equivalent to --no-document + Gem.install name, version, document: [] + rescue Gem::UnsatisfiableDependencyError odie_if_defined "failed to install the '#{name}' gem." end diff --git a/Library/Homebrew/utils/github.rb b/Library/Homebrew/utils/github.rb index 1768ed6b56..556089c091 100644 --- a/Library/Homebrew/utils/github.rb +++ b/Library/Homebrew/utils/github.rb @@ -14,8 +14,6 @@ module GitHub ALL_SCOPES_URL = Formatter.url( "https://github.com/settings/tokens/new?scopes=#{ALL_SCOPES.join(",")}&description=Homebrew", ).freeze - PR_ENV_KEY = "HOMEBREW_NEW_FORMULA_PULL_REQUEST_URL" - PR_ENV = ENV[PR_ENV_KEY] class Error < RuntimeError attr_reader :github_message @@ -396,37 +394,6 @@ module GitHub open_api(uri) { |json| json.fetch("items", []) } end - def create_issue_comment(body) - return false unless PR_ENV - - _, user, repo, pr = *PR_ENV.match(HOMEBREW_PULL_OR_COMMIT_URL_REGEX) - if !user || !repo || !pr - opoo <<-EOS.undent - #{PR_ENV_KEY} set but regex matched: - user: #{user.inspect}, repo: #{repo.inspect}, pr: #{pr.inspect} - EOS - return false - end - - url = "#{API_URL}/repos/#{user}/#{repo}/issues/#{pr}/comments" - data = { "body" => body } - if issue_comment_exists?(user, repo, pr, body) - ohai "Skipping: identical comment exists on #{PR_ENV}" - return true - end - - scopes = CREATE_ISSUE_FORK_OR_PR_SCOPES - open_api(url, data: data, scopes: scopes) - end - - def issue_comment_exists?(user, repo, pr, body) - url = "#{API_URL}/repos/#{user}/#{repo}/issues/#{pr}/comments" - comments = open_api(url) - return unless comments - - comments.any? { |comment| comment["body"].eql?(body) } - end - def dispatch_event(user, repo, event, **payload) url = "#{API_URL}/repos/#{user}/#{repo}/dispatches" open_api(url, data: { event_type: event, client_payload: payload }, @@ -440,8 +407,9 @@ module GitHub pr_payload = open_api("#{base_url}/pulls/#{pr}", scopes: scopes) pr_sha = pr_payload["head"]["sha"] pr_branch = URI.encode_www_form_component(pr_payload["head"]["ref"]) + parameters = "event=pull_request&branch=#{pr_branch}" - workflow = open_api("#{base_url}/actions/workflows/#{workflow_id}/runs?branch=#{pr_branch}", scopes: scopes) + workflow = open_api("#{base_url}/actions/workflows/#{workflow_id}/runs?#{parameters}", scopes: scopes) workflow_run = workflow["workflow_runs"].select do |run| run["head_sha"] == pr_sha end diff --git a/Library/Homebrew/utils/notability.rb b/Library/Homebrew/utils/notability.rb new file mode 100644 index 0000000000..ef6099844d --- /dev/null +++ b/Library/Homebrew/utils/notability.rb @@ -0,0 +1,75 @@ +# frozen_string_literal: true + +require "utils/curl" + +module SharedAudits + module_function + + def github(user, repo) + begin + metadata = GitHub.repository(user, repo) + rescue GitHub::HTTPNotFoundError + return + end + + return if metadata.nil? + + return "GitHub fork (not canonical repository)" if metadata["fork"] + if (metadata["forks_count"] < 30) && (metadata["subscribers_count"] < 30) && + (metadata["stargazers_count"] < 75) + return "GitHub repository not notable enough (<30 forks, <30 watchers and <75 stars)" + end + + return if Date.parse(metadata["created_at"]) <= (Date.today - 30) + + "GitHub repository too new (<30 days old)" + end + + def gitlab(user, repo) + out, _, status= curl_output("--request", "GET", "https://gitlab.com/api/v4/projects/#{user}%2F#{repo}") + return unless status.success? + + metadata = JSON.parse(out) + return if metadata.nil? + + return "GitLab fork (not canonical repository)" if metadata["fork"] + if (metadata["forks_count"] < 30) && (metadata["star_count"] < 75) + return "GitLab repository not notable enough (<30 forks and <75 stars)" + end + + return if Date.parse(metadata["created_at"]) <= (Date.today - 30) + + "GitLab repository too new (<30 days old)" + end + + def bitbucket(user, repo) + api_url = "https://api.bitbucket.org/2.0/repositories/#{user}/#{repo}" + out, _, status= curl_output("--request", "GET", api_url) + return unless status.success? + + metadata = JSON.parse(out) + return if metadata.nil? + + return "Uses deprecated mercurial support in Bitbucket" if metadata["scm"] == "hg" + + return "Bitbucket fork (not canonical repository)" unless metadata["parent"].nil? + + return "Bitbucket repository too new (<30 days old)" if Date.parse(metadata["created_on"]) >= (Date.today - 30) + + forks_out, _, forks_status= curl_output("--request", "GET", "#{api_url}/forks") + return unless forks_status.success? + + watcher_out, _, watcher_status= curl_output("--request", "GET", "#{api_url}/watchers") + return unless watcher_status.success? + + forks_metadata = JSON.parse(forks_out) + return if forks_metadata.nil? + + watcher_metadata = JSON.parse(watcher_out) + return if watcher_metadata.nil? + + return if (forks_metadata["size"] < 30) && (watcher_metadata["size"] < 75) + + "Bitbucket repository not notable enough (<30 forks and <75 watchers)" + end +end diff --git a/Library/Homebrew/utils/ruby.sh b/Library/Homebrew/utils/ruby.sh index bd36c4d7d7..1792359767 100644 --- a/Library/Homebrew/utils/ruby.sh +++ b/Library/Homebrew/utils/ruby.sh @@ -1,82 +1,93 @@ +test-ruby () { + [[ ! -x $1 ]] && { echo "false"; return 1; } + "$1" --enable-frozen-string-literal --disable=gems,did_you_mean,rubyopt -rrubygems -e \ + "puts Gem::Version.new(RUBY_VERSION.to_s.dup).to_s.split('.').first(2) == \ + Gem::Version.new('$required_ruby_version').to_s.split('.').first(2)" 2>/dev/null +} + setup-ruby-path() { local vendor_dir - local vendor_ruby_current_version local vendor_ruby_path + local vendor_ruby_latest_version + local vendor_ruby_current_version local usable_ruby_version # When bumping check if HOMEBREW_MACOS_SYSTEM_RUBY_NEW_ENOUGH (in brew.sh) # also needs to be changed. local required_ruby_version="2.6" - - vendor_dir="$HOMEBREW_LIBRARY/Homebrew/vendor" - vendor_ruby_current_version="$vendor_dir/portable-ruby/current" - vendor_ruby_path="$vendor_ruby_current_version/bin/ruby" - - if [[ -z "$HOMEBREW_DEVELOPER" ]] - then - unset HOMEBREW_RUBY_PATH - fi - - if [[ -z "$HOMEBREW_RUBY_PATH" && "$HOMEBREW_COMMAND" != "vendor-install" ]] - then - if [[ -x "$vendor_ruby_path" ]] - then - HOMEBREW_RUBY_PATH="$vendor_ruby_path" - - if [[ $(readlink "$vendor_ruby_current_version") != "$(<"$vendor_dir/portable-ruby-version")" ]] - then - if ! brew vendor-install ruby - then - if [[ -n "$HOMEBREW_MACOS" ]] - then - odie "Failed to upgrade Homebrew Portable Ruby!" - else - odie <<-EOS -Failed to upgrade Homebrew Portable Ruby! + local ruby_exec + local advice=" If there's no Homebrew Portable Ruby available for your processor: - install Ruby $required_ruby_version with your system package manager (or rbenv/ruby-build) - make it first in your PATH - try again -EOS - fi - fi - fi - else - if [[ -n "$HOMEBREW_MACOS" ]] - then - HOMEBREW_RUBY_PATH="/System/Library/Frameworks/Ruby.framework/Versions/Current/usr/bin/ruby" - else - HOMEBREW_RUBY_PATH="$(type -P ruby)" - fi +" - if [[ -n "$HOMEBREW_MACOS_SYSTEM_RUBY_NEW_ENOUGH" ]] - then - usable_ruby_version="true" - elif [[ -n "$HOMEBREW_RUBY_PATH" && -z "$HOMEBREW_FORCE_VENDOR_RUBY" ]] - then - usable_ruby_version="$("$HOMEBREW_RUBY_PATH" --enable-frozen-string-literal --disable=gems,did_you_mean,rubyopt -rrubygems -e "puts Gem::Version.new(RUBY_VERSION.to_s.dup).to_s.split('.').first(2) == Gem::Version.new('$required_ruby_version').to_s.split('.').first(2)")" - fi + vendor_dir="$HOMEBREW_LIBRARY/Homebrew/vendor" + vendor_ruby_path="$vendor_dir/portable-ruby/current/bin/ruby" + vendor_ruby_latest_version=$(<"$vendor_dir/portable-ruby-version") + vendor_ruby_current_version=$(readlink "$vendor_dir/portable-ruby/current") - if [[ -z "$HOMEBREW_RUBY_PATH" || -n "$HOMEBREW_FORCE_VENDOR_RUBY" || "$usable_ruby_version" != "true" ]] + unset HOMEBREW_RUBY_PATH + + if [[ "$HOMEBREW_COMMAND" == "vendor-install" ]] + then + return 0 + fi + + if [[ -x "$vendor_ruby_path" ]] + then + HOMEBREW_RUBY_PATH="$vendor_ruby_path" + if [[ $vendor_ruby_current_version != $vendor_ruby_latest_version ]] + then + if ! brew vendor-install ruby then - brew vendor-install ruby - if [[ ! -x "$vendor_ruby_path" ]] + if [[ -n "$HOMEBREW_MACOS" ]] then - if [[ -n "$HOMEBREW_MACOS" ]] - then - odie "Failed to install Homebrew Portable Ruby (and your system version is too old)!" - else - odie <<-EOS -Failed to install Homebrew Portable Ruby and cannot find another Ruby $required_ruby_version! -If there's no Homebrew Portable Ruby available for your processor: -- install $required_ruby_version with your system package manager (or rbenv/ruby-build) -- make it first in your PATH -- try again -EOS - fi + odie "Failed to upgrade Homebrew Portable Ruby!" + else + odie "Failed to upgrade Homebrew Portable Ruby!$advice" fi - HOMEBREW_RUBY_PATH="$vendor_ruby_path" fi fi + else + if [[ -n "$HOMEBREW_MACOS" ]] + then + HOMEBREW_RUBY_PATH="/System/Library/Frameworks/Ruby.framework/Versions/Current/usr/bin/ruby" + else + IFS=$'\n' # Do word splitting on new lines only + for ruby_exec in $(which -a ruby) $(PATH=$HOMEBREW_PATH which -a ruby) + do + if [[ $(test-ruby "$ruby_exec") == "true" ]]; then + HOMEBREW_RUBY_PATH=$ruby_exec + break + fi + done + IFS=$' \t\n' # Restore IFS to its default value + [[ -z $HOMEBREW_RUBY_PATH ]] && onoe "Failed to find usable Ruby $required_ruby_version!" + fi + + if [[ -n "$HOMEBREW_MACOS_SYSTEM_RUBY_NEW_ENOUGH" ]] + then + usable_ruby_version="true" + elif [[ -n "$HOMEBREW_RUBY_PATH" && -z "$HOMEBREW_FORCE_VENDOR_RUBY" ]] + then + usable_ruby_version=$(test-ruby "$HOMEBREW_RUBY_PATH") + fi + + if [[ -z "$HOMEBREW_RUBY_PATH" || -n "$HOMEBREW_FORCE_VENDOR_RUBY" || "$usable_ruby_version" != "true" ]] + then + brew vendor-install ruby + if [[ ! -x "$vendor_ruby_path" ]] + then + if [[ -n "$HOMEBREW_MACOS" ]] + then + odie "Failed to install Homebrew Portable Ruby (and your system version is too old)!" + else + odie "Failed to install Homebrew Portable Ruby and cannot find another Ruby $required_ruby_version!$advice" + fi + fi + HOMEBREW_RUBY_PATH="$vendor_ruby_path" + fi fi export HOMEBREW_RUBY_PATH diff --git a/Library/Homebrew/vendor/bundle/bundler/setup.rb b/Library/Homebrew/vendor/bundle/bundler/setup.rb index 41a0f0c253..3c4002ea48 100644 --- a/Library/Homebrew/vendor/bundle/bundler/setup.rb +++ b/Library/Homebrew/vendor/bundle/bundler/setup.rb @@ -4,7 +4,7 @@ ruby_engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby' ruby_version = RbConfig::CONFIG["ruby_version"] path = File.expand_path('..', __FILE__) $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby" -$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/i18n-1.8.2/lib" +$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/i18n-1.8.3/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/minitest-5.14.1/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/thread_safe-0.3.6/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/tzinfo-1.2.7/lib" @@ -12,7 +12,9 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/zeitwerk-2.3.0/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/activesupport-6.0.3.1/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ast-2.4.0/lib" $:.unshift "#{path}/" -$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/connection_pool-2.2.2/lib" +$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-19/2.6.0/byebug-11.1.3" +$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/byebug-11.1.3/lib" +$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/connection_pool-2.2.3/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-19/2.6.0/json-2.3.0" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/json-2.3.0/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/docile-1.3.2/lib" @@ -44,11 +46,12 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mechanize-2.7.6/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mustache-1.1.1/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parallel-1.19.1/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parallel_tests-2.32.0/lib" -$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parser-2.7.1.2/lib" +$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parser-2.7.1.3/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/plist-3.5.0/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rainbow-3.0.0/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-19/2.6.0/rdiscount-2.2.0.1" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rdiscount-2.2.0.1/lib" +$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/regexp_parser-1.7.0/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rexml-3.2.4/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ronn-0.7.3/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-support-3.9.3/lib" @@ -59,10 +62,10 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-3.9.0/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-its-1.3.0/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-retry-0.6.2/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-wait-0.0.9/lib" +$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-ast-0.0.3/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-progressbar-1.10.1/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unicode-display_width-1.7.0/lib" -$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-0.83.0/lib" -$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-performance-1.5.2/lib" +$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-0.85.0/lib" +$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-performance-1.6.1/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-rspec-1.39.0/lib" $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-macho-2.2.0/lib" -$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/byebug-11.1.3/lib" diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/locale/tag/parents.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/locale/tag/parents.rb deleted file mode 100644 index ec53060f9c..0000000000 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/locale/tag/parents.rb +++ /dev/null @@ -1,22 +0,0 @@ -module I18n - module Locale - module Tag - module Parents - def parent - @parent ||= begin - segs = to_a.compact - segs.length > 1 ? self.class.tag(*segs[0..(segs.length-2)].join('-')) : nil - end - end - - def self_and_parents - @self_and_parents ||= [self] + parents - end - - def parents - @parents ||= ([parent] + (parent ? parent.parents : [])).compact - end - end - end - end -end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n.rb similarity index 98% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n.rb index 4e9a108ea1..ba29a1e134 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n.rb @@ -223,11 +223,11 @@ module I18n alias :t! :translate! # Returns true if a translation exists for a given key, otherwise returns false. - def exists?(key, _locale = nil, locale: _locale) + def exists?(key, _locale = nil, locale: _locale, **options) locale ||= config.locale raise Disabled.new('exists?') if locale == false raise I18n::ArgumentError if key.is_a?(String) && key.empty? - config.backend.exists?(locale, key) + config.backend.exists?(locale, key, options) end # Transliterates UTF-8 characters to ASCII. By default this method will @@ -389,7 +389,7 @@ module I18n @@normalized_key_cache[separator][key] ||= case key when Array - key.map { |k| normalize_key(k, separator) }.flatten + key.flat_map { |k| normalize_key(k, separator) } else keys = key.to_s.split(separator) keys.delete('') diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend.rb similarity index 100% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend.rb diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/base.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/base.rb similarity index 98% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/base.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/base.rb index 285e5e6109..b04a259e01 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/base.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/base.rb @@ -64,7 +64,7 @@ module I18n entry end - def exists?(locale, key) + def exists?(locale, key, options = EMPTY_HASH) lookup(locale, key) != nil end @@ -146,7 +146,7 @@ module I18n I18n.translate(subject, **options.merge(:locale => locale, :throw => true)) when Proc date_or_time = options.delete(:object) || object - resolve(locale, object, subject.call(date_or_time, options)) + resolve(locale, object, subject.call(date_or_time, **options)) else subject end @@ -163,6 +163,7 @@ module I18n # not standard with regards to the CLDR pluralization rules. # Other backends can implement more flexible or complex pluralization rules. def pluralize(locale, entry, count) + entry = entry.reject { |k, _v| k == :attributes } if entry.is_a?(Hash) return entry unless entry.is_a?(Hash) && count && entry.values.none? { |v| v.is_a?(Hash) } key = pluralization_key(entry, count) diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/cache.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/cache.rb similarity index 100% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/cache.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/cache.rb diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/cache_file.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/cache_file.rb similarity index 100% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/cache_file.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/cache_file.rb diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/cascade.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/cascade.rb similarity index 100% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/cascade.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/cascade.rb diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/chain.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/chain.rb similarity index 95% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/chain.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/chain.rb index 123f7e3c51..9ab857536f 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/chain.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/chain.rb @@ -73,9 +73,9 @@ module I18n throw(:exception, I18n::MissingTranslation.new(locale, key, options)) end - def exists?(locale, key) + def exists?(locale, key, options = EMPTY_HASH) backends.any? do |backend| - backend.exists?(locale, key) + backend.exists?(locale, key, options) end end @@ -101,8 +101,7 @@ module I18n init_translations unless initialized? translations end - - memo.deep_merge!(partial_translations) + memo.deep_merge!(partial_translations) { |_, a, b| b || a } end end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/fallbacks.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/fallbacks.rb similarity index 86% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/fallbacks.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/fallbacks.rb index 7355d19299..7188a82c47 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/fallbacks.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/fallbacks.rb @@ -46,7 +46,10 @@ module I18n begin catch(:exception) do result = super(fallback, key, fallback_options) - return result unless result.nil? + unless result.nil? + on_fallback(locale, fallback, key, options) if locale != fallback + return result + end end rescue I18n::InvalidLocale # we do nothing when the locale is invalid, as this is a fallback anyways. @@ -68,7 +71,8 @@ module I18n return first_non_symbol_default end - def exists?(locale, key) + def exists?(locale, key, options = EMPTY_HASH) + return super unless options.fetch(:fallback, true) I18n.fallbacks[locale].each do |fallback| begin return true if super(fallback, key) @@ -79,6 +83,13 @@ module I18n false end + + private + + # Overwrite on_fallback to add specified logic when the fallback succeeds. + def on_fallback(_original_locale, _fallback_locale, _key, _optoins) + nil + end end end end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/flatten.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/flatten.rb similarity index 93% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/flatten.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/flatten.rb index f2ce3a0d36..e9bd9d531d 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/flatten.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/flatten.rb @@ -18,14 +18,17 @@ module I18n # and creates way less objects than the one at I18n.normalize_keys. # It also handles escaping the translation keys. def self.normalize_flat_keys(locale, key, scope, separator) - keys = [scope, key].flatten.compact + keys = [scope, key] + keys.flatten! + keys.compact! + separator ||= I18n.default_separator if separator != FLATTEN_SEPARATOR - keys.map! do |k| - k.to_s.tr("#{FLATTEN_SEPARATOR}#{separator}", - "#{SEPARATOR_ESCAPE_CHAR}#{FLATTEN_SEPARATOR}") - end + from_str = "#{FLATTEN_SEPARATOR}#{separator}" + to_str = "#{SEPARATOR_ESCAPE_CHAR}#{FLATTEN_SEPARATOR}" + + keys.map! { |k| k.to_s.tr from_str, to_str } end keys.join(".") diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/gettext.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/gettext.rb similarity index 100% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/gettext.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/gettext.rb diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/interpolation_compiler.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/interpolation_compiler.rb similarity index 100% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/interpolation_compiler.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/interpolation_compiler.rb diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/key_value.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/key_value.rb similarity index 100% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/key_value.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/key_value.rb diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/memoize.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/memoize.rb similarity index 100% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/memoize.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/memoize.rb diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/metadata.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/metadata.rb similarity index 100% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/metadata.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/metadata.rb diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/pluralization.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/pluralization.rb similarity index 100% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/pluralization.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/pluralization.rb diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/simple.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/simple.rb similarity index 100% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/simple.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/simple.rb diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/transliterator.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/transliterator.rb similarity index 100% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/backend/transliterator.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/backend/transliterator.rb diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/config.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/config.rb similarity index 100% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/config.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/config.rb diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/core_ext/hash.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/core_ext/hash.rb similarity index 57% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/core_ext/hash.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/core_ext/hash.rb index 95434acda0..775d490d34 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/core_ext/hash.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/core_ext/hash.rb @@ -18,12 +18,24 @@ module I18n end end - # deep_merge_hash! by Stefan Rusterholz, see http://www.ruby-forum.com/topic/142809 - def deep_merge!(data) - merger = lambda do |_key, v1, v2| - Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 + # deep_merge from activesupport 5 + # Copyright (c) 2005-2019 David Heinemeier Hansson + def deep_merge(other_hash, &block) + dup.deep_merge!(other_hash, &block) + end + + # deep_merge! from activesupport 5 + # Copyright (c) 2005-2019 David Heinemeier Hansson + def deep_merge!(other_hash, &block) + merge!(other_hash) do |key, this_val, other_val| + if this_val.is_a?(Hash) && other_val.is_a?(Hash) + this_val.deep_merge(other_val, &block) + elsif block_given? + block.call(key, this_val, other_val) + else + other_val + end end - merge!(data, &merger) end def symbolize_key(key) diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/exceptions.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/exceptions.rb similarity index 100% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/exceptions.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/exceptions.rb diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/gettext.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/gettext.rb similarity index 100% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/gettext.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/gettext.rb diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/gettext/helpers.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/gettext/helpers.rb similarity index 100% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/gettext/helpers.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/gettext/helpers.rb diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/gettext/po_parser.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/gettext/po_parser.rb similarity index 100% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/gettext/po_parser.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/gettext/po_parser.rb diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/interpolate/ruby.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/interpolate/ruby.rb similarity index 100% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/interpolate/ruby.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/interpolate/ruby.rb diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/locale.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/locale.rb similarity index 100% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/locale.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/locale.rb diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/locale/fallbacks.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/locale/fallbacks.rb similarity index 94% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/locale/fallbacks.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/locale/fallbacks.rb index 0a791c65a7..dee991728b 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/locale/fallbacks.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/locale/fallbacks.rb @@ -60,7 +60,7 @@ module I18n end def defaults=(defaults) - @defaults = defaults.map { |default| compute(default, false) }.flatten + @defaults = defaults.flat_map { |default| compute(default, false) } end attr_reader :defaults @@ -84,13 +84,15 @@ module I18n protected def compute(tags, include_defaults = true, exclude = []) - result = Array(tags).collect do |tag| + result = Array(tags).flat_map do |tag| tags = I18n::Locale::Tag.tag(tag).self_and_parents.map! { |t| t.to_sym } - exclude tags.each { |_tag| tags += compute(@map[_tag], false, exclude + tags) if @map[_tag] } tags - end.flatten + end result.push(*defaults) if include_defaults - result.uniq.compact + result.uniq! + result.compact! + result end end end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/locale/tag.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/locale/tag.rb similarity index 100% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/locale/tag.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/locale/tag.rb diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/locale/tag/parents.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/locale/tag/parents.rb new file mode 100644 index 0000000000..6283e667ff --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/locale/tag/parents.rb @@ -0,0 +1,24 @@ +module I18n + module Locale + module Tag + module Parents + def parent + @parent ||= + begin + segs = to_a + segs.compact! + segs.length > 1 ? self.class.tag(*segs[0..(segs.length - 2)].join('-')) : nil + end + end + + def self_and_parents + @self_and_parents ||= [self].concat parents + end + + def parents + @parents ||= parent ? [parent].concat(parent.parents) : [] + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/locale/tag/rfc4646.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/locale/tag/rfc4646.rb similarity index 100% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/locale/tag/rfc4646.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/locale/tag/rfc4646.rb diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/locale/tag/simple.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/locale/tag/simple.rb similarity index 89% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/locale/tag/simple.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/locale/tag/simple.rb index 68642a123f..6d9ab565cc 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/locale/tag/simple.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/locale/tag/simple.rb @@ -19,7 +19,7 @@ module I18n end def subtags - @subtags = tag.to_s.split('-').map { |subtag| subtag.to_s } + @subtags = tag.to_s.split('-').map!(&:to_s) end def to_sym diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/middleware.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/middleware.rb similarity index 100% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/middleware.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/middleware.rb diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/version.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/version.rb similarity index 70% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/version.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/version.rb index dfc9f7ca6a..16bc6b2bcc 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.2/lib/i18n/version.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/i18n-1.8.3/lib/i18n/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module I18n - VERSION = "1.8.2" + VERSION = "1.8.3" end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/config/default.yml b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/config/default.yml similarity index 92% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/config/default.yml rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/config/default.yml index 13740d9418..4b30f22509 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/config/default.yml +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/config/default.yml @@ -1,5 +1,10 @@ # This is the default configuration file. +Performance/BindCall: + Description: 'Use `bind_call(obj, args, ...)` instead of `bind(obj).call(args, ...)`.' + Enabled: true + VersionAdded: '1.6' + Performance/Caller: Description: >- Use `caller(n..n)` instead of `caller`. @@ -21,6 +26,7 @@ Performance/Casecmp: Use `casecmp` rather than `downcase ==`, `upcase ==`, `== downcase`, or `== upcase`.. Reference: 'https://github.com/JuanitoFatas/fast-ruby#stringcasecmp-vs-stringdowncase---code' Enabled: true + Safe: false VersionAdded: '0.36' Performance/ChainArrayAllocation: @@ -49,6 +55,18 @@ Performance/Count: VersionAdded: '0.31' VersionChanged: '1.5' +Performance/DeletePrefix: + Description: 'Use `delete_prefix` instead of `gsub`.' + Enabled: true + SafeMultiline: true + VersionAdded: '1.6' + +Performance/DeleteSuffix: + Description: 'Use `delete_suffix` instead of `gsub`.' + Enabled: true + SafeMultiline: true + VersionAdded: '1.6' + Performance/Detect: Description: >- Use `detect` instead of `select.first`, `find_all.first`, @@ -83,11 +101,12 @@ Performance/EndWith: SafeAutoCorrect: false AutoCorrect: false Enabled: true + SafeMultiline: true VersionAdded: '0.36' - VersionChanged: '0.44' + VersionChanged: '1.6' Performance/FixedSize: - Description: 'Do not compute the size of statically sized objects except in constants' + Description: 'Do not compute the size of statically sized objects except in constants.' Enabled: true VersionAdded: '0.35' @@ -95,7 +114,7 @@ Performance/FlatMap: Description: >- Use `Enumerable#flat_map` instead of `Enumerable#map...Array#flatten(1)` - or `Enumberable#collect..Array#flatten(1)` + or `Enumberable#collect..Array#flatten(1)`. Reference: 'https://github.com/JuanitoFatas/fast-ruby#enumerablemaparrayflatten-vs-enumerableflat_map-code' Enabled: true VersionAdded: '0.30' @@ -106,7 +125,7 @@ Performance/FlatMap: # `flatten` without any parameters can flatten multiple levels. Performance/InefficientHashSearch: - Description: 'Use `key?` or `value?` instead of `keys.include?` or `values.include?`' + Description: 'Use `key?` or `value?` instead of `keys.include?` or `values.include?`.' Reference: 'https://github.com/JuanitoFatas/fast-ruby#hashkey-instead-of-hashkeysinclude-code' Enabled: true VersionAdded: '0.56' @@ -177,8 +196,9 @@ Performance/StartWith: SafeAutoCorrect: false AutoCorrect: false Enabled: true + SafeMultiline: true VersionAdded: '0.36' - VersionChanged: '0.44' + VersionChanged: '1.6' Performance/StringReplacement: Description: >- diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop-performance.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop-performance.rb similarity index 100% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop-performance.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop-performance.rb diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/mixin/regexp_metacharacter.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/mixin/regexp_metacharacter.rb new file mode 100644 index 0000000000..9d3ab3cc43 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/mixin/regexp_metacharacter.rb @@ -0,0 +1,76 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + # Common functionality for handling regexp metacharacters. + module RegexpMetacharacter + private + + def literal_at_start?(regexp) + return true if literal_at_start_with_backslash_a?(regexp) + + !safe_multiline? && literal_at_start_with_caret?(regexp) + end + + def literal_at_end?(regexp) + return true if literal_at_end_with_backslash_z?(regexp) + + !safe_multiline? && literal_at_end_with_dollar?(regexp) + end + + def literal_at_start_with_backslash_a?(regex_str) + # is this regexp 'literal' in the sense of only matching literal + # chars, rather than using metachars like `.` and `*` and so on? + # also, is it anchored at the start of the string? + # (tricky: \s, \d, and so on are metacharacters, but other characters + # escaped with a slash are just literals. LITERAL_REGEX takes all + # that into account.) + /\A\\A(?:#{Util::LITERAL_REGEX})+\z/.match?(regex_str) + end + + def literal_at_start_with_caret?(regex_str) + # is this regexp 'literal' in the sense of only matching literal + # chars, rather than using metachars like `.` and `*` and so on? + # also, is it anchored at the start of the string? + # (tricky: \s, \d, and so on are metacharacters, but other characters + # escaped with a slash are just literals. LITERAL_REGEX takes all + # that into account.) + /\A\^(?:#{Util::LITERAL_REGEX})+\z/.match?(regex_str) + end + + def literal_at_end_with_backslash_z?(regex_str) + # is this regexp 'literal' in the sense of only matching literal + # chars, rather than using metachars like . and * and so on? + # also, is it anchored at the end of the string? + /\A(?:#{Util::LITERAL_REGEX})+\\z\z/.match?(regex_str) + end + + def literal_at_end_with_dollar?(regex_str) + # is this regexp 'literal' in the sense of only matching literal + # chars, rather than using metachars like . and * and so on? + # also, is it anchored at the end of the string? + /\A(?:#{Util::LITERAL_REGEX})+\$\z/.match?(regex_str) + end + + def drop_start_metacharacter(regexp_string) + if regexp_string.start_with?('\\A') + regexp_string[2..-1] # drop `\A` anchor + else + regexp_string[1..-1] # drop `^` anchor + end + end + + def drop_end_metacharacter(regexp_string) + if regexp_string.end_with?('\\z') + regexp_string.chomp('\z') # drop `\z` anchor + else + regexp_string.chop # drop `$` anchor + end + end + + def safe_multiline? + cop_config.fetch('SafeMultiline', true) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/bind_call.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/bind_call.rb new file mode 100644 index 0000000000..cf671fde25 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/bind_call.rb @@ -0,0 +1,87 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + # In Ruby 2.7, `UnboundMethod#bind_call` has been added. + # + # This cop identifies places where `bind(obj).call(args, ...)` + # can be replaced by `bind_call(obj, args, ...)`. + # + # The `bind_call(obj, args, ...)` method is faster than + # `bind(obj).call(args, ...)`. + # + # @example + # # bad + # umethod.bind(obj).call(foo, bar) + # umethod.bind(obj).(foo, bar) + # + # # good + # umethod.bind_call(obj, foo, bar) + # + class BindCall < Cop + include RangeHelp + extend TargetRubyVersion + + minimum_target_ruby_version 2.7 + + MSG = 'Use `bind_call(%s%s%s)` ' \ + 'instead of `bind(%s).call(%s)`.' + + def_node_matcher :bind_with_call_method?, <<~PATTERN + (send + $(send + (send nil? _) :bind + $(...)) :call + $...) + PATTERN + + def on_send(node) + bind_with_call_method?(node) do |receiver, bind_arg, call_args_node| + range = correction_range(receiver, node) + + call_args = build_call_args(call_args_node) + + message = message(bind_arg.source, call_args) + + add_offense(node, location: range, message: message) + end + end + + def autocorrect(node) + receiver, bind_arg, call_args_node = bind_with_call_method?(node) + + range = correction_range(receiver, node) + + call_args = build_call_args(call_args_node) + call_args = ", #{call_args}" unless call_args.empty? + + replacement_method = "bind_call(#{bind_arg.source}#{call_args})" + + lambda do |corrector| + corrector.replace(range, replacement_method) + end + end + + private + + def message(bind_arg, call_args) + comma = call_args.empty? ? '' : ', ' + + format(MSG, bind_arg: bind_arg, comma: comma, call_args: call_args) + end + + def correction_range(receiver, node) + location_of_bind = receiver.loc.selector.begin_pos + location_of_call = node.loc.end.end_pos + + range_between(location_of_bind, location_of_call) + end + + def build_call_args(call_args_node) + call_args_node.map(&:source).join(', ') + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/caller.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/caller.rb similarity index 93% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/caller.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/caller.rb index 9cc82243d4..7f9d22887f 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/caller.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/caller.rb @@ -24,14 +24,14 @@ module RuboCop MSG_FIRST = 'Use `%s(%d..%d).first`' \ ' instead of `%s.first`.' - def_node_matcher :slow_caller?, <<-PATTERN + def_node_matcher :slow_caller?, <<~PATTERN { (send nil? {:caller :caller_locations}) (send nil? {:caller :caller_locations} int) } PATTERN - def_node_matcher :caller_with_scope_method?, <<-PATTERN + def_node_matcher :caller_with_scope_method?, <<~PATTERN { (send #slow_caller? :first) (send #slow_caller? :[] int) diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/case_when_splat.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/case_when_splat.rb similarity index 100% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/case_when_splat.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/case_when_splat.rb diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/casecmp.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/casecmp.rb similarity index 91% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/casecmp.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/casecmp.rb index c411eca255..cfb0c709cb 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/casecmp.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/casecmp.rb @@ -5,6 +5,8 @@ module RuboCop module Performance # This cop identifies places where a case-insensitive string comparison # can better be implemented using `casecmp`. + # This cop is unsafe because `String#casecmp` and `String#casecmp?` behave + # differently when using Non-ASCII characters. # # @example # # bad @@ -21,21 +23,21 @@ module RuboCop MSG = 'Use `%s` instead of `%s`.' CASE_METHODS = %i[downcase upcase].freeze - def_node_matcher :downcase_eq, <<-PATTERN + def_node_matcher :downcase_eq, <<~PATTERN (send $(send _ ${:downcase :upcase}) ${:== :eql? :!=} ${str (send _ {:downcase :upcase} ...) (begin str)}) PATTERN - def_node_matcher :eq_downcase, <<-PATTERN + def_node_matcher :eq_downcase, <<~PATTERN (send {str (send _ {:downcase :upcase} ...) (begin str)} ${:== :eql? :!=} $(send _ ${:downcase :upcase})) PATTERN - def_node_matcher :downcase_downcase, <<-PATTERN + def_node_matcher :downcase_downcase, <<~PATTERN (send $(send _ ${:downcase :upcase}) ${:== :eql? :!=} diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/chain_array_allocation.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/chain_array_allocation.rb similarity index 98% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/chain_array_allocation.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/chain_array_allocation.rb index 49620cea8e..140dfa48ed 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/chain_array_allocation.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/chain_array_allocation.rb @@ -51,7 +51,7 @@ module RuboCop '(followed by `return array` if required) instead of chaining '\ '`%s...%s`.' - def_node_matcher :flat_map_candidate?, <<-PATTERN + def_node_matcher :flat_map_candidate?, <<~PATTERN { (send (send _ ${#{RETURN_NEW_ARRAY_WHEN_ARGS}} {int lvar ivar cvar gvar}) ${#{HAS_MUTATION_ALTERNATIVE}} $...) (send (block (send _ ${#{ALWAYS_RETURNS_NEW_ARRAY} }) ...) ${#{HAS_MUTATION_ALTERNATIVE}} $...) diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/compare_with_block.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/compare_with_block.rb similarity index 97% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/compare_with_block.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/compare_with_block.rb index 040e6e47b2..01c1393a5d 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/compare_with_block.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/compare_with_block.rb @@ -30,14 +30,14 @@ module RuboCop '`%s { |%s, %s| %s ' \ '<=> %s }`.' - def_node_matcher :compare?, <<-PATTERN + def_node_matcher :compare?, <<~PATTERN (block $(send _ {:sort :min :max}) (args (arg $_a) (arg $_b)) $send) PATTERN - def_node_matcher :replaceable_body?, <<-PATTERN + def_node_matcher :replaceable_body?, <<~PATTERN (send (send (lvar %1) $_method $...) :<=> diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/count.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/count.rb similarity index 98% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/count.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/count.rb index 80a6e42627..4a2eb1df83 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/count.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/count.rb @@ -42,7 +42,7 @@ module RuboCop MSG = 'Use `count` instead of `%s...%s`.' - def_node_matcher :count_candidate?, <<-PATTERN + def_node_matcher :count_candidate?, <<~PATTERN { (send (block $(send _ ${:select :reject}) ...) ${:count :length :size}) (send $(send _ ${:select :reject} (:block_pass _)) ${:count :length :size}) diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/delete_prefix.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/delete_prefix.rb new file mode 100644 index 0000000000..a5f5c472d5 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/delete_prefix.rb @@ -0,0 +1,96 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + # In Ruby 2.5, `String#delete_prefix` has been added. + # + # This cop identifies places where `gsub(/\Aprefix/, '')` and `sub(/\Aprefix/, '')` + # can be replaced by `delete_prefix('prefix')`. + # + # This cop has `SafeMultiline` configuration option that `true` by default because + # `^prefix` is unsafe as it will behave incompatible with `delete_prefix` + # for receiver is multiline string. + # + # The `delete_prefix('prefix')` method is faster than `gsub(/\Aprefix/, '')`. + # + # @example + # + # # bad + # str.gsub(/\Aprefix/, '') + # str.gsub!(/\Aprefix/, '') + # + # str.sub(/\Aprefix/, '') + # str.sub!(/\Aprefix/, '') + # + # # good + # str.delete_prefix('prefix') + # str.delete_prefix!('prefix') + # + # @example SafeMultiline: true (default) + # + # # good + # str.gsub(/^prefix/, '') + # str.gsub!(/^prefix/, '') + # str.sub(/^prefix/, '') + # str.sub!(/^prefix/, '') + # + # @example SafeMultiline: false + # + # # bad + # str.gsub(/^prefix/, '') + # str.gsub!(/^prefix/, '') + # str.sub(/^prefix/, '') + # str.sub!(/^prefix/, '') + # + class DeletePrefix < Cop + extend TargetRubyVersion + include RegexpMetacharacter + + minimum_target_ruby_version 2.5 + + MSG = 'Use `%s` instead of `%s`.' + + PREFERRED_METHODS = { + gsub: :delete_prefix, + gsub!: :delete_prefix!, + sub: :delete_prefix, + sub!: :delete_prefix! + }.freeze + + def_node_matcher :delete_prefix_candidate?, <<~PATTERN + (send $!nil? ${:gsub :gsub! :sub :sub!} (regexp (str $#literal_at_start?) (regopt)) (str $_)) + PATTERN + + def on_send(node) + delete_prefix_candidate?(node) do |_, bad_method, _, replace_string| + return unless replace_string.blank? + + good_method = PREFERRED_METHODS[bad_method] + + message = format(MSG, current: bad_method, prefer: good_method) + + add_offense(node, location: :selector, message: message) + end + end + + def autocorrect(node) + delete_prefix_candidate?(node) do |receiver, bad_method, regexp_str, _| + lambda do |corrector| + good_method = PREFERRED_METHODS[bad_method] + regexp_str = drop_start_metacharacter(regexp_str) + regexp_str = interpret_string_escapes(regexp_str) + string_literal = to_string_literal(regexp_str) + + new_code = "#{receiver.source}.#{good_method}(#{string_literal})" + + # TODO: `source_range` is no longer required when RuboCop 0.81 or lower support will be dropped. + # https://github.com/rubocop-hq/rubocop/commit/82eb350d2cba16 + corrector.replace(node.source_range, new_code) + end + end + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/delete_suffix.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/delete_suffix.rb new file mode 100644 index 0000000000..d90245cccb --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/delete_suffix.rb @@ -0,0 +1,96 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Performance + # In Ruby 2.5, `String#delete_suffix` has been added. + # + # This cop identifies places where `gsub(/suffix\z/, '')` and `sub(/suffix\z/, '')` + # can be replaced by `delete_suffix('suffix')`. + # + # This cop has `SafeMultiline` configuration option that `true` by default because + # `suffix$` is unsafe as it will behave incompatible with `delete_suffix?` + # for receiver is multiline string. + # + # The `delete_suffix('suffix')` method is faster than `gsub(/suffix\z/, '')`. + # + # @example + # + # # bad + # str.gsub(/suffix\z/, '') + # str.gsub!(/suffix\z/, '') + # + # str.sub(/suffix\z/, '') + # str.sub!(/suffix\z/, '') + # + # # good + # str.delete_suffix('suffix') + # str.delete_suffix!('suffix') + # + # @example SafeMultiline: true (default) + # + # # good + # str.gsub(/suffix$/, '') + # str.gsub!(/suffix$/, '') + # str.sub(/suffix$/, '') + # str.sub!(/suffix$/, '') + # + # @example SafeMultiline: false + # + # # bad + # str.gsub(/suffix$/, '') + # str.gsub!(/suffix$/, '') + # str.sub(/suffix$/, '') + # str.sub!(/suffix$/, '') + # + class DeleteSuffix < Cop + extend TargetRubyVersion + include RegexpMetacharacter + + minimum_target_ruby_version 2.5 + + MSG = 'Use `%s` instead of `%s`.' + + PREFERRED_METHODS = { + gsub: :delete_suffix, + gsub!: :delete_suffix!, + sub: :delete_suffix, + sub!: :delete_suffix! + }.freeze + + def_node_matcher :delete_suffix_candidate?, <<~PATTERN + (send $!nil? ${:gsub :gsub! :sub :sub!} (regexp (str $#literal_at_end?) (regopt)) (str $_)) + PATTERN + + def on_send(node) + delete_suffix_candidate?(node) do |_, bad_method, _, replace_string| + return unless replace_string.blank? + + good_method = PREFERRED_METHODS[bad_method] + + message = format(MSG, current: bad_method, prefer: good_method) + + add_offense(node, location: :selector, message: message) + end + end + + def autocorrect(node) + delete_suffix_candidate?(node) do |receiver, bad_method, regexp_str, _| + lambda do |corrector| + good_method = PREFERRED_METHODS[bad_method] + regexp_str = drop_end_metacharacter(regexp_str) + regexp_str = interpret_string_escapes(regexp_str) + string_literal = to_string_literal(regexp_str) + + new_code = "#{receiver.source}.#{good_method}(#{string_literal})" + + # TODO: `source_range` is no longer required when RuboCop 0.81 or lower support will be dropped. + # https://github.com/rubocop-hq/rubocop/commit/82eb350d2cba16 + corrector.replace(node.source_range, new_code) + end + end + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/detect.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/detect.rb similarity index 98% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/detect.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/detect.rb index f1aa75be8d..958b4e8444 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/detect.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/detect.rb @@ -28,7 +28,7 @@ module RuboCop REVERSE_MSG = 'Use `reverse.%s` instead of ' \ '`%s.%s`.' - def_node_matcher :detect_candidate?, <<-PATTERN + def_node_matcher :detect_candidate?, <<~PATTERN { (send $(block (send _ {:select :find_all}) ...) ${:first :last} $...) (send $(send _ {:select :find_all} ...) ${:first :last} $...) diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/double_start_end_with.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/double_start_end_with.rb similarity index 95% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/double_start_end_with.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/double_start_end_with.rb index 530c41d424..92e7e385be 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/double_start_end_with.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/double_start_end_with.rb @@ -75,13 +75,13 @@ module RuboCop cop_config['IncludeActiveSupportAliases'] end - def_node_matcher :two_start_end_with_calls, <<-PATTERN + def_node_matcher :two_start_end_with_calls, <<~PATTERN (or (send $_recv [{:start_with? :end_with?} $_method] $...) (send _recv _method $...)) PATTERN - def_node_matcher :check_with_active_support_aliases, <<-PATTERN + def_node_matcher :check_with_active_support_aliases, <<~PATTERN (or (send $_recv [{:start_with? :starts_with? :end_with? :ends_with?} $_method] diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/end_with.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/end_with.rb similarity index 62% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/end_with.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/end_with.rb index 66f43a6ce6..185c2183b5 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/end_with.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/end_with.rb @@ -3,8 +3,11 @@ module RuboCop module Cop module Performance - # This cop identifies unnecessary use of a regex where `String#end_with?` - # would suffice. + # This cop identifies unnecessary use of a regex where `String#end_with?` would suffice. + # + # This cop has `SafeMultiline` configuration option that `true` by default because + # `end$` is unsafe as it will behave incompatible with `end_with?` + # for receiver is multiline string. # # @example # # bad @@ -17,24 +20,39 @@ module RuboCop # # # good # 'abc'.end_with?('bc') + # + # @example SafeMultiline: true (default) + # + # # good + # 'abc'.match?(/bc$/) + # /bc$/.match?('abc') + # 'abc' =~ /bc$/ + # /bc$/ =~ 'abc' + # 'abc'.match(/bc$/) + # /bc$/.match('abc') + # + # @example SafeMultiline: false + # + # # bad + # 'abc'.match?(/bc$/) + # /bc$/.match?('abc') + # 'abc' =~ /bc$/ + # /bc$/ =~ 'abc' + # 'abc'.match(/bc$/) + # /bc$/.match('abc') + # class EndWith < Cop + include RegexpMetacharacter + MSG = 'Use `String#end_with?` instead of a regex match anchored to ' \ 'the end of the string.' - SINGLE_QUOTE = "'" - def_node_matcher :redundant_regex?, <<-PATTERN + def_node_matcher :redundant_regex?, <<~PATTERN {(send $!nil? {:match :=~ :match?} (regexp (str $#literal_at_end?) (regopt))) (send (regexp (str $#literal_at_end?) (regopt)) {:match :match?} $_) (match-with-lvasgn (regexp (str $#literal_at_end?) (regopt)) $_)} PATTERN - def literal_at_end?(regex_str) - # is this regexp 'literal' in the sense of only matching literal - # chars, rather than using metachars like . and * and so on? - # also, is it anchored at the end of the string? - regex_str =~ /\A(?:#{LITERAL_REGEX})+\\z\z/ - end - def on_send(node) return unless redundant_regex?(node) @@ -45,7 +63,7 @@ module RuboCop def autocorrect(node) redundant_regex?(node) do |receiver, regex_str| receiver, regex_str = regex_str, receiver if receiver.is_a?(String) - regex_str = regex_str[0..-3] # drop \Z anchor + regex_str = drop_end_metacharacter(regex_str) regex_str = interpret_string_escapes(regex_str) lambda do |corrector| diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/fixed_size.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/fixed_size.rb similarity index 97% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/fixed_size.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/fixed_size.rb index c3a0beb481..76be44259c 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/fixed_size.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/fixed_size.rb @@ -48,7 +48,7 @@ module RuboCop class FixedSize < Cop MSG = 'Do not compute the size of statically sized objects.' - def_node_matcher :counter, <<-MATCHER + def_node_matcher :counter, <<~MATCHER (send ${array hash str sym} {:count :length :size} $...) MATCHER diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/flat_map.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/flat_map.rb similarity index 97% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/flat_map.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/flat_map.rb index b5b91876a7..de4677a444 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/flat_map.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/flat_map.rb @@ -22,7 +22,7 @@ module RuboCop 'and `flatten` can be used to flatten ' \ 'multiple levels.' - def_node_matcher :flat_map_candidate?, <<-PATTERN + def_node_matcher :flat_map_candidate?, <<~PATTERN (send { (block $(send _ ${:collect :map}) ...) diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/inefficient_hash_search.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/inefficient_hash_search.rb similarity index 98% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/inefficient_hash_search.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/inefficient_hash_search.rb index 0a4a1cc0b2..b72063faef 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/inefficient_hash_search.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/inefficient_hash_search.rb @@ -37,7 +37,7 @@ module RuboCop # h = { a: 1, b: 2 }; h.value?(nil) # class InefficientHashSearch < Cop - def_node_matcher :inefficient_include?, <<-PATTERN + def_node_matcher :inefficient_include?, <<~PATTERN (send (send $_ {:keys :values}) :include? _) PATTERN diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/open_struct.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/open_struct.rb similarity index 96% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/open_struct.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/open_struct.rb index d3d3e212aa..192bc81239 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/open_struct.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/open_struct.rb @@ -31,7 +31,7 @@ module RuboCop MSG = 'Consider using `Struct` over `OpenStruct` ' \ 'to optimize the performance.' - def_node_matcher :open_struct, <<-PATTERN + def_node_matcher :open_struct, <<~PATTERN (send (const {nil? cbase} :OpenStruct) :new ...) PATTERN diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/range_include.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/range_include.rb similarity index 96% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/range_include.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/range_include.rb index 77eebc8bbc..0e49753c54 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/range_include.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/range_include.rb @@ -31,7 +31,7 @@ module RuboCop # Right now, we only detect direct calls on a Range literal # (We don't even catch it if the Range is in double parens) - def_node_matcher :range_include, <<-PATTERN + def_node_matcher :range_include, <<~PATTERN (send {irange erange (begin {irange erange})} :include? ...) PATTERN diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/redundant_block_call.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/redundant_block_call.rb similarity index 93% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/redundant_block_call.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/redundant_block_call.rb index 315deac115..1301ae821e 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/redundant_block_call.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/redundant_block_call.rb @@ -29,16 +29,16 @@ module RuboCop CLOSE_PAREN = ')' SPACE = ' ' - def_node_matcher :blockarg_def, <<-PATTERN + def_node_matcher :blockarg_def, <<~PATTERN {(def _ (args ... (blockarg $_)) $_) (defs _ _ (args ... (blockarg $_)) $_)} PATTERN - def_node_search :blockarg_calls, <<-PATTERN + def_node_search :blockarg_calls, <<~PATTERN (send (lvar %1) :call ...) PATTERN - def_node_search :blockarg_assigned?, <<-PATTERN + def_node_search :blockarg_assigned?, <<~PATTERN (lvasgn %1 ...) PATTERN diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/redundant_match.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/redundant_match.rb similarity index 93% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/redundant_match.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/redundant_match.rb index b1eabc8ae4..f0bfecde0a 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/redundant_match.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/redundant_match.rb @@ -23,12 +23,12 @@ module RuboCop # 'match' is a fairly generic name, so we don't flag it unless we see # a string or regexp literal on one side or the other - def_node_matcher :match_call?, <<-PATTERN + def_node_matcher :match_call?, <<~PATTERN {(send {str regexp} :match _) (send !nil? :match {str regexp})} PATTERN - def_node_matcher :only_truthiness_matters?, <<-PATTERN + def_node_matcher :only_truthiness_matters?, <<~PATTERN ^({if while until case while_post until_post} equal?(%0) ...) PATTERN diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/redundant_merge.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/redundant_merge.rb similarity index 89% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/redundant_merge.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/redundant_merge.rb index d93ca155d9..bfb7347aec 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/redundant_merge.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/redundant_merge.rb @@ -5,11 +5,25 @@ module RuboCop module Performance # This cop identifies places where `Hash#merge!` can be replaced by # `Hash#[]=`. + # You can set the maximum number of key-value pairs to consider + # an offense with `MaxKeyValuePairs`. # # @example + # # bad # hash.merge!(a: 1) # hash.merge!({'key' => 'value'}) + # + # # good + # hash[:a] = 1 + # hash['key'] = 'value' + # + # @example MaxKeyValuePairs: 2 (default) + # # bad # hash.merge!(a: 1, b: 2) + # + # # good + # hash[:a] = 1 + # hash[:b] = 2 class RedundantMerge < Cop AREF_ASGN = '%s[%s] = %s' MSG = 'Use `%s` instead of `%s`.' @@ -20,11 +34,11 @@ module RuboCop %send RUBY - def_node_matcher :redundant_merge_candidate, <<-PATTERN + def_node_matcher :redundant_merge_candidate, <<~PATTERN (send $!nil? :merge! [(hash $...) !kwsplat_type?]) PATTERN - def_node_matcher :modifier_flow_control?, <<-PATTERN + def_node_matcher :modifier_flow_control?, <<~PATTERN [{if while until} modifier_form?] PATTERN @@ -168,13 +182,11 @@ module RuboCop end def unwind(receiver) - while receiver.respond_to?(:send_type?) && receiver.send_type? - receiver, = *receiver - end + receiver, = *receiver while receiver.respond_to?(:send_type?) && receiver.send_type? receiver end - def_node_matcher :each_with_object_node, <<-PATTERN + def_node_matcher :each_with_object_node, <<~PATTERN (block (send _ :each_with_object _) (args _ $_) ...) PATTERN end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/regexp_match.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/regexp_match.rb similarity index 92% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/regexp_match.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/regexp_match.rb index e59ea7f63d..bc5579ec05 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/regexp_match.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/regexp_match.rb @@ -73,32 +73,28 @@ module RuboCop # end # end class RegexpMatch < Cop - extend TargetRubyVersion - - minimum_target_ruby_version 2.4 - # Constants are included in this list because it is unlikely that # someone will store `nil` as a constant and then use it for comparison TYPES_IMPLEMENTING_MATCH = %i[const regexp str sym].freeze MSG = 'Use `match?` instead of `%s` when `MatchData` ' \ 'is not used.' - def_node_matcher :match_method?, <<-PATTERN + def_node_matcher :match_method?, <<~PATTERN { (send _recv :match {regexp str sym}) (send {regexp str sym} :match _) } PATTERN - def_node_matcher :match_with_int_arg_method?, <<-PATTERN + def_node_matcher :match_with_int_arg_method?, <<~PATTERN (send _recv :match _ (int ...)) PATTERN - def_node_matcher :match_operator?, <<-PATTERN + def_node_matcher :match_operator?, <<~PATTERN (send !nil? {:=~ :!~} !nil?) PATTERN - def_node_matcher :match_threequals?, <<-PATTERN + def_node_matcher :match_threequals?, <<~PATTERN (send (regexp (str _) {(regopt) (regopt _)}) :=== !nil?) PATTERN @@ -109,7 +105,7 @@ module RuboCop regexp.to_regexp.named_captures.empty? end - MATCH_NODE_PATTERN = <<-PATTERN + MATCH_NODE_PATTERN = <<~PATTERN { #match_method? #match_with_int_arg_method? @@ -122,7 +118,7 @@ module RuboCop def_node_matcher :match_node?, MATCH_NODE_PATTERN def_node_search :search_match_nodes, MATCH_NODE_PATTERN - def_node_search :last_matches, <<-PATTERN + def_node_search :last_matches, <<~PATTERN { (send (const nil? :Regexp) :last_match) (send (const nil? :Regexp) :last_match _) @@ -256,6 +252,13 @@ module RuboCop def correct_operator(corrector, recv, arg, oper = nil) op_range = correction_range(recv, arg) + replace_with_match_predicate_method(corrector, recv, arg, op_range) + + corrector.insert_after(arg.loc.expression, ')') unless op_range.source.end_with?('(') + corrector.insert_before(recv.loc.expression, '!') if oper == :!~ + end + + def replace_with_match_predicate_method(corrector, recv, arg, op_range) if TYPES_IMPLEMENTING_MATCH.include?(recv.type) corrector.replace(op_range, '.match?(') elsif TYPES_IMPLEMENTING_MATCH.include?(arg.type) @@ -264,9 +267,6 @@ module RuboCop else corrector.replace(op_range, '&.match?(') end - - corrector.insert_after(arg.loc.expression, ')') - corrector.insert_before(recv.loc.expression, '!') if oper == :!~ end def swap_receiver_and_arg(corrector, recv, arg) diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/reverse_each.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/reverse_each.rb similarity index 82% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/reverse_each.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/reverse_each.rb index 6c6fdfba14..09a8214123 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/reverse_each.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/reverse_each.rb @@ -18,7 +18,7 @@ module RuboCop MSG = 'Use `reverse_each` instead of `reverse.each`.' UNDERSCORE = '_' - def_node_matcher :reverse_each?, <<-MATCHER + def_node_matcher :reverse_each?, <<~MATCHER (send $(send _ :reverse) :each) MATCHER @@ -34,7 +34,8 @@ module RuboCop end def autocorrect(node) - ->(corrector) { corrector.replace(node.loc.dot, UNDERSCORE) } + range = range_between(node.loc.dot.begin_pos, node.loc.selector.begin_pos) + ->(corrector) { corrector.replace(range, UNDERSCORE) } end end end diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/size.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/size.rb similarity index 100% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/size.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/size.rb diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/start_with.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/start_with.rb similarity index 60% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/start_with.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/start_with.rb index b4a7cae8a1..feda084bbc 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/start_with.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/start_with.rb @@ -3,8 +3,11 @@ module RuboCop module Cop module Performance - # This cop identifies unnecessary use of a regex where - # `String#start_with?` would suffice. + # This cop identifies unnecessary use of a regex where `String#start_with?` would suffice. + # + # This cop has `SafeMultiline` configuration option that `true` by default because + # `^start` is unsafe as it will behave incompatible with `start_with?` + # for receiver is multiline string. # # @example # # bad @@ -17,27 +20,39 @@ module RuboCop # # # good # 'abc'.start_with?('ab') + # + # @example SafeMultiline: true (default) + # + # # good + # 'abc'.match?(/^ab/) + # /^ab/.match?('abc') + # 'abc' =~ /^ab/ + # /^ab/ =~ 'abc' + # 'abc'.match(/^ab/) + # /^ab/.match('abc') + # + # @example SafeMultiline: false + # + # # bad + # 'abc'.match?(/^ab/) + # /^ab/.match?('abc') + # 'abc' =~ /^ab/ + # /^ab/ =~ 'abc' + # 'abc'.match(/^ab/) + # /^ab/.match('abc') + # class StartWith < Cop + include RegexpMetacharacter + MSG = 'Use `String#start_with?` instead of a regex match anchored to ' \ 'the beginning of the string.' - SINGLE_QUOTE = "'" - def_node_matcher :redundant_regex?, <<-PATTERN + def_node_matcher :redundant_regex?, <<~PATTERN {(send $!nil? {:match :=~ :match?} (regexp (str $#literal_at_start?) (regopt))) (send (regexp (str $#literal_at_start?) (regopt)) {:match :match?} $_) (match-with-lvasgn (regexp (str $#literal_at_start?) (regopt)) $_)} PATTERN - def literal_at_start?(regex_str) - # is this regexp 'literal' in the sense of only matching literal - # chars, rather than using metachars like `.` and `*` and so on? - # also, is it anchored at the start of the string? - # (tricky: \s, \d, and so on are metacharacters, but other characters - # escaped with a slash are just literals. LITERAL_REGEX takes all - # that into account.) - regex_str =~ /\A\\A(?:#{LITERAL_REGEX})+\z/ - end - def on_send(node) return unless redundant_regex?(node) @@ -48,7 +63,7 @@ module RuboCop def autocorrect(node) redundant_regex?(node) do |receiver, regex_str| receiver, regex_str = regex_str, receiver if receiver.is_a?(String) - regex_str = regex_str[2..-1] # drop \A anchor + regex_str = drop_start_metacharacter(regex_str) regex_str = interpret_string_escapes(regex_str) lambda do |corrector| diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/string_replacement.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/string_replacement.rb similarity index 91% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/string_replacement.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/string_replacement.rb index b5b0a4dafd..e6dab7e396 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/string_replacement.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/string_replacement.rb @@ -26,9 +26,8 @@ module RuboCop DELETE = 'delete' TR = 'tr' BANG = '!' - SINGLE_QUOTE = "'" - def_node_matcher :string_replacement?, <<-PATTERN + def_node_matcher :string_replacement?, <<~PATTERN (send _ {:gsub :gsub!} ${regexp str (send (const nil? :Regexp) {:new :compile} _)} $str) @@ -48,9 +47,7 @@ module RuboCop first_source, = first_source(first_param) second_source, = *second_param - unless first_param.str_type? - first_source = interpret_string_escapes(first_source) - end + first_source = interpret_string_escapes(first_source) unless first_param.str_type? replacement_method = replacement_method(node, first_source, second_source) @@ -67,9 +64,7 @@ module RuboCop to_string_literal(first)) end - if second.empty? && first.length == 1 - remove_second_param(corrector, node, first_param) - end + remove_second_param(corrector, node, first_param) if second.empty? && first.length == 1 end end @@ -99,9 +94,7 @@ module RuboCop def offense(node, first_param, second_param) first_source, = first_source(first_param) - unless first_param.str_type? - first_source = interpret_string_escapes(first_source) - end + first_source = interpret_string_escapes(first_source) unless first_param.str_type? second_source, = *second_param message = message(node, first_source, second_source) diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/times_map.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/times_map.rb similarity index 97% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/times_map.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/times_map.rb index 1a04732947..cd719da2ce 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/times_map.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/times_map.rb @@ -61,7 +61,7 @@ module RuboCop map_or_collect: map_or_collect.method_name) end - def_node_matcher :times_map_call, <<-PATTERN + def_node_matcher :times_map_call, <<~PATTERN {(block $(send (send $!nil? :times) {:map :collect}) ...) $(send (send $!nil? :times) {:map :collect} (block_pass ...))} PATTERN diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/unfreeze_string.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/unfreeze_string.rb similarity index 83% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/unfreeze_string.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/unfreeze_string.rb index 408fa959d4..f0dbb4178c 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/unfreeze_string.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/unfreeze_string.rb @@ -7,7 +7,7 @@ module RuboCop # literal instead of `String#dup` and `String.new`. # Unary plus operator is faster than `String#dup`. # - # Note: `String.new` (without operator) is not exactly the same as `+''`. + # NOTE: `String.new` (without operator) is not exactly the same as `+''`. # These differ in encoding. `String.new.encoding` is always `ASCII-8BIT`. # However, `(+'').encoding` is the same as script encoding(e.g. `UTF-8`). # So, if you expect `ASCII-8BIT` encoding, disable this cop. @@ -24,17 +24,13 @@ module RuboCop # +'something' # +'' class UnfreezeString < Cop - extend TargetRubyVersion - - minimum_target_ruby_version 2.3 - MSG = 'Use unary plus to get an unfrozen string literal.' - def_node_matcher :dup_string?, <<-PATTERN + def_node_matcher :dup_string?, <<~PATTERN (send {str dstr} :dup) PATTERN - def_node_matcher :string_new?, <<-PATTERN + def_node_matcher :string_new?, <<~PATTERN { (send (const nil? :String) :new {str dstr}) (send (const nil? :String) :new) diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/uri_default_parser.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/uri_default_parser.rb similarity index 95% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/uri_default_parser.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/uri_default_parser.rb index a8aa3eb128..e0d2ac8f40 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance/uri_default_parser.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance/uri_default_parser.rb @@ -17,7 +17,7 @@ module RuboCop MSG = 'Use `%sURI::DEFAULT_PARSER` instead of ' \ '`%sURI::Parser.new`.' - def_node_matcher :uri_parser_new?, <<-PATTERN + def_node_matcher :uri_parser_new?, <<~PATTERN (send (const (const ${nil? cbase} :URI) :Parser) :new) diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance_cops.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance_cops.rb similarity index 86% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance_cops.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance_cops.rb index 0d0a13d621..446357cff3 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/cop/performance_cops.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/cop/performance_cops.rb @@ -1,10 +1,15 @@ # frozen_string_literal: true +require_relative 'mixin/regexp_metacharacter' + +require_relative 'performance/bind_call' require_relative 'performance/caller' require_relative 'performance/case_when_splat' require_relative 'performance/casecmp' require_relative 'performance/compare_with_block' require_relative 'performance/count' +require_relative 'performance/delete_prefix' +require_relative 'performance/delete_suffix' require_relative 'performance/detect' require_relative 'performance/double_start_end_with' require_relative 'performance/end_with' diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/performance.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/performance.rb similarity index 100% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/performance.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/performance.rb diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/performance/inject.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/performance/inject.rb similarity index 88% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/performance/inject.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/performance/inject.rb index f82404dad3..e255a881a4 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/performance/inject.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/performance/inject.rb @@ -8,7 +8,7 @@ module RuboCop def self.defaults! path = CONFIG_DEFAULT.to_s hash = ConfigLoader.send(:load_yaml_configuration, path) - config = Config.new(hash, path) + config = Config.new(hash, path).tap(&:make_excludes_absolute) puts "configuration from #{path}" if ConfigLoader.debug? config = ConfigLoader.merge_with_default(config, path) ConfigLoader.instance_variable_set(:@default_configuration, config) diff --git a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/performance/version.rb b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/performance/version.rb similarity index 81% rename from Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/performance/version.rb rename to Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/performance/version.rb index d07d623aab..afbdfb9b40 100644 --- a/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.5.2/lib/rubocop/performance/version.rb +++ b/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-performance-1.6.1/lib/rubocop/performance/version.rb @@ -3,7 +3,7 @@ module RuboCop module Performance module Version - STRING = '1.5.2' + STRING = '1.6.1' end end end diff --git a/README.md b/README.md index 33f0e1bc4a..e770c93b21 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Homebrew is a member of the [Software Freedom Conservancy](https://sfconservancy ## Security Please report security issues to our [HackerOne](https://hackerone.com/homebrew/). -## Who Are You? +## Who We Are Homebrew's [Project Leader](https://docs.brew.sh/Homebrew-Governance#6-project-leader) is [Mike McQuaid](https://github.com/MikeMcQuaid). Homebrew's [Project Leadership Committee](https://docs.brew.sh/Homebrew-Governance#4-project-leadership-committee) is [Misty De Meo](https://github.com/mistydemeo), [Shaun Jackman](https://github.com/sjackman), [Jonathan Chang](https://github.com/jonchang), [Sean Molenaar](https://github.com/SMillerDev) and [Markus Reiter](https://github.com/reitermarkus). diff --git a/completions/zsh/_brew b/completions/zsh/_brew index f216255bd3..c4f75cf6a7 100644 --- a/completions/zsh/_brew +++ b/completions/zsh/_brew @@ -377,17 +377,19 @@ _brew_edit() { '*:: :__brew_formulae_or_ruby_files' } -# brew fetch [--force] [--retry] [-v] [--devel|--HEAD] [--deps] [--build-from-source|--force-bottle] formulae +# brew fetch [--force] [--retry] [-v] [--devel|--HEAD] [--deps] +# [--build-from-source|--build-bottle|--force-bottle] formulae _brew_fetch() { _arguments \ - '--force[remove previously cached version and re-fetch]' \ + '(--force -f)'{--force,-f}'[remove previously cached version and re-fetch]' \ '--retry[retry if a download fails or re-download if the checksum of a previously cached version no longer matches]' \ - '-v[verbose VCS checkout]' \ + '(--verbose -v)'{--verbose,-v}'[verbose VCS checkout]' \ '(--HEAD)--devel[fetch devel version instead of stable]' \ '(--devel)--HEAD[fetch HEAD version instead of stable]' \ '--deps[also download dependencies for any listed formulae]' \ - '(--force-bottle)--build-from-source[download the source rather than a bottle]' \ - '(--build-from-source)--force-bottle[download a bottle if it exists for the current version of OS X, even if it would not be used during installation]' \ + '(--build-from-source -s --force-bottle --build-bottle)'{--build-from-source,-s}'[download the source rather than a bottle]' \ + '(--build-from-source -s --force-bottle)--build-bottle[download the source (for eventual bottling) rather than a bottle]' \ + '(--build-from-source -s --build-bottle)--force-bottle[download a bottle if it exists for the current version of OS X, even if it would not be used during installation]' \ '*:formula:__brew_formulae' } @@ -431,9 +433,10 @@ _brew_info() { '(--all --installed)*: :__brew_formulae' } -# brew install [--debug] [--env=std|super] [--ignore-dependencies] -# [--only-dependencies] [--cc=compiler] [--build-from-source] -# [--devel|--HEAD] [--keep-tmp] formulae +# brew install [--debug] [--env=std|super] +# [--ignore-dependencies|--only-dependencies] [--include-test] +# [--cc=compiler] [--build-from-source|--build-bottle|--force-fottle] +# [--devel|--HEAD] [--fetch-HEAD] [--bottle-arch=architecture] [--keep-tmp] formulae # brew install --interactive [--git] formula _brew_install() { local state @@ -441,11 +444,16 @@ _brew_install() { - normal-install \ '--debug[if brewing fails, open an interactive debugging session]' \ -'-env=-[use standard or super environment]:environment:(std super)' \ - '--ignore-dependencies[skip installing any dependencies of any kind]' \ - '--only-dependencies[install the dependencies but do not install the specified formula]' \ + '(--only-dependencies)--ignore-dependencies[skip installing any dependencies of any kind]' \ + '(--ignore-dependencies)--only-dependencies[install the dependencies but do not install the specified formula]' \ '--cc=-[attempt to compile using compiler]:compiler: ' \ - '(--build-from-source -s)'{--build-from-source,-s}'[compile the specified formula from source even if a bottle is provided]' \ + '(--build-from-source -s --force-bottle --build-bottle)'{--build-from-source,-s}'[compile the specified formula from source even if a bottle is provided]' \ + '(--build-from-source -s --force-bottle)--build-bottle[prepare the formula for eventual bottling during installation, skipping any post-install steps]' \ + '(--build-from-source -s --build-bottle)--force-bottle[install from a bottle if it exists for the current version of OS X, even if it would not normally be used for installation]' \ + '--include-test[install testing dependencies]' \ '(--devel --HEAD)'{--devel,--HEAD}'[install the development / HEAD version]' \ + '--fetch-HEAD[fetch the upstream repository to detect if the HEAD installation of the formula is outdated]' \ + '--bottle-arch=-[optimise bottles for the specified architecture]:architecture: ' \ '--keep-tmp[don''t delete temporary files created during installation]' \ '--display-times[display installation times at end of run]' \ '*: : __brew_formulae' \ @@ -570,7 +578,7 @@ _brew_pull() { } # brew pr-pull [--no-upload|--no-publish] [--dry-run] [--clean] [--branch-okay] -# [--resolve] [--workflow] [--artifact] [--bintray-org] [--tap] pull_request +# [--resolve] [--workflow] [--artifact] [--bintray-org] [--tap] pull_request _brew_pr_pull() { _arguments \ '(--no-upload)--no-publish[download the bottles, apply the bottle commit, and upload the bottles to Bintray, but don''t publish them]' \ @@ -592,10 +600,19 @@ _brew_readall() { } # brew reinstall formulae: +# mostly copy from brew install _brew_reinstall() { _arguments \ - '--display-times[display installation times at end of run]' \ - '*::formula:__brew_installed_formulae' + - normal-install \ + '--debug[if brewing fails, open an interactive debugging session]' \ + '(--build-from-source -s --force-bottle)'{--build-from-source,-s}'[compile the specified formula from source even if a bottle is provided]' \ + '(--build-from-source -s)--force-bottle[install from a bottle if it exists for the current version of OS X, even if it would not normally be used for installation]' \ + '--keep-tmp[don''t delete temporary files created during installation]' \ + '--display-times[display installation times at end of run]' \ + '*::formula:__brew_installed_formulae' \ + - interactive-install \ + '--interactive[download and patch formula, then open a shell]' \ + '::formula:__brew_installed_formulae' } # brew search, -S: @@ -790,7 +807,8 @@ _brew_upgrade() { '--ignore-dependencies[skip installing any dependencies of any kind]' \ '--only-dependencies[install the dependencies but do not install the specified formula]' \ '--cc=-[attempt to compile using compiler]:compiler: ' \ - '(--build-from-source -s)'{--build-from-source,-s}'[compile the specified formula from source even if a bottle is provided]' \ + '(--build-from-source -s --force-bottle)'{--build-from-source,-s}'[compile the specified formula from source even if a bottle is provided]' \ + '(--build-from-source -s)--force-bottle[install from a bottle if it exists for the current version of OS X, even if it would not normally be used for installation]' \ '(--devel --HEAD)'{--devel,--HEAD}'[install the development / HEAD version]' \ '--keep-tmp[don''t delete temporary files created during installation]' \ '--display-times[display installation times at end of run]' \ diff --git a/completions/zsh/_brew_cask b/completions/zsh/_brew_cask index da49f5c462..c841b006c3 100644 --- a/completions/zsh/_brew_cask +++ b/completions/zsh/_brew_cask @@ -19,7 +19,13 @@ __brew_cask() { __brew_all_casks() { local -a list local expl - list=( $(brew search --casks) ) + local comp_cachename=brew_casks + + if _cache_invalid $comp_cachename || ! _retrieve_cache $comp_cachename; then + list=( $(brew search --casks) ) + _store_cache $comp_cachename list + fi + _wanted list expl 'all casks' compadd -a list } diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock index e94a45a0b6..55648a90ba 100644 --- a/docs/Gemfile.lock +++ b/docs/Gemfile.lock @@ -28,12 +28,12 @@ GEM execjs (2.7.0) faraday (1.0.1) multipart-post (>= 1.2, < 3) - ffi (1.12.2) + ffi (1.13.0) forwardable-extended (2.6.0) gemoji (3.0.1) - github-pages (204) + github-pages (206) github-pages-health-check (= 1.16.1) - jekyll (= 3.8.5) + jekyll (= 3.8.7) jekyll-avatar (= 0.7.0) jekyll-coffeescript (= 1.1.1) jekyll-commonmark-ghpages (= 0.1.6) @@ -72,7 +72,7 @@ GEM mercenary (~> 0.3) minima (= 2.5.1) nokogiri (>= 1.10.4, < 2.0) - rouge (= 3.13.0) + rouge (= 3.19.0) terminal-table (~> 1.4) github-pages-health-check (1.16.1) addressable (~> 2.3) @@ -80,7 +80,7 @@ GEM octokit (~> 4.0) public_suffix (~> 3.0) typhoeus (~> 1.3) - html-pipeline (2.12.3) + html-pipeline (2.13.0) activesupport (>= 2) nokogiri (>= 1.4) html-proofer (3.15.3) @@ -94,7 +94,7 @@ GEM http_parser.rb (0.6.0) i18n (0.9.5) concurrent-ruby (~> 1.0) - jekyll (3.8.5) + jekyll (3.8.7) addressable (~> 2.4) colorator (~> 1.0) em-websocket (~> 0.5) @@ -228,7 +228,7 @@ GEM rb-fsevent (0.10.4) rb-inotify (0.10.1) ffi (~> 1.0) - rouge (3.13.0) + rouge (3.19.0) ruby-enum (0.8.0) i18n rubyzip (2.3.0) diff --git a/docs/Manpage.md b/docs/Manpage.md index 36c45bea58..e7b415d951 100644 --- a/docs/Manpage.md +++ b/docs/Manpage.md @@ -917,26 +917,6 @@ Apply the bottle commit and publish bottles to Bintray. Run Homebrew with the Ruby profiler, e.g. `brew prof readall`. -### `pull` [*`options`*] *`patch`* - -Get a patch from a GitHub commit or pull request and apply it to Homebrew. - -Each *`patch`* may be the number of a pull request in `homebrew/core` or the URL -of any pull request or commit on GitHub. - -* `--bump`: - For one-formula PRs, automatically reword commit message to our preferred format. -* `--clean`: - Do not rewrite or otherwise modify the commits found in the pulled PR. -* `--ignore-whitespace`: - Silently ignore whitespace discrepancies when applying diffs. -* `--resolve`: - When a patch fails to apply, leave in progress and allow user to resolve, instead of aborting. -* `--branch-okay`: - Do not warn if pulling to a branch besides master (useful for testing). -* `--no-pbcopy`: - Do not copy anything to the system clipboard. - ### `release-notes` [*`options`*] [*`previous_tag`*] [*`end_ref`*] Print the merged pull requests on Homebrew/brew between two Git refs. If no @@ -1082,23 +1062,52 @@ Bundler for non-Ruby dependencies from Homebrew, Homebrew Cask, Mac App Store and Whalebrew. `brew bundle` [`install`]: - Install or upgrade all dependencies in a `Brewfile`. + Install and upgrade (by default) all dependencies from the `Brewfile`. + +You can skip the installation of dependencies by adding space-separated values +to one or more of the following environment variables: +`HOMEBREW_BUNDLE_BREW_SKIP`, `HOMEBREW_BUNDLE_CASK_SKIP`, +`HOMEBREW_BUNDLE_MAS_SKIP`, `HOMEBREW_BUNDLE_WHALEBREW_SKIP`, +`HOMEBREW_BUNDLE_TAP_SKIP` + +`brew bundle` will output a `Brewfile.lock.json` in the same directory as the +`Brewfile` if all dependencies are installed successfully. This contains +dependency and system status information which can be useful in debugging `brew +bundle` failures and replicating a "last known good build" state. You can +opt-out of this behaviour by setting the `HOMEBREW_BUNDLE_NO_LOCK` environment +variable or passing the `--no-lock` option. You may wish to check this file into +the same version control system as your `Brewfile` (or ensure your version +control system ignores it if you'd prefer to rely on debugging information from +a local machine). `brew bundle dump`: Write all installed casks/formulae/images/taps into a `Brewfile`. `brew bundle cleanup`: - Uninstall all dependencies not listed in a `Brewfile`. + Uninstall all dependencies not listed from the `Brewfile`. + +This workflow is useful for maintainers or testers who regularly install lots of +formulae. `brew bundle check`: - Check if all dependencies are installed in a `Brewfile`. + Check if all dependencies are installed from the `Brewfile` . -`brew bundle exec` *`command`*: - Run an external command in an isolated build environment. +This provides a successful exit code if everything is up-to-date, making it +useful for scripting. `brew bundle list`: - List all dependencies present in a `Brewfile`. By default, only Homebrew -dependencies are listed. + List all dependencies present in a `Brewfile`. + +By default, only Homebrew dependencies are listed. + +`brew bundle exec` *`command`*: + Run an external command in an isolated build environment based on the +`Brewfile` dependencies. + +This sanitized build environment ignores unrequested dependencies, which makes +sure that things you didn't specify in your `Brewfile` won't get picked up by +commands like `bundle install`, `npm install`, etc. It will also add compiler +flags which will help find keg-only dependencies like `openssl`, `icu4c`, etc. * `--file`: Read the `Brewfile` from this location. Use `--file=-` to pipe to stdin/stdout. @@ -1139,7 +1148,7 @@ If `sudo` is passed, operate on `/Library/LaunchDaemons` (started at boot). Otherwise, operate on `~/Library/LaunchAgents` (started at login). [`sudo`] `brew services` [`list`]: - List all running services for the current user (or root). + List all managed services for the current user (or root). [`sudo`] `brew services run` (*`formula`*|`--all`): Run the service *`formula`* without registering to launch at login (or boot). @@ -1162,6 +1171,64 @@ it to launch at login (or boot). * `--all`: Run *`subcommand`* on all services. +### `test-bot` [*`options`*] [*`formula`*]: + +Tests the full lifecycle of a Homebrew change to a tap (Git repository). For +example, for a GitHub Actions pull request that changes a formula `brew +test-bot` will ensure the system is cleaned and setup to test the formula, +install the formula, run various tests and checks on it, bottle (package) the +binaries and test formulae that depend on it to ensure they aren't broken by +these changes. + +Only supports GitHub Actions as a CI provider. This is because Homebrew uses +GitHub Actions and it's freely available for public and private use with macOS +and Linux workers. + +* `--dry-run`: + print what would be done rather than doing it. +* `--cleanup`: + clean all state from the Homebrew directory. Use with care! +* `--skip-setup`: + don't check if the local system is set up correctly. +* `--keep-old`: + run `brew bottle --keep-old` to build new bottles for a single platform. +* `--skip-relocation`: + run `brew bottle --skip-relocation` to build new bottles that don't require relocation. +* `--local`: + ask Homebrew to write verbose logs under `./logs/` and set `$HOME` to `./home/` +* `--tap`: + use the `git` repository of the given tap. Defaults to the core tap for syntax checking. +* `--fail-fast`: + immediately exit on a failing step. +* `-v`, `--verbose`: + print test step output in real time. Has the side effect of passing output as raw bytes instead of re-encoding in UTF-8. +* `--test-default-formula`: + use a default testing formula when not building a tap and no other formulae are specified. +* `--bintray-org`: + upload to the given Bintray organisation. +* `--root-url`: + use the specified *`URL`* as the root of the bottle's URL instead of Homebrew's default. +* `--git-name`: + set the Git author/committer names to the given name. +* `--git-email`: + set the Git author/committer email to the given email. +* `--ci-upload`: + use the Homebrew CI bottle upload options. +* `--publish`: + publish the uploaded bottles. +* `--skip-recursive-dependents`: + only test the direct dependents. +* `--only-cleanup-before`: + Only run the pre-cleanup step. Needs `--cleanup`. +* `--only-setup`: + Only run the local system setup check step. +* `--only-tap-syntax`: + Only run the tap syntax check step. +* `--only-formulae`: + Only run the formulae steps. +* `--only-cleanup-after`: + Only run the post-cleanup step. Needs `--cleanup`. + ## CUSTOM EXTERNAL COMMANDS Homebrew, like `git`(1), supports external commands. These are executable @@ -1186,11 +1253,9 @@ can take several different forms: You can still access these formulae by using a special syntax, e.g. `homebrew/dupes/vim` or `homebrew/versions/node4`. - * An arbitrary file or URL: - Homebrew can install formulae via URL, e.g. - `https://raw.githubusercontent.com/Homebrew/homebrew-core/master/Formula/git.rb`, - or from a local path. It can point to either a formula file or a bottle. - In the case of a URL, the downloaded file will be cached for later use. + * An arbitrary file: + Homebrew can install formulae from a local path. It can point to either a + formula file or a bottle. ## ENVIRONMENT diff --git a/docs/Tips-N'-Tricks.md b/docs/Tips-N'-Tricks.md index 2e29670b7c..6b5179b35a 100644 --- a/docs/Tips-N'-Tricks.md +++ b/docs/Tips-N'-Tricks.md @@ -5,14 +5,6 @@ The supported method of installing specific versions of some formulae is to see if there is a versioned formula (e.g. `gcc@7`) available. If the version you’re looking for isn’t available, consider using `brew extract`. -### Installing directly from pull requests -You can [browse pull requests](https://github.com/Homebrew/homebrew-core/pulls) -and install through their direct link. For example, Python 3.7.0 from pull request [Homebrew/homebrew-core#29490](https://github.com/Homebrew/homebrew-core/pull/29490): - -```sh -brew install https://raw.githubusercontent.com/sashkab/homebrew-core/176823eb82ee1b5ce55a91e5e1bf2f50aa674092/Formula/python.rb -``` - ## Quickly remove something from `/usr/local` ```sh diff --git a/docs/Versions.md b/docs/Versions.md index a2b99e9a2e..22d297c323 100644 --- a/docs/Versions.md +++ b/docs/Versions.md @@ -11,6 +11,7 @@ Versioned formulae we include in [homebrew/core](https://github.com/homebrew/hom * Versioned formulae should differ in major/minor (not patch) versions from the current stable release. This is because patch versions indicate bug or security updates and we want to ensure you apply security updates. * Unstable versions (alpha, beta, development versions) are not acceptable for versioned (or unversioned) formulae. * Upstream should have a release branch for the versioned formulae version and still make security updates for that version, when necessary. For example, [PHP 5.5 was not a supported version but PHP 7.2 was](https://php.net/supported-versions.php) in January 2018. +* Versioned formulae share a codebase with the main formula. If the project is split into a different repository we recommend creating a new formula (`formula2` rather than `formula@2` or `formula@1`). * Formulae that depend on versioned formulae must not depend on the same formulae at two different versions twice in their recursive dependencies. For example, if you depend on `openssl@1.0` and `foo`, and `foo` depends on `openssl` then you must instead use `openssl`. * Versioned formulae should only be linkable at the same time as their non-versioned counterpart if the upstream project provides support for it, e.g. using suffixed binaries. If this is not possible, use `keg_only :versioned_formula` to allow users to have multiple versions installed at once. * A `keg_only :versioned_formula` should not `post_install` anything in the `HOMEBREW_PREFIX` that conflicts with or duplicates the non-versioned counterpart (or other versioned formulae). For example, a `node@6` formula should not install its `npm` into `HOMEBREW_PREFIX` like the `node` formula does. diff --git a/manpages/brew-cask.1 b/manpages/brew-cask.1 index 6dcccee77b..f250696a66 100644 --- a/manpages/brew-cask.1 +++ b/manpages/brew-cask.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BREW\-CASK" "1" "May 2020" "Homebrew" "brew-cask" +.TH "BREW\-CASK" "1" "June 2020" "Homebrew" "brew-cask" . .SH "NAME" \fBbrew\-cask\fR \- a friendly binary installer for macOS diff --git a/manpages/brew.1 b/manpages/brew.1 index d69f8f770a..bccb3cd322 100644 --- a/manpages/brew.1 +++ b/manpages/brew.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BREW" "1" "May 2020" "Homebrew" "brew" +.TH "BREW" "1" "June 2020" "Homebrew" "brew" . .SH "NAME" \fBbrew\fR \- The Missing Package Manager for macOS @@ -1189,36 +1189,6 @@ Use the specified \fIURL\fR as the root of the bottle\'s URL instead of Homebrew .SS "\fBprof\fR \fIcommand\fR" Run Homebrew with the Ruby profiler, e\.g\. \fBbrew prof readall\fR\. . -.SS "\fBpull\fR [\fIoptions\fR] \fIpatch\fR" -Get a patch from a GitHub commit or pull request and apply it to Homebrew\. -. -.P -Each \fIpatch\fR may be the number of a pull request in \fBhomebrew/core\fR or the URL of any pull request or commit on GitHub\. -. -.TP -\fB\-\-bump\fR -For one\-formula PRs, automatically reword commit message to our preferred format\. -. -.TP -\fB\-\-clean\fR -Do not rewrite or otherwise modify the commits found in the pulled PR\. -. -.TP -\fB\-\-ignore\-whitespace\fR -Silently ignore whitespace discrepancies when applying diffs\. -. -.TP -\fB\-\-resolve\fR -When a patch fails to apply, leave in progress and allow user to resolve, instead of aborting\. -. -.TP -\fB\-\-branch\-okay\fR -Do not warn if pulling to a branch besides master (useful for testing)\. -. -.TP -\fB\-\-no\-pbcopy\fR -Do not copy anything to the system clipboard\. -. .SS "\fBrelease\-notes\fR [\fIoptions\fR] [\fIprevious_tag\fR] [\fIend_ref\fR]" Print the merged pull requests on Homebrew/brew between two Git refs\. If no \fIprevious_tag\fR is provided it defaults to the latest tag\. If no \fIend_ref\fR is provided it defaults to \fBorigin/master\fR\. . @@ -1388,7 +1358,13 @@ Bundler for non\-Ruby dependencies from Homebrew, Homebrew Cask, Mac App Store a . .P \fBbrew bundle\fR [\fBinstall\fR] - Install or upgrade all dependencies in a \fBBrewfile\fR\. + Install and upgrade (by default) all dependencies from the \fBBrewfile\fR\. +. +.P +You can skip the installation of dependencies by adding space\-separated values to one or more of the following environment variables: \fBHOMEBREW_BUNDLE_BREW_SKIP\fR, \fBHOMEBREW_BUNDLE_CASK_SKIP\fR, \fBHOMEBREW_BUNDLE_MAS_SKIP\fR, \fBHOMEBREW_BUNDLE_WHALEBREW_SKIP\fR, \fBHOMEBREW_BUNDLE_TAP_SKIP\fR +. +.P +\fBbrew bundle\fR will output a \fBBrewfile\.lock\.json\fR in the same directory as the \fBBrewfile\fR if all dependencies are installed successfully\. This contains dependency and system status information which can be useful in debugging \fBbrew bundle\fR failures and replicating a "last known good build" state\. You can opt\-out of this behaviour by setting the \fBHOMEBREW_BUNDLE_NO_LOCK\fR environment variable or passing the \fB\-\-no\-lock\fR option\. You may wish to check this file into the same version control system as your \fBBrewfile\fR (or ensure your version control system ignores it if you\'d prefer to rely on debugging information from a local machine)\. . .P \fBbrew bundle dump\fR @@ -1396,19 +1372,31 @@ Bundler for non\-Ruby dependencies from Homebrew, Homebrew Cask, Mac App Store a . .P \fBbrew bundle cleanup\fR - Uninstall all dependencies not listed in a \fBBrewfile\fR\. + Uninstall all dependencies not listed from the \fBBrewfile\fR\. +. +.P +This workflow is useful for maintainers or testers who regularly install lots of formulae\. . .P \fBbrew bundle check\fR - Check if all dependencies are installed in a \fBBrewfile\fR\. + Check if all dependencies are installed from the \fBBrewfile\fR \. . .P -\fBbrew bundle exec\fR \fIcommand\fR - Run an external command in an isolated build environment\. +This provides a successful exit code if everything is up\-to\-date, making it useful for scripting\. . .P \fBbrew bundle list\fR - List all dependencies present in a \fBBrewfile\fR\. By default, only Homebrew dependencies are listed\. + List all dependencies present in a \fBBrewfile\fR\. +. +.P +By default, only Homebrew dependencies are listed\. +. +.P +\fBbrew bundle exec\fR \fIcommand\fR + Run an external command in an isolated build environment based on the \fBBrewfile\fR dependencies\. +. +.P +This sanitized build environment ignores unrequested dependencies, which makes sure that things you didn\'t specify in your \fBBrewfile\fR won\'t get picked up by commands like \fBbundle install\fR, \fBnpm install\fR, etc\. It will also add compiler flags which will help find keg\-only dependencies like \fBopenssl\fR, \fBicu4c\fR, etc\. . .TP \fB\-\-file\fR @@ -1478,7 +1466,7 @@ If \fBsudo\fR is passed, operate on \fB/Library/LaunchDaemons\fR (started at boo . .P [\fBsudo\fR] \fBbrew services\fR [\fBlist\fR] - List all running services for the current user (or root)\. + List all managed services for the current user (or root)\. . .P [\fBsudo\fR] \fBbrew services run\fR (\fIformula\fR|\fB\-\-all\fR) @@ -1504,6 +1492,100 @@ If \fBsudo\fR is passed, operate on \fB/Library/LaunchDaemons\fR (started at boo \fB\-\-all\fR Run \fIsubcommand\fR on all services\. . +.SS "\fBtest\-bot\fR [\fIoptions\fR] [\fIformula\fR]:" +Tests the full lifecycle of a Homebrew change to a tap (Git repository)\. For example, for a GitHub Actions pull request that changes a formula \fBbrew test\-bot\fR will ensure the system is cleaned and setup to test the formula, install the formula, run various tests and checks on it, bottle (package) the binaries and test formulae that depend on it to ensure they aren\'t broken by these changes\. +. +.P +Only supports GitHub Actions as a CI provider\. This is because Homebrew uses GitHub Actions and it\'s freely available for public and private use with macOS and Linux workers\. +. +.TP +\fB\-\-dry\-run\fR +print what would be done rather than doing it\. +. +.TP +\fB\-\-cleanup\fR +clean all state from the Homebrew directory\. Use with care! +. +.TP +\fB\-\-skip\-setup\fR +don\'t check if the local system is set up correctly\. +. +.TP +\fB\-\-keep\-old\fR +run \fBbrew bottle \-\-keep\-old\fR to build new bottles for a single platform\. +. +.TP +\fB\-\-skip\-relocation\fR +run \fBbrew bottle \-\-skip\-relocation\fR to build new bottles that don\'t require relocation\. +. +.TP +\fB\-\-local\fR +ask Homebrew to write verbose logs under \fB\./logs/\fR and set \fB$HOME\fR to \fB\./home/\fR +. +.TP +\fB\-\-tap\fR +use the \fBgit\fR repository of the given tap\. Defaults to the core tap for syntax checking\. +. +.TP +\fB\-\-fail\-fast\fR +immediately exit on a failing step\. +. +.TP +\fB\-v\fR, \fB\-\-verbose\fR +print test step output in real time\. Has the side effect of passing output as raw bytes instead of re\-encoding in UTF\-8\. +. +.TP +\fB\-\-test\-default\-formula\fR +use a default testing formula when not building a tap and no other formulae are specified\. +. +.TP +\fB\-\-bintray\-org\fR +upload to the given Bintray organisation\. +. +.TP +\fB\-\-root\-url\fR +use the specified \fIURL\fR as the root of the bottle\'s URL instead of Homebrew\'s default\. +. +.TP +\fB\-\-git\-name\fR +set the Git author/committer names to the given name\. +. +.TP +\fB\-\-git\-email\fR +set the Git author/committer email to the given email\. +. +.TP +\fB\-\-ci\-upload\fR +use the Homebrew CI bottle upload options\. +. +.TP +\fB\-\-publish\fR +publish the uploaded bottles\. +. +.TP +\fB\-\-skip\-recursive\-dependents\fR +only test the direct dependents\. +. +.TP +\fB\-\-only\-cleanup\-before\fR +Only run the pre\-cleanup step\. Needs \fB\-\-cleanup\fR\. +. +.TP +\fB\-\-only\-setup\fR +Only run the local system setup check step\. +. +.TP +\fB\-\-only\-tap\-syntax\fR +Only run the tap syntax check step\. +. +.TP +\fB\-\-only\-formulae\fR +Only run the formulae steps\. +. +.TP +\fB\-\-only\-cleanup\-after\fR +Only run the post\-cleanup step\. Needs \fB\-\-cleanup\fR\. +. .SH "CUSTOM EXTERNAL COMMANDS" Homebrew, like \fBgit\fR(1), supports external commands\. These are executable scripts that reside somewhere in the \fBPATH\fR, named \fBbrew\-\fR\fIcmdname\fR or \fBbrew\-\fR\fIcmdname\fR\fB\.rb\fR, which can be invoked like \fBbrew\fR \fIcmdname\fR\. This allows you to create your own commands without modifying Homebrew\'s internals\. . @@ -1522,8 +1604,8 @@ The fully\-qualified name of a tapped formula Sometimes a formula from a tapped repository may conflict with one in \fBhomebrew/core\fR\. You can still access these formulae by using a special syntax, e\.g\. \fBhomebrew/dupes/vim\fR or \fBhomebrew/versions/node4\fR\. . .TP -An arbitrary file or URL -Homebrew can install formulae via URL, e\.g\. \fBhttps://raw\.githubusercontent\.com/Homebrew/homebrew\-core/master/Formula/git\.rb\fR, or from a local path\. It can point to either a formula file or a bottle\. In the case of a URL, the downloaded file will be cached for later use\. +An arbitrary file +Homebrew can install formulae from a local path\. It can point to either a formula file or a bottle\. . .SH "ENVIRONMENT" Note that environment variables must have a value set to be detected\. For example, run \fBexport HOMEBREW_NO_INSECURE_REDIRECT=1\fR rather than just \fBexport HOMEBREW_NO_INSECURE_REDIRECT\fR\.