diff --git a/Library/Homebrew/style.rb b/Library/Homebrew/style.rb index 98b31c9a03..b82a2a65ad 100644 --- a/Library/Homebrew/style.rb +++ b/Library/Homebrew/style.rb @@ -65,6 +65,8 @@ module Homebrew run_shellcheck(shell_files, output_type) end + run_shfmt(shell_files) if ruby_files.none? || shell_files.any? + if output_type == :json Offenses.new(rubocop_result + shellcheck_result) else @@ -164,30 +166,7 @@ module Homebrew end def run_shellcheck(files, output_type) - # Always use the latest brewed shellcheck - unless Formula["shellcheck"].latest_version_installed? - if Formula["shellcheck"].any_version_installed? - ohai "Upgrading `shellcheck` for shell style checks..." - safe_system HOMEBREW_BREW_FILE, "upgrade", "shellcheck" - else - ohai "Installing `shellcheck` for shell style checks..." - safe_system HOMEBREW_BREW_FILE, "install", "shellcheck" - end - end - shellcheck = Formula["shellcheck"].opt_bin/"shellcheck" - - if files.empty? - files = [ - HOMEBREW_BREW_FILE, - HOMEBREW_REPOSITORY/"completions/bash/brew", - HOMEBREW_REPOSITORY/"Dockerfile", - *HOMEBREW_LIBRARY.glob("Homebrew/*.sh"), - *HOMEBREW_LIBRARY.glob("Homebrew/shims/**/*").map(&:realpath).uniq - .reject { |path| path.directory? || path.basename.to_s == "cc" }, - *HOMEBREW_LIBRARY.glob("Homebrew/{dev-,}cmd/*.sh"), - *HOMEBREW_LIBRARY.glob("Homebrew/{cask/,}utils/*.sh"), - ] - end + files = [*shell_scripts, HOMEBREW_REPOSITORY/"Dockerfile"] if files.empty? args = ["--shell=bash", "--enable=all", "--external-sources", "--source-path=#{HOMEBREW_LIBRARY}", "--", *files] @@ -235,6 +214,15 @@ module Homebrew end end + def run_shfmt(files) + files = shell_scripts if files.empty? + + args = ["-i", "2", "-ci", "-ln", "bash", "--", *files] + + system shfmt, *args + $CHILD_STATUS.success? + end + def json_result!(result) # An exit status of 1 just means violations were found; other numbers mean # execution errors. @@ -244,6 +232,49 @@ module Homebrew JSON.parse(result.stdout) end + def shell_scripts + [ + HOMEBREW_BREW_FILE, + HOMEBREW_REPOSITORY/"completions/bash/brew", + HOMEBREW_REPOSITORY/"Dockerfile", + *HOMEBREW_LIBRARY.glob("Homebrew/*.sh"), + *HOMEBREW_LIBRARY.glob("Homebrew/shims/**/*").map(&:realpath).uniq + .reject { |path| path.directory? || path.basename.to_s == "cc" }, + *HOMEBREW_LIBRARY.glob("Homebrew/{dev-,}cmd/*.sh"), + *HOMEBREW_LIBRARY.glob("Homebrew/{cask/,}utils/*.sh"), + ] + end + + def shellcheck + # Always use the latest brewed shellcheck + unless Formula["shellcheck"].latest_version_installed? + if Formula["shellcheck"].any_version_installed? + ohai "Upgrading `shellcheck` for shell style checks..." + safe_system HOMEBREW_BREW_FILE, "upgrade", "shellcheck" + else + ohai "Installing `shellcheck` for shell style checks..." + safe_system HOMEBREW_BREW_FILE, "install", "shellcheck" + end + end + + Formula["shellcheck"].opt_bin/"shellcheck" + end + + def shfmt + # Always use the latest brewed shfmt + unless Formula["shfmt"].latest_version_installed? + if Formula["shfmt"].any_version_installed? + ohai "Upgrading `shfmt` to format shell scripts..." + safe_system HOMEBREW_BREW_FILE, "upgrade", "shfmt" + else + ohai "Installing `shfmt` to format shell scripts..." + safe_system HOMEBREW_BREW_FILE, "install", "shfmt" + end + end + + HOMEBREW_LIBRARY/"Homebrew/utils/shfmt.sh" + end + # Collection of style offenses. class Offenses include Enumerable diff --git a/Library/Homebrew/utils/shfmt.sh b/Library/Homebrew/utils/shfmt.sh new file mode 100755 index 0000000000..96891970eb --- /dev/null +++ b/Library/Homebrew/utils/shfmt.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +# HOMEBREW_LIBRARY is set by bin/brew +# HOMEBREW_PREFIX is set by extend/ENV/super.rb +# shellcheck disable=SC2154 +if [[ -z "${HOMEBREW_LIBRARY}" || -z "${HOMEBREW_PREFIX}" ]] +then + echo "${0##*/}: This program is internal and must be run via brew." >&2 + exit 1 +fi + +# HOMEBREW_PREFIX is set by extend/ENV/super.rb +# shellcheck disable=SC2154 +SHFMT="${HOMEBREW_PREFIX}/opt/shfmt/bin/shfmt" + +if [[ ! -x "${SHFMT}" ]] +then + echo "${0##*/}: Please install shfmt by running \`brew install shfmt\`." >&2 + exit 1 +fi + +SHFMT_ARGS=() +INPLACE='' +while [[ $# -gt 0 ]] +do + arg="$1" + if [[ "${arg}" == "--" ]] + then + shift + break + fi + if [[ "${arg}" == "-w" ]] + then + shift + INPLACE=1 + continue + fi + SHFMT_ARGS+=("${arg}") + shift +done + +FILES=() +for file in "$@" +do + if [[ -f "${file}" ]] + then + FILES+=("${file}") + else + echo "${0##*/}: File \"${file}\" does not exist." >&2 + exit 1 + fi +done + +if [[ "${#FILES[@]}" == 0 ]] +then + exit +fi + +"${SHFMT}" "${SHFMT_ARGS[@]}" "${FILES[@]}"