diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml new file mode 100644 index 000000000000..f7ed82bb7c4a --- /dev/null +++ b/.github/workflows/format.yml @@ -0,0 +1,29 @@ +on: + push: + pull_request: + +name: "Format checks" +permissions: {} + +jobs: + shellcheck: + name: Shellcheck + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Run ShellCheck + uses: ludeeus/action-shellcheck@master + with: + # shellcheck doesn't have good support for zsh, so we're ignoring this + ignore_paths: >- + *.zsh + severity: error + + - name: Run ShellCheck Warnings + uses: ludeeus/action-shellcheck@master + with: + ignore_paths: >- + ./etc/completion.zsh + ./etc/completion.bash + ./etc/win-ci/cygwin-build-iconv.sh + severity: warning diff --git a/bin/ci b/bin/ci index 03d8a20a19e4..46fcc099c574 100755 --- a/bin/ci +++ b/bin/ci @@ -1,14 +1,14 @@ #!/bin/sh fail() { - echo "${@}" >&2 + echo "${*}" >&2 exit 1 } on_tag() { if [ -n "$CURRENT_TAG" ]; then - echo "${@}" - eval "${@}" + echo "${*}" + eval "${*}" return $? else return 0 @@ -20,7 +20,7 @@ fail_on_error() { exit=$? if [ "$exit" -ne "0" ]; then - fail "${@} exited with $exit" + fail "${*} exited with $exit" fi return 0 @@ -50,8 +50,8 @@ on_os() { verify_environment if [ "$TRAVIS_OS_NAME" = "$os" ]; then - echo "${@}" - eval "${@}" + echo "${*}" + eval "${*}" return $? else return 0 @@ -62,17 +62,17 @@ on_os() { } on_linux() { - fail_on_error on_os "linux" "${@}" + fail_on_error on_os "linux" "${*}" } on_osx() { - fail_on_error on_os "osx" "${@}" + fail_on_error on_os "osx" "${*}" } on_nix_shell_eval() { if [ -n "$CI_NIX_SHELL" ]; then - echo "${@}" - eval "${@}" + echo "${*}" + eval "${*}" return $? else return 0 @@ -80,12 +80,12 @@ on_nix_shell_eval() { } on_nix_shell() { - fail_on_error on_nix_shell_eval "${@}" + fail_on_error on_nix_shell_eval "${*}" } on_github() { if [ "$GITHUB_ACTIONS" = "true" ]; then - eval "${@}" + eval "${*}" return $? else return 0 @@ -153,7 +153,7 @@ prepare_build() { # Install a recent bash version for nix-shell. # macos ships with an ancient one. - if [ `uname` = "Darwin" ]; then + if [ "$(uname)" = "Darwin" ]; then on_nix_shell "brew install bash" fi # initialize nix environment @@ -172,7 +172,7 @@ prepare_build() { verify_version() { # If building a tag, check it matches with file - FILE_VERSION=`cat ./src/VERSION` + FILE_VERSION=$(cat ./src/VERSION) if [ "$FILE_VERSION" != "$CURRENT_TAG" ] then @@ -205,8 +205,8 @@ with_build_env() { on_linux docker run \ --rm -t \ - -u $(id -u) \ - -v $PWD:/mnt \ + -u "$(id -u)" \ + -v "$PWD":/mnt \ -v /etc/passwd:/etc/passwd \ -v /etc/group:/etc/group \ -w /mnt \ @@ -222,6 +222,7 @@ with_build_env() { CRYSTAL_CACHE_DIR="/tmp/crystal" \ /bin/sh -c "'$command'" + # shellcheck disable=SC2086 on_nix_shell nix-shell --pure $CI_NIX_SHELL_ARGS --run "'TZ=$TZ $command'" on_github echo "::endgroup::" @@ -254,7 +255,7 @@ case $command in prepare_build ;; with_build_env) - target_command="${@}" + target_command="${*}" with_build_env "$target_command" ;; build) diff --git a/bin/crystal b/bin/crystal index ad5e3357c985..ef8710c4ff93 100755 --- a/bin/crystal +++ b/bin/crystal @@ -175,7 +175,7 @@ fi # CRYSTAL_PATH has all symlinks resolved. In order to avoid issues with duplicate file # paths when the working directory is a symlink, we cd into the current directory # with symlinks resolved as well (see https://github.com/crystal-lang/crystal/issues/12969). -cd "$(realpath "$(pwd)")" +cd "$(realpath "$(pwd)")" || exit case "$(uname -s)" in CYGWIN*|MSYS_NT*|MINGW32_NT*|MINGW64_NT*) diff --git a/scripts/git/pre-commit b/scripts/git/pre-commit index 2624b25a1fd7..f2f1b011667b 100755 --- a/scripts/git/pre-commit +++ b/scripts/git/pre-commit @@ -22,7 +22,9 @@ changed_cr_files=$(git diff --cached --name-only --diff-filter=ACM | grep '\.cr$ if [ -x bin/crystal ]; then # use bin/crystal wrapper when available to run local compiler build + # shellcheck disable=SC2086 exec bin/crystal tool format --check $changed_cr_files >&2 else + # shellcheck disable=SC2086 exec crystal tool format --check $changed_cr_files >&2 fi diff --git a/scripts/release-update.sh b/scripts/release-update.sh index b6216ce3d6df..c0e9fab3d0b2 100755 --- a/scripts/release-update.sh +++ b/scripts/release-update.sh @@ -42,13 +42,13 @@ sed -i -E "s|crystal: \"[0-9.]+\"|crystal: \"$CRYSTAL_VERSION\"|g" .github/workf # Edit shell.nix latestCrystalBinary using nix-prefetch-url --unpack darwin_url="https://github.com/crystal-lang/crystal/releases/download/$CRYSTAL_VERSION/crystal-$CRYSTAL_VERSION-1-darwin-universal.tar.gz" -darwin_sha=$(nix-prefetch-url --unpack $darwin_url) +darwin_sha=$(nix-prefetch-url --unpack "$darwin_url") sed -i -E "s|https://github.com/crystal-lang/crystal/releases/download/[0-9.]+/crystal-[0-9.]+-[0-9]-darwin-universal.tar.gz|$darwin_url|" shell.nix sed -i -E "/darwin-universal\.tar\.gz/ {n;s|sha256:[^\"]+|sha256:$darwin_sha|}" shell.nix linux_url="https://github.com/crystal-lang/crystal/releases/download/$CRYSTAL_VERSION/crystal-$CRYSTAL_VERSION-1-linux-x86_64.tar.gz" -linux_sha=$(nix-prefetch-url --unpack $linux_url) +linux_sha=$(nix-prefetch-url --unpack "$linux_url") sed -i -E "s|https://github.com/crystal-lang/crystal/releases/download/[0-9.]+/crystal-[0-9.]+-[0-9]-linux-x86_64.tar.gz|$linux_url|" shell.nix sed -i -E "/linux-x86_64\.tar\.gz/ {n;s|sha256:[^\"]+|sha256:$linux_sha|}" shell.nix diff --git a/scripts/update-changelog.sh b/scripts/update-changelog.sh index 763e63670f43..f38ac4b8362c 100755 --- a/scripts/update-changelog.sh +++ b/scripts/update-changelog.sh @@ -35,10 +35,10 @@ branch="changelog/$VERSION" current_changelog="CHANGELOG.$VERSION.md" echo "Generating $current_changelog..." -scripts/github-changelog.cr $VERSION > $current_changelog +scripts/github-changelog.cr "$VERSION" > "$current_changelog" echo "Switching to branch $branch" -git switch $branch 2>/dev/null || git switch -c $branch; +git switch "$branch" 2>/dev/null || git switch -c "$branch"; # Write release version into src/VERSION echo "${VERSION}" > src/VERSION @@ -49,8 +49,8 @@ sed -i -E "s/version: .*/version: ${VERSION}/" shard.yml git add shard.yml # Write release date into src/SOURCE_DATE_EPOCH -release_date=$(head -n1 $current_changelog | grep -o -P '(?<=\()[^)]+') -echo "$(date --utc --date="${release_date}" +%s)" > src/SOURCE_DATE_EPOCH +release_date=$(head -n1 "$current_changelog" | grep -o -P '(?<=\()[^)]+') +date --utc --date="${release_date}" +%s > src/SOURCE_DATE_EPOCH git add src/SOURCE_DATE_EPOCH if grep --silent -E "^## \[$VERSION\]" CHANGELOG.md; then @@ -70,7 +70,7 @@ else git add CHANGELOG.md git commit -m "Add changelog for $VERSION" - git push -u upstream $branch + git push -u upstream "$branch" gh pr create --draft --base "$base_branch" \ --body "Preview: https://github.com/crystal-lang/crystal/blob/$branch/CHANGELOG.md" \ diff --git a/scripts/update-distribution-scripts.sh b/scripts/update-distribution-scripts.sh index 467e5b036de5..bccf44acd060 100755 --- a/scripts/update-distribution-scripts.sh +++ b/scripts/update-distribution-scripts.sh @@ -35,14 +35,14 @@ branch="${2:-"ci/update-distribution-scripts"}" git switch -C "$branch" master old_reference=$(sed -n "/distribution-scripts-version:/{n;n;n;p}" .circleci/config.yml | grep -o -P '(?<=default: ")[^"]+') -echo $old_reference..$reference +echo "$old_reference".."$reference" sed -i -E "/distribution-scripts-version:/{n;n;n;s/default: \".*\"/default: \"$reference\"/}" .circleci/config.yml git add .circleci/config.yml message="Updates \`distribution-scripts\` dependency to https://github.com/crystal-lang/distribution-scripts/commit/$reference" -log=$($GIT_DS log $old_reference..$reference --format="%s" | sed "s/.*(/crystal-lang\/distribution-scripts/;s/^/* /;s/)$//") +log=$($GIT_DS log "$old_reference".."$reference" --format="%s" | sed "s/.*(/crystal-lang\/distribution-scripts/;s/^/* /;s/)$//") message=$(printf "%s\n\nThis includes the following changes:\n\n%s" "$message" "$log") git commit -m "Update distribution-scripts" -m "$message" diff --git a/spec/debug/test.sh b/spec/debug/test.sh index f2fd7cb8ac3e..473ff5c77d10 100755 --- a/spec/debug/test.sh +++ b/spec/debug/test.sh @@ -36,11 +36,11 @@ BUILD_DIR=$SCRIPT_ROOT/../../.build crystal=${CRYSTAL_SPEC_COMPILER_BIN:-$SCRIPT_ROOT/../../bin/crystal} debugger=${1:-lldb} driver=$BUILD_DIR/debug_driver -mkdir -p $BUILD_DIR -"$crystal" build $SCRIPT_ROOT/driver.cr -o $driver +mkdir -p "$BUILD_DIR" +"$crystal" build "$SCRIPT_ROOT"/driver.cr -o "$driver" -$driver $SCRIPT_ROOT/top_level.cr $debugger -$driver $SCRIPT_ROOT/strings.cr $debugger -$driver $SCRIPT_ROOT/arrays.cr $debugger -$driver $SCRIPT_ROOT/blocks.cr $debugger -$driver $SCRIPT_ROOT/large_enums.cr $debugger +$driver "$SCRIPT_ROOT"/top_level.cr "$debugger" +$driver "$SCRIPT_ROOT"/strings.cr "$debugger" +$driver "$SCRIPT_ROOT"/arrays.cr "$debugger" +$driver "$SCRIPT_ROOT"/blocks.cr "$debugger" +$driver "$SCRIPT_ROOT"/large_enums.cr "$debugger" diff --git a/spec/generate_wasm32_spec.sh b/spec/generate_wasm32_spec.sh index a6388e0cc8e4..8f77a9da21fb 100755 --- a/spec/generate_wasm32_spec.sh +++ b/spec/generate_wasm32_spec.sh @@ -24,7 +24,7 @@ set +x WORK_DIR=$(mktemp -d) function cleanup { - rm -rf $WORK_DIR + rm -rf "$WORK_DIR" } trap cleanup EXIT @@ -39,8 +39,8 @@ echo for spec in $(find "spec/std" -type f -iname "*_spec.cr" | LC_ALL=C sort); do require="require \"./${spec##spec/}\"" - target=$WORK_DIR"/"$spec".wasm" - mkdir -p $(dirname "$target") + target="$WORK_DIR/$spec.wasm" + mkdir -p "$(dirname "$target")" if ! output=$(bin/crystal build "$spec" -o "$target" --target wasm32-wasi 2>&1); then if [[ "$output" =~ "execution of command failed" ]]; then diff --git a/spec/llvm-ir/test.sh b/spec/llvm-ir/test.sh index 48a8f38d4d8b..bfc3ee064242 100755 --- a/spec/llvm-ir/test.sh +++ b/spec/llvm-ir/test.sh @@ -9,31 +9,32 @@ SCRIPT_PATH="$(realpath "$0")" SCRIPT_ROOT="$(dirname "$SCRIPT_PATH")" BUILD_DIR=$SCRIPT_ROOT/../../.build -LLVM_CONFIG="$(basename $($SCRIPT_ROOT/../../src/llvm/ext/find-llvm-config))" +LLVM_CONFIG="$(basename "$("$SCRIPT_ROOT"/../../src/llvm/ext/find-llvm-config)")" FILE_CHECK=FileCheck-"${LLVM_CONFIG#llvm-config-}" crystal=${CRYSTAL_SPEC_COMPILER_BIN:-$SCRIPT_ROOT/../../bin/crystal} -mkdir -p $BUILD_DIR +mkdir -p "$BUILD_DIR" function test() { - echo "test: $@" + echo "test: $*" input_cr="$SCRIPT_ROOT/$1" output_ll="$BUILD_DIR/${1%.cr}.ll" - compiler_options="$2" + # FIXME: unused variable + # compiler_options="$2" check_prefix="${3+--check-prefix $3}" # $BUILD_DIR/test-ir is never used # pushd $BUILD_DIR + $output_ll is a workaround due to the fact that we can't control # the filename generated by --emit=llvm-ir - "$crystal" build --single-module --no-color --emit=llvm-ir $2 -o $BUILD_DIR/test-ir $input_cr - $FILE_CHECK $input_cr --input-file $output_ll $check_prefix + "$crystal" build --single-module --no-color --emit=llvm-ir "$2" -o "$BUILD_DIR"/test-ir "$input_cr" + $FILE_CHECK "$input_cr" --input-file "$output_ll" "$check_prefix" - rm $BUILD_DIR/test-ir.o - rm $output_ll + rm "$BUILD_DIR"/test-ir.o + rm "$output_ll" } -pushd $BUILD_DIR >/dev/null +pushd "$BUILD_DIR" >/dev/null test argless-initialize-debug-loc.cr "--cross-compile --target x86_64-unknown-linux-gnu --prelude=empty" test proc-call-debug-loc.cr "--cross-compile --target x86_64-unknown-linux-gnu --prelude=empty" diff --git a/src/llvm/ext/find-llvm-config b/src/llvm/ext/find-llvm-config index 5aa381aaf13b..eaceefda81be 100755 --- a/src/llvm/ext/find-llvm-config +++ b/src/llvm/ext/find-llvm-config @@ -2,15 +2,16 @@ if ! LLVM_CONFIG=$(command -v "$LLVM_CONFIG"); then llvm_config_version=$(llvm-config --version 2>/dev/null) - for version in $(cat "$(dirname $0)/llvm-versions.txt"); do + # shellcheck disable=SC2013 + for version in $(cat "$(dirname "$0")/llvm-versions.txt"); do LLVM_CONFIG=$( - ([ "${llvm_config_version#$version}" != "$llvm_config_version" ] && command -v llvm-config) || \ - command -v llvm-config-${version%.*} || \ - command -v llvm-config-$version || \ - command -v llvm-config${version%.*}${version#*.} || \ - command -v llvm-config${version%.*} || \ - command -v llvm-config$version || \ - command -v llvm${version%.*}-config) + ([ "${llvm_config_version#"$version"}" != "$llvm_config_version" ] && command -v llvm-config) || \ + command -v llvm-config-"${version%.*}" || \ + command -v llvm-config-"$version" || \ + command -v "llvm-config${version%.*}${version#*.}" || \ + command -v llvm-config"${version%.*}" || \ + command -v llvm-config"$version" || \ + command -v llvm"${version%.*}"-config) [ "$LLVM_CONFIG" ] && break done fi @@ -26,6 +27,6 @@ if [ "$LLVM_CONFIG" ]; then esac else printf "Error: Could not find location of llvm-config. Please specify path in environment variable LLVM_CONFIG.\n" >&2 - printf "Supported LLVM versions: $(cat "$(dirname $0)/llvm-versions.txt" | sed 's/\.0//g')\n" >&2 + printf "Supported LLVM versions: %s\n" "$(sed 's/\.0//g' "$(dirname "$0")/llvm-versions.txt")" >&2 exit 1 fi