From 39f8080457f35cc57cbb485a54e13f3eb64c50c7 Mon Sep 17 00:00:00 2001 From: Eric Arellano Date: Tue, 14 May 2019 06:21:06 -0700 Subject: [PATCH] Add `shellcheck.py` and apply first round of fixes (#7698) [Shellcheck](https://www.shellcheck.net) is a phenomenal linter for bash scripts. We have a non-trivial amount of bash code, so any additional help we can get to ensure quality is useful. This PR only takes shellcheck's suggestions when obviously correct. More complex changes are left for followup PRs, after which we can start to require shellcheck in CI. --- build-support/bin/BUILD | 9 ++ build-support/bin/check_clippy.sh | 2 +- build-support/bin/check_packages.sh | 8 +- build-support/bin/check_rust_formatting.sh | 14 +-- .../bin/check_rust_target_headers.sh | 6 +- build-support/bin/check_shell.sh | 6 +- build-support/bin/ci.sh | 29 +++--- build-support/bin/contributors.sh | 1 + build-support/bin/download_binary.sh | 5 +- .../bin/get_ci_bootstrapped_pants_pex.sh | 2 +- .../bin/get_failing_travis_targets_for_pr.sh | 4 +- build-support/bin/install_aws_cli_for_ci.sh | 2 +- build-support/bin/install_git_hooks.sh | 14 +-- build-support/bin/isort.sh | 5 +- build-support/bin/native/bootstrap_cffi.sh | 1 + build-support/bin/native/bootstrap_code.sh | 11 ++- build-support/bin/native/bootstrap_rust.sh | 2 + build-support/bin/publish_docs.sh | 14 +-- build-support/bin/release-changelog-helper.sh | 18 ++-- build-support/bin/release.sh | 96 +++++++++++-------- build-support/bin/shellcheck.py | 46 +++++++++ build-support/common.sh | 7 +- build-support/githooks/prepare-commit-msg | 4 +- build-support/pants_venv | 25 +++-- build-support/python/clean.sh | 14 +-- build-support/virtualenv | 16 ++-- pants | 26 ++--- pants2 | 4 +- src/docs/publish_via_git.sh | 8 +- 29 files changed, 246 insertions(+), 153 deletions(-) create mode 100755 build-support/bin/shellcheck.py diff --git a/build-support/bin/BUILD b/build-support/bin/BUILD index 838f7a8da84..3e0db3c97b3 100644 --- a/build-support/bin/BUILD +++ b/build-support/bin/BUILD @@ -33,3 +33,12 @@ python_binary( ], compatibility = ['CPython>=3.6'], ) + +python_binary( + name = 'shellcheck', + sources = 'shellcheck.py', + dependencies = [ + ':common', + ], + compatibility = ['CPython>=3.6'], +) diff --git a/build-support/bin/check_clippy.sh b/build-support/bin/check_clippy.sh index 4f9b6049b4b..0b195401408 100755 --- a/build-support/bin/check_clippy.sh +++ b/build-support/bin/check_clippy.sh @@ -3,6 +3,6 @@ set -e REPO_ROOT="$(git rev-parse --show-toplevel)" -cd ${REPO_ROOT} +cd "${REPO_ROOT}" ./build-support/bin/native/cargo clippy --manifest-path="${REPO_ROOT}/src/rust/engine/Cargo.toml" --all diff --git a/build-support/bin/check_packages.sh b/build-support/bin/check_packages.sh index 2a7bbb748c0..13d3ad00b53 100755 --- a/build-support/bin/check_packages.sh +++ b/build-support/bin/check_packages.sh @@ -4,19 +4,19 @@ set -euo pipefail IFS=$'\n\t' REPO_ROOT="$(git rev-parse --show-toplevel)" -cd ${REPO_ROOT} +cd "${REPO_ROOT}" DIRS_TO_CHECK=("$@") -non_empty_files=$(find ${DIRS_TO_CHECK[@]} -type f -name "__init__.py" -not -empty) +non_empty_files=$(find "${DIRS_TO_CHECK[@]}" -type f -name "__init__.py" -not -empty) bad_files=() for package_file in ${non_empty_files} do - if [[ "$(sed -E -e 's/^[[:space:]]+//' -e 's/[[:space:]]+$//' ${package_file})" != \ + if [[ "$(sed -E -e 's/^[[:space:]]+//' -e 's/[[:space:]]+$//' "${package_file}")" != \ "__import__('pkg_resources').declare_namespace(__name__)" ]] then - bad_files+=(${package_file}) + bad_files+=("${package_file}") fi done diff --git a/build-support/bin/check_rust_formatting.sh b/build-support/bin/check_rust_formatting.sh index 43be728e4d3..18e6c9e00a4 100755 --- a/build-support/bin/check_rust_formatting.sh +++ b/build-support/bin/check_rust_formatting.sh @@ -36,7 +36,7 @@ done NATIVE_ROOT="${REPO_ROOT}/src/rust/engine" cmd=( - ${REPO_ROOT}/build-support/bin/native/cargo fmt --all -- + "${REPO_ROOT}/build-support/bin/native/cargo" fmt --all -- ) if [[ "${check}" == "true" ]]; then cmd=("${cmd[@]}" "--check") @@ -44,17 +44,17 @@ fi bad_files=( $( - cd "${NATIVE_ROOT}" + cd "${NATIVE_ROOT}" || exit "${PIPESTATUS[0]}" # Ensure generated code is present since `cargo fmt` needs to do enough parsing to follow use's # and these will land in generated code. echo >&2 "Ensuring generated code is present for downstream formatting checks..." - ${REPO_ROOT}/build-support/bin/native/cargo check -p bazel_protos + "${REPO_ROOT}/build-support/bin/native/cargo" check -p bazel_protos - ${cmd[@]} | \ + "${cmd[@]}" | \ awk '$0 ~ /^Diff in/ {print $3}' | \ sort -u - exit ${PIPESTATUS[0]} + exit "${PIPESTATUS[0]}" ) ) exit_code=$? @@ -63,7 +63,7 @@ if [[ ${exit_code} -ne 0 ]]; then if [[ "${check}" == "true" ]]; then echo >&2 "The following rust files were incorrectly formatted, run \`$0 -f\` to reformat them:" for bad_file in ${bad_files[*]}; do - echo >&2 ${bad_file} + echo >&2 "${bad_file}" done else cat << EOF >&2 @@ -71,7 +71,7 @@ An error occurred while checking the formatting of rust files. Try running \`(cd "${NATIVE_ROOT}" && ${cmd[@]})\` to investigate. Its error is: EOF - cd "${NATIVE_ROOT}" && ${cmd[@]} >/dev/null + cd "${NATIVE_ROOT}" && "${cmd[@]}" >/dev/null fi exit 1 fi diff --git a/build-support/bin/check_rust_target_headers.sh b/build-support/bin/check_rust_target_headers.sh index 3b885f49a71..cc6c6473814 100755 --- a/build-support/bin/check_rust_target_headers.sh +++ b/build-support/bin/check_rust_target_headers.sh @@ -6,8 +6,10 @@ cargo="${REPO_ROOT}/build-support/bin/native/cargo" "${cargo}" ensure-installed --package cargo-ensure-prefix --version 0.1.3 -out="$("${cargo}" ensure-prefix --manifest-path="${REPO_ROOT}/src/rust/engine/Cargo.toml" --prefix-path="${REPO_ROOT}/build-support/rust-target-prefix.txt" --all --exclude=bazel_protos)" -if [[ $? -ne 0 ]]; then +if ! out="$("${cargo}" ensure-prefix \ + --manifest-path="${REPO_ROOT}/src/rust/engine/Cargo.toml" \ + --prefix-path="${REPO_ROOT}/build-support/rust-target-prefix.txt" \ + --all --exclude=bazel_protos)"; then echo >&2 "Rust targets didn't have correct prefix:" echo >&2 "${out}" exit 1 diff --git a/build-support/bin/check_shell.sh b/build-support/bin/check_shell.sh index e03473eb727..360dd709ef6 100755 --- a/build-support/bin/check_shell.sh +++ b/build-support/bin/check_shell.sh @@ -1,5 +1,9 @@ #!/bin/bash -eu -bad_output="$(find * -name '*.sh' -print0 | xargs -0 grep '^ *\(readonly\|declare\) .*\(\$(\|`\)' || :)" + +# shellcheck disable=SC2016 +bad_output="$(find ./* -name '*.sh' -print0 \ + | xargs -0 grep '^ *\(readonly\|declare\) .*\(\$(\|`\)' \ + || :)" if [[ -n "${bad_output}" ]]; then echo >&2 "Found bash files with readonly variables defined by invoking subprocesses." diff --git a/build-support/bin/ci.sh b/build-support/bin/ci.sh index 602c400113a..baf3d3a68ed 100755 --- a/build-support/bin/ci.sh +++ b/build-support/bin/ci.sh @@ -4,8 +4,8 @@ # fails the build. set -o pipefail -REPO_ROOT=$(cd $(dirname "${BASH_SOURCE[0]}") && cd "$(git rev-parse --show-toplevel)" && pwd) -cd ${REPO_ROOT} +REPO_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")" && cd "$(git rev-parse --show-toplevel)" && pwd) +cd "${REPO_ROOT}" || exit 1 source build-support/common.sh @@ -85,11 +85,11 @@ while getopts "h27fxbmrjlpeasu:ny:ci:tz" opt; do *) usage "Invalid option: -${OPTARG}" ;; esac done -shift $((${OPTIND} - 1)) +shift $((OPTIND - 1)) echo -if [[ $# > 0 ]]; then - banner "CI BEGINS: $@" +if [[ $# -gt 0 ]]; then + banner "CI BEGINS: $*" else banner "CI BEGINS" fi @@ -106,7 +106,7 @@ export PANTS_DEV=1 # We only want to output failures and skips. # See https://docs.pytest.org/en/latest/usage.html#detailed-summary-report. -export PYTEST_PASSTHRU_ARGS="-q -rfa" +export PYTEST_PASSTHRU_ARGS=(-q -rfa) # Determine the Python version to use for bootstrapping pants.pex. This would usually not be # necessary to set when developing locally, because the `./pants` and `./pants2` scripts set @@ -122,6 +122,7 @@ else fi export PY="${PY:-python${py_major_minor}}" +# shellcheck disable=SC2016 export PANTS_PYTHON_SETUP_INTERPRETER_CONSTRAINTS="${PANTS_PYTHON_SETUP_INTERPRETER_CONSTRAINTS:-['CPython==${py_major_minor}.*']}" banner "Setting interpreter constraints to ${PANTS_PYTHON_SETUP_INTERPRETER_CONSTRAINTS}" @@ -196,7 +197,7 @@ if [[ "${run_internal_backends:-false}" == "true" ]]; then start_travis_section "BackendTests" "Running internal backend python tests" ( ./pants.pex test.pytest \ - pants-plugins/src/python:: pants-plugins/tests/python:: -- ${PYTEST_PASSTHRU_ARGS} + pants-plugins/src/python:: pants-plugins/tests/python:: -- "${PYTEST_PASSTHRU_ARGS[@]}" ) || die "Internal backend python test failure" end_travis_section fi @@ -208,8 +209,8 @@ if [[ "${run_python:-false}" == "true" ]]; then start_travis_section "CoreTests" "Running core python tests${shard_desc}" ( ./pants.pex --tag='-integration' test.pytest --chroot \ - --test-pytest-test-shard=${python_unit_shard} \ - src/python:: tests/python:: -- ${PYTEST_PASSTHRU_ARGS} + "--test-pytest-test-shard=${python_unit_shard}" \ + src/python:: tests/python:: -- "${PYTEST_PASSTHRU_ARGS[@]}" ) || die "Core python test failure" end_travis_section fi @@ -221,8 +222,8 @@ if [[ "${run_contrib:-false}" == "true" ]]; then start_travis_section "ContribTests" "Running contrib python tests${shard_desc}" ( ./pants.pex --exclude-target-regexp='.*/testprojects/.*' test.pytest \ - --test-pytest-test-shard=${python_contrib_shard} \ - contrib:: -- ${PYTEST_PASSTHRU_ARGS} + "--test-pytest-test-shard=${python_contrib_shard}" \ + contrib:: -- "${PYTEST_PASSTHRU_ARGS[@]}" ) || die "Contrib python test failure" end_travis_section fi @@ -269,7 +270,7 @@ if [[ "${test_platform_specific_behavior:-false}" == 'true' ]]; then "Running platform-specific testing on platform: $(uname)" ( ./pants.pex --tag='+platform_specific_behavior' test \ - src/python/:: tests/python:: -- ${PYTEST_PASSTHRU_ARGS} + src/python/:: tests/python:: -- "${PYTEST_PASSTHRU_ARGS[@]}" ) || die "Pants platform-specific test failure" end_travis_section fi @@ -282,8 +283,8 @@ if [[ "${run_integration:-false}" == "true" ]]; then start_travis_section "IntegrationTests" "Running Pants Integration tests${shard_desc}" ( ./pants.pex --tag='+integration' test.pytest \ - --test-pytest-test-shard=${python_intg_shard} \ - src/python:: tests/python:: -- ${PYTEST_PASSTHRU_ARGS} + "--test-pytest-test-shard=${python_intg_shard}" \ + src/python:: tests/python:: -- "${PYTEST_PASSTHRU_ARGS[@]}" ) || die "Pants Integration test failure" end_travis_section fi diff --git a/build-support/bin/contributors.sh b/build-support/bin/contributors.sh index 0f5c373b29c..6a6f2b1daf8 100755 --- a/build-support/bin/contributors.sh +++ b/build-support/bin/contributors.sh @@ -3,6 +3,7 @@ REPO_ROOT="$(git rev-parse --show-toplevel)" cd "$REPO_ROOT" || exit 1 +# shellcheck source=build-support/common.sh source "${REPO_ROOT}/build-support/common.sh" function usage() { diff --git a/build-support/bin/download_binary.sh b/build-support/bin/download_binary.sh index 9c0043edf22..9bee84d3b3a 100755 --- a/build-support/bin/download_binary.sh +++ b/build-support/bin/download_binary.sh @@ -2,10 +2,11 @@ # This script wraps the main() method in binary_util.py. -REPO_ROOT=$(cd $(dirname "${BASH_SOURCE[0]}") && cd ../.. && pwd -P) +REPO_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")" && cd ../.. && pwd -P) BINARY_HELPER_SCRIPT="${REPO_ROOT}/src/python/pants/binaries/binary_util.py" +# shellcheck source=build-support/pants_venv source "${REPO_ROOT}/build-support/pants_venv" activate_pants_venv 1>&2 -PYTHONPATH="${REPO_ROOT}/src/python:${PYTHONPATH}" python "$BINARY_HELPER_SCRIPT" $@ +PYTHONPATH="${REPO_ROOT}/src/python:${PYTHONPATH}" python "$BINARY_HELPER_SCRIPT" "$@" diff --git a/build-support/bin/get_ci_bootstrapped_pants_pex.sh b/build-support/bin/get_ci_bootstrapped_pants_pex.sh index 30608491ba8..00b067e608e 100755 --- a/build-support/bin/get_ci_bootstrapped_pants_pex.sh +++ b/build-support/bin/get_ci_bootstrapped_pants_pex.sh @@ -12,7 +12,7 @@ BOOTSTRAPPED_PEX_URL=s3://${BOOTSTRAPPED_PEX_BUCKET}/${BOOTSTRAPPED_PEX_KEY} # First check that there's only one version of the object on S3, to detect malicious overwrites. NUM_VERSIONS=$(aws --no-sign-request --region us-east-1 s3api list-object-versions \ - --bucket ${BOOTSTRAPPED_PEX_BUCKET} --prefix ${BOOTSTRAPPED_PEX_KEY} --max-items 2 \ + --bucket "${BOOTSTRAPPED_PEX_BUCKET}" --prefix "${BOOTSTRAPPED_PEX_KEY}" --max-items 2 \ | jq '.Versions | length') [ "${NUM_VERSIONS}" == "1" ] || (echo "Error: Found ${NUM_VERSIONS} versions for ${BOOTSTRAPPED_PEX_URL}" && exit 1) diff --git a/build-support/bin/get_failing_travis_targets_for_pr.sh b/build-support/bin/get_failing_travis_targets_for_pr.sh index 8e935bb8314..81a9fec89ee 100755 --- a/build-support/bin/get_failing_travis_targets_for_pr.sh +++ b/build-support/bin/get_failing_travis_targets_for_pr.sh @@ -11,12 +11,12 @@ mkdir -p logs/jobs curl=(curl -s -S -H 'Travis-API-Version: 3') "${curl[@]}" 'https://api.travis-ci.org/repo/pantsbuild%2Fpants/builds?event_type=pull_request&limit=100&sort_by=finished_at:desc' > logs/search -jobs="$(cat logs/search | jq "[ .builds[] | select(.pull_request_number == ${pull}) ][0] | .jobs[].id")" +jobs="$(jq "[ .builds[] | select(.pull_request_number == ${pull}) ][0] | .jobs[].id" logs/search)" targets=() for job in ${jobs}; do mkdir -p "logs/jobs/${job}" "${curl[@]}" "https://api.travis-ci.org/job/${job}" >"logs/jobs/${job}/info" - state="$(cat logs/jobs/${job}/info | jq -r '.state')" + state="$(jq -r '.state' "logs/jobs/${job}/info")" case "${state}" in "passed") continue diff --git a/build-support/bin/install_aws_cli_for_ci.sh b/build-support/bin/install_aws_cli_for_ci.sh index 2db14def841..02a235f74e2 100755 --- a/build-support/bin/install_aws_cli_for_ci.sh +++ b/build-support/bin/install_aws_cli_for_ci.sh @@ -21,7 +21,7 @@ if [[ ! -x "${AWS_CLI_BIN}" ]]; then TMPDIR=$(mktemp -d) - pushd ${TMPDIR} + pushd "${TMPDIR}" curl "https://s3.amazonaws.com/aws-cli/awscli-bundle.zip" -o "awscli-bundle.zip" unzip awscli-bundle.zip diff --git a/build-support/bin/install_git_hooks.sh b/build-support/bin/install_git_hooks.sh index c3e6cb57a4b..74ca3e757c8 100755 --- a/build-support/bin/install_git_hooks.sh +++ b/build-support/bin/install_git_hooks.sh @@ -9,7 +9,7 @@ REPO_ROOT="$(git rev-parse --show-toplevel)" HOOK_DIR="${GIT_DIR:-${REPO_ROOT}/.git}/hooks" HOOK_SRC_DIR="${REPO_ROOT}/build-support/githooks" -HOOK_NAMES="$(ls ${HOOK_SRC_DIR})" +HOOK_NAMES="$(ls "${HOOK_SRC_DIR}")" RELPATH_PREFIX="$(cat << EOF | python import os @@ -24,8 +24,8 @@ function install_hook() { RELPATH="${RELPATH_PREFIX}/${HOOK}" ( cd "${HOOK_DIR}" && \ - rm -f ${HOOK} && \ - ln -s "${RELPATH}" ${HOOK} && \ + rm -f "${HOOK}" && \ + ln -s "${RELPATH}" "${HOOK}" && \ echo "${HOOK} hook linked to $(pwd)/${HOOK}"; ) } @@ -38,16 +38,16 @@ function ensure_hook() { if [[ ! -e "${HOOK_DST}" ]] then - install_hook ${HOOK} + install_hook "${HOOK}" else if cmp --quiet "${HOOK_SRC}" "${HOOK_DST}" then echo "${HOOK} hook up to date." else - read -p "A ${HOOK} hook already exists, replace with ${HOOK_SRC}? [Yn]" ok + read -rp "A ${HOOK} hook already exists, replace with ${HOOK_SRC}? [Yn]" ok if [[ "${ok:-Y}" =~ ^[yY]([eE][sS])?$ ]] then - install_hook ${HOOK} + install_hook "${HOOK}" else echo "${HOOK} hook not installed" exit 1 @@ -58,5 +58,5 @@ function ensure_hook() { for HOOK in ${HOOK_NAMES}; do - ensure_hook ${HOOK} + ensure_hook "${HOOK}" done diff --git a/build-support/bin/isort.sh b/build-support/bin/isort.sh index 10a11469986..81ced8b16be 100755 --- a/build-support/bin/isort.sh +++ b/build-support/bin/isort.sh @@ -1,8 +1,9 @@ #!/usr/bin/env bash REPO_ROOT="$(git rev-parse --show-toplevel)" -cd ${REPO_ROOT} +cd "${REPO_ROOT}" || exit 1 +# shellcheck source=build-support/common.sh source build-support/common.sh function usage() { @@ -34,7 +35,7 @@ do done # If changes were made or issues found, output with leading whitespace trimmed. -output="$(./pants --changed-parent="$(git_merge_base)" fmt.isort -- ${isort_args[@]})" +output="$(./pants --changed-parent="$(git_merge_base)" fmt.isort -- "${isort_args[@]}")" echo "${output}" | grep -Eo '(ERROR).*$' && exit 1 echo "${output}" | grep -Eo '(Fixing).*$' exit 0 diff --git a/build-support/bin/native/bootstrap_cffi.sh b/build-support/bin/native/bootstrap_cffi.sh index 0a54fb97893..247c9bc20ea 100755 --- a/build-support/bin/native/bootstrap_cffi.sh +++ b/build-support/bin/native/bootstrap_cffi.sh @@ -4,6 +4,7 @@ set -e REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && cd ../../.. && pwd -P)" +# shellcheck source=build-support/pants_venv source "${REPO_ROOT}/build-support/pants_venv" if (( $# != 2 )); then diff --git a/build-support/bin/native/bootstrap_code.sh b/build-support/bin/native/bootstrap_code.sh index 7b3b746505b..7b191017686 100644 --- a/build-support/bin/native/bootstrap_code.sh +++ b/build-support/bin/native/bootstrap_code.sh @@ -5,7 +5,9 @@ REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && cd ../../.. && pwd -P)" # Exposes: # + die: Exit in a failure state and optionally log an error message to the console. # + fingerprint_data: Fingerprints the data on stdin. -source ${REPO_ROOT}/build-support/common.sh + +# shellcheck source=build-support/common.sh +source "${REPO_ROOT}/build-support/common.sh" KERNEL=$(uname -s | tr '[:upper:]' '[:lower:]') case "${KERNEL}" in @@ -40,7 +42,7 @@ function calculate_current_hash() { # # Assumes we're in the venv that will be used to build the native engine. ( - cd ${REPO_ROOT} + cd "${REPO_ROOT}" || exit 1 (echo "${MODE_FLAG}" echo "${RUST_TOOLCHAIN}" uname @@ -69,7 +71,8 @@ function _build_native_code() { function bootstrap_native_code() { # Bootstraps the native code only if needed. - local native_engine_version="$(calculate_current_hash)" + local native_engine_version + native_engine_version="$(calculate_current_hash)" local engine_version_hdr="engine_version: ${native_engine_version}" local target_binary="${NATIVE_ENGINE_CACHE_DIR}/${native_engine_version}/${NATIVE_ENGINE_BINARY}" local target_binary_metadata="${target_binary}.metadata" @@ -90,7 +93,7 @@ function bootstrap_native_code() { target_binary="${NATIVE_ENGINE_CACHE_DIR}/${native_engine_version}/${NATIVE_ENGINE_BINARY}" target_binary_metadata="${target_binary}.metadata" - mkdir -p "$(dirname ${target_binary})" + mkdir -p "$(dirname "${target_binary}")" cp "${native_binary}" "${target_binary}" local -r metadata_file=$(mktemp -t pants.native_engine.metadata.XXXXXX) diff --git a/build-support/bin/native/bootstrap_rust.sh b/build-support/bin/native/bootstrap_rust.sh index 7fbe66c8969..77cba49591d 100644 --- a/build-support/bin/native/bootstrap_rust.sh +++ b/build-support/bin/native/bootstrap_rust.sh @@ -5,6 +5,8 @@ REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && cd ../../.. && pwd -P)" # Exposes: # + log: Log a message to the console. # + fingerprint_data: Fingerprints the data on stdin. + +# shellcheck source=build-support/common.sh source "${REPO_ROOT}/build-support/common.sh" rust_toolchain_root="${CACHE_ROOT}/rust" diff --git a/build-support/bin/publish_docs.sh b/build-support/bin/publish_docs.sh index 0f6cc9213a5..436812a16f5 100755 --- a/build-support/bin/publish_docs.sh +++ b/build-support/bin/publish_docs.sh @@ -10,9 +10,9 @@ GIT_URL="${GIT_URL:-${PANTS_GH_PAGES}}" PANTS_SITE_URL='https://www.pantsbuild.org' VIEW_PUBLISH_URL="${VIEW_PUBLISH_URL:-${PANTS_SITE_URL}}" -REPO_ROOT=$(cd $(dirname "${BASH_SOURCE[0]}") && cd "$(git rev-parse --show-toplevel)" && pwd) +REPO_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")" && cd "$(git rev-parse --show-toplevel)" && pwd) -source ${REPO_ROOT}/build-support/common.sh +source "${REPO_ROOT}/build-support/common.sh" PANTS_EXE="${REPO_ROOT}/pants" @@ -69,10 +69,10 @@ ${PANTS_EXE} sitegen \ function do_open() { if [[ "${preview}" = "true" ]]; then - if which xdg-open &>/dev/null; then - xdg-open $1 - elif which open &>/dev/null; then - open $1 + if command -v xdg-open &>/dev/null; then + xdg-open "$1" + elif command -v open &>/dev/null; then + open "$1" else die "Failed to find an opener on your system for $1" fi @@ -92,7 +92,7 @@ fi if [[ "${publish}" = "true" ]]; then url="${VIEW_PUBLISH_URL}/${publish_path}" if [[ "${publish_confirmed}" != "true" ]] ; then - read -ep "To abort publishing these docs to ${url} press CTRL-C, otherwise press enter to \ + read -rep "To abort publishing these docs to ${url} press CTRL-C, otherwise press enter to \ continue." fi ( diff --git a/build-support/bin/release-changelog-helper.sh b/build-support/bin/release-changelog-helper.sh index 75f7bae66bb..b87b33f3a47 100755 --- a/build-support/bin/release-changelog-helper.sh +++ b/build-support/bin/release-changelog-helper.sh @@ -28,7 +28,7 @@ then help "Too many arguments." elif (( $# == 0 )) then - read -p "What sha was the last release made from?: " LAST_RELEASE_SHA + read -rp "What sha was the last release made from?: " LAST_RELEASE_SHA elif [[ "$1" == "-h" ]] then help @@ -68,16 +68,16 @@ echo "Changes since ${LAST_RELEASE_SHA}:" echo "----------------------------------------------------------------------------------------------------" echo -for sha in `git log --format="format:%H" HEAD ^${LAST_RELEASE_SHA}` +for sha in $(git log --format="format:%H" HEAD "^${LAST_RELEASE_SHA}") do - subject=`git log -1 --format="format:%s" "$sha"` + subject=$(git log -1 --format="format:%s" "$sha") echo "* ${subject}" urls=() urls=( ${urls} $( - git log -1 --oneline ${sha} | \ + git log -1 --oneline "${sha}" | \ grep -Eo "\(#[0-9]+\)" | \ sed -Ee "s|^\(#([0-9]+)\)$|https://github.com/pantsbuild/pants/pull/\1|" ) @@ -85,7 +85,7 @@ do urls=( ${urls} $( - git log -1 ${sha} --format="format:%b" | \ + git log -1 "${sha}" --format="format:%b" | \ grep -E "https?://" | \ sed -Ee "s|^.*(https?://[^ ]+).*$|\1|" | \ grep -v travis-ci.org | \ @@ -93,18 +93,18 @@ do ) ) - for url in ${urls[@]} + for url in "${urls[@]}" do - if echo ${url} | grep github.com | grep -q /issues/ + if echo "${url}" | grep github.com | grep -q /issues/ then issue=${url##*/} echo " \`Issue #${issue} <${url}>\`_" fi done - for url in ${urls[@]} + for url in "${urls[@]}" do - if echo ${url} | grep github.com | grep -q /pull/ + if echo "${url}" | grep github.com | grep -q /pull/ then issue=${url##*/} echo " \`PR #${issue} <${url}>\`_" diff --git a/build-support/bin/release.sh b/build-support/bin/release.sh index 27073414e8b..2e30c6ac5a5 100755 --- a/build-support/bin/release.sh +++ b/build-support/bin/release.sh @@ -4,8 +4,10 @@ set -e -ROOT=$(cd $(dirname "${BASH_SOURCE[0]}") && cd "$(git rev-parse --show-toplevel)" && pwd) -source ${ROOT}/build-support/common.sh +ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")" && cd "$(git rev-parse --show-toplevel)" && pwd) + +# shellcheck source=build-support/common.sh +source "${ROOT}/build-support/common.sh" # Note we parse some options here, but parse most at the bottom. This is due to execution order. # If the option must be used right away, we parse at the top of the script, whereas if it @@ -34,7 +36,7 @@ fi # Note we allow the user to predefine this value so that they may point to a specific interpreter, # e.g. 2.7.13 vs. 2.7.15. export PY="${PY:-${default_interpreter}}" -if ! which "${PY}" >/dev/null; then +if ! command -v "${PY}" >/dev/null; then die "Python interpreter ${PY} not discoverable on your PATH." fi py_major_minor=$(${PY} -c 'import sys; print(".".join(map(str, sys.version_info[0:2])))') @@ -45,7 +47,7 @@ fi export PANTS_PYTHON_SETUP_INTERPRETER_CONSTRAINTS="['${interpreter_constraint}']" function run_local_pants() { - ${ROOT}/pants "$@" + "${ROOT}/pants" "$@" } # NB: Pants core does not have the ability to change its own version, so we compute the @@ -66,12 +68,13 @@ readonly DEPLOY_PANTS_WHEEL_DIR="${DEPLOY_DIR}/${DEPLOY_PANTS_WHEELS_PATH}" # A space-separated list of pants packages to include in any pexes that are built: by default, # only pants core is included. -: ${PANTS_PEX_PACKAGES:="pantsbuild.pants"} +: "${PANTS_PEX_PACKAGES:="pantsbuild.pants"}" # URL from which pex release binaries can be downloaded. -: ${PEX_DOWNLOAD_PREFIX:="https://github.com/pantsbuild/pex/releases/download"} +: "${PEX_DOWNLOAD_PREFIX:="https://github.com/pantsbuild/pex/releases/download"}" -source ${ROOT}/contrib/release_packages.sh +# shellcheck source=contrib/release_packages.sh +source "${ROOT}/contrib/release_packages.sh" function requirement() { package="$1" @@ -105,7 +108,7 @@ function run_packages_script() { cd "${ROOT}" args=("$@") if [[ "${python_two:-false}" == "true" ]]; then - args=("--py2" ${args[@]}) + args=("--py2" "${args[@]}") fi requirements=("$(requirement future)" "$(requirement beautifulsoup4)" "$(requirement configparser)" "$(requirement subprocess32)") run_pex "${requirements[@]}" -- "${ROOT}/src/python/pants/releases/packages.py" "${args[@]}" @@ -122,8 +125,8 @@ function find_pkg() { function pkg_pants_install_test() { local version=$1 shift - local PIP_ARGS="$@" - pip install ${PIP_ARGS} "pantsbuild.pants==${version}" || \ + local PIP_ARGS=("$@") + pip install "${PIP_ARGS[@]}" "pantsbuild.pants==${version}" || \ die "pip install of pantsbuild.pants failed!" execute_packaged_pants_with_internal_backends list src:: || \ die "'pants list src::' failed in venv!" @@ -134,8 +137,8 @@ function pkg_pants_install_test() { function pkg_testinfra_install_test() { local version=$1 shift - local PIP_ARGS="$@" - pip install ${PIP_ARGS} "pantsbuild.pants.testinfra==${version}" && \ + local PIP_ARGS=("$@") + pip install "${PIP_ARGS[@]}" "pantsbuild.pants.testinfra==${version}" && \ python -c "import pants_test" } @@ -177,8 +180,8 @@ function execute_packaged_pants_with_internal_backends() { } function pants_version_reset() { - pushd ${ROOT} > /dev/null - git checkout -- ${VERSION_FILE} + pushd "${ROOT}" > /dev/null + git checkout -- "${VERSION_FILE}" popd > /dev/null unset _PANTS_VERSION_OVERRIDE } @@ -203,15 +206,15 @@ function build_3rdparty_packages() { rm -rf "${DEPLOY_3RDPARTY_WHEEL_DIR}" mkdir -p "${DEPLOY_3RDPARTY_WHEEL_DIR}/${version}" - local req_args="" + local req_args=() for req_file in "${REQUIREMENTS_3RDPARTY_FILES[@]}"; do - req_args="${req_args} -r ${ROOT}/$req_file" + req_args=("${req_args[@]}" -r "${ROOT}/$req_file") done - start_travis_section "3rdparty" "Building 3rdparty whls from ${REQUIREMENTS_3RDPARTY_FILES[@]}" + start_travis_section "3rdparty" "Building 3rdparty whls from ${REQUIREMENTS_3RDPARTY_FILES[*]}" activate_tmp_venv - pip wheel --wheel-dir="${DEPLOY_3RDPARTY_WHEEL_DIR}/${version}" ${req_args} + pip wheel --wheel-dir="${DEPLOY_3RDPARTY_WHEEL_DIR}/${version}" "${req_args[@]}" deactivate end_travis_section @@ -232,7 +235,7 @@ function build_pants_packages() { for package in "${packages[@]}" do ( - wheel=$(find_pkg ${package} ${version} "${ROOT}/dist") && \ + wheel=$(find_pkg "${package}" "${version}" "${ROOT}/dist") && \ cp -p "${wheel}" "${DEPLOY_PANTS_WHEEL_DIR}/${version}" ) || die "Failed to find package ${package}-${version}!" done @@ -261,9 +264,12 @@ function build_fs_util() { } function activate_tmp_venv() { + # Because the venv/bin/activate script's location is dynamic and not located in a fixed + # place, Shellcheck will not be able to find it so we tell Shellcheck to ignore the file. + # shellcheck source=/dev/null VENV_DIR=$(mktemp -d -t pants.XXXXX) && \ - ${ROOT}/build-support/virtualenv $VENV_DIR && \ - source $VENV_DIR/bin/activate + "${ROOT}/build-support/virtualenv" "$VENV_DIR" && \ + source "$VENV_DIR/bin/activate" } function pre_install() { @@ -287,7 +293,7 @@ From there, you can run 'pants' (not './pants') to do some testing. When you're done testing, press enter to continue. EOM - read + read -r fi deactivate } @@ -306,7 +312,8 @@ function install_and_test_packages() { pre_install || die "Failed to setup virtualenv while testing ${NAME}-${VERSION}!" # Avoid caching plugin installs. - export PANTS_PLUGIN_CACHE_DIR=$(mktemp -d -t plugins_cache.XXXXX) + PANTS_PLUGIN_CACHE_DIR=$(mktemp -d -t plugins_cache.XXXXX) + export PANTS_PLUGIN_CACHE_DIR trap "rm -rf ${PANTS_PLUGIN_CACHE_DIR}" EXIT packages=( @@ -317,7 +324,7 @@ function install_and_test_packages() { for package in "${packages[@]}" do start_travis_section "${package}" "Installing and testing package ${package}-${VERSION}" - eval pkg_${package##*\.}_install_test ${PIP_ARGS[@]} || \ + eval pkg_${package##*\.}_install_test "${PIP_ARGS[@]}" || \ die "Failed to install and test package ${package}-${VERSION}!" end_travis_section done @@ -393,8 +400,8 @@ EOM ) get_pgp_keyid &> /dev/null || die "${msg}" echo "Found the following key for release signing:" - $(get_pgp_program) -k $(get_pgp_keyid) - read -p "Is this the correct key? [Yn]: " answer + "$(get_pgp_program)" -k "$(get_pgp_keyid)" + read -rp "Is this the correct key? [Yn]: " answer [[ "${answer:-y}" =~ [Yy]([Ee][Ss])? ]] || die "${msg}" } @@ -410,16 +417,16 @@ function tag_release() { release_version="${PANTS_STABLE_VERSION}" && \ tag_name="release_${release_version}" && \ git tag -f \ - --local-user=$(get_pgp_keyid) \ + "--local-user=$(get_pgp_keyid)" \ -m "pantsbuild.pants release ${release_version}" \ - ${tag_name} && \ - git push -f git@github.com:pantsbuild/pants.git ${tag_name} + "${tag_name}" && \ + git push -f git@github.com:pantsbuild/pants.git "${tag_name}" } function publish_docs_if_master() { branch=$(get_branch) if [[ "${branch}" == "master" ]]; then - ${ROOT}/build-support/bin/publish_docs.sh -p -y + "${ROOT}/build-support/bin/publish_docs.sh" -p -y else echo "Skipping docsite publishing on non-master branch (${branch})." fi @@ -436,7 +443,7 @@ function reversion_whls() { local dest_dir=$2 local output_version=$3 - for whl in `ls -1 "${src_dir}"/*.whl`; do + for whl in $(ls -1 "${src_dir}"/*.whl); do run_local_pants -q run src/python/pants/releases:reversion -- \ --glob='pants/VERSION' \ "${whl}" "${dest_dir}" "${output_version}" \ @@ -479,10 +486,12 @@ function fetch_prebuilt_wheels() { ( cd "${to_dir}" list_prebuilt_wheels | { - while read path_tuple + while read -r path_tuple do - local file_path=$(echo "$path_tuple" | awk -F'\t' '{print $1}') - local url_path=$(echo "$path_tuple" | awk -F'\t' '{print $2}') + local file_path + file_path=$(echo "$path_tuple" | awk -F'\t' '{print $1}') + local url_path + url_path=$(echo "$path_tuple" | awk -F'\t' '{print $2}') echo "${BINARY_BASE_URL}/${url_path}:" local dest="${to_dir}/${file_path}" mkdir -p "$(dirname "${dest}")" @@ -521,7 +530,7 @@ function fetch_and_check_prebuilt_wheels() { local cross_platform="" for package in "${packages[@]}" do - if [[ "${package}" =~ "-none-any.whl" ]] + if [[ "${package}" =~ -none-any.whl ]] then cross_platform="true" fi @@ -550,7 +559,7 @@ function adjust_wheel_platform() { local src_plat="$1" local dst_plat="$2" local dir="$3" - for src_whl in `find "${dir}" -name '*'"${src_plat}.whl"`; do + for src_whl in $(find "${dir}" -name '*'"${src_plat}.whl"); do local dst_whl=${src_whl/$src_plat/$dst_plat} mv -f "${src_whl}" "${dst_whl}" done @@ -561,6 +570,9 @@ function activate_twine() { rm -rf "${venv_dir}" "${ROOT}/build-support/virtualenv" "${venv_dir}" + # Because the venv/bin/activate script's location is dynamic and not located in a fixed + # place, Shellcheck will not be able to find it so we tell Shellcheck to ignore the file. + # shellcheck source=/dev/null source "${venv_dir}/bin/activate" pip install twine } @@ -595,10 +607,10 @@ function build_pex() { # NB: When building locally, we use a platform that does not refer to the ABI version, to # avoid needing to introspect the python ABI for this machine. Darwin) - local platform=("${osx_platform_noabi}") + local platform="${osx_platform_noabi}" ;; Linux) - local platform=("${linux_platform_noabi}") + local platform="${linux_platform_noabi}" ;; *) echo >&2 "Unknown uname" @@ -689,7 +701,7 @@ function publish_packages() { activate_twine trap deactivate RETURN - twine upload --sign --sign-with=$(get_pgp_program) --identity=$(get_pgp_keyid) \ + twine upload --sign "--sign-with=$(get_pgp_program)" "--identity=$(get_pgp_keyid)" \ "${DEPLOY_PANTS_WHEEL_DIR}/${PANTS_STABLE_VERSION}"/*.whl end_travis_section @@ -753,19 +765,19 @@ fi if [[ "${dry_run}" == "true" && "${test_release}" == "true" ]]; then usage "The dry run and test options are mutually exclusive, pick one." elif [[ "${dry_run}" == "true" ]]; then - banner "Performing a dry run release" && \ + banner "Performing a dry run release" ( dry_run_install && \ banner "Dry run release succeeded" ) || die "Dry run release failed." elif [[ "${test_release}" == "true" ]]; then - banner "Installing and testing the latest released packages" && \ + banner "Installing and testing the latest released packages" ( install_and_test_packages "${PANTS_STABLE_VERSION}" && \ banner "Successfully installed and tested the latest released packages" ) || die "Failed to install and test the latest released packages." else - banner "Releasing packages to PyPi" && \ + banner "Releasing packages to PyPi" ( check_origin && check_clean_branch && check_pgp && check_owners && \ publish_packages && tag_release && publish_docs_if_master && \ diff --git a/build-support/bin/shellcheck.py b/build-support/bin/shellcheck.py new file mode 100755 index 00000000000..ac85330406b --- /dev/null +++ b/build-support/bin/shellcheck.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +# Copyright 2019 Pants project contributors (see CONTRIBUTORS.md). +# Licensed under the Apache License, Version 2.0 (see LICENSE). + +import shutil +import subprocess +from glob import glob + +from common import die, green + + +def main() -> None: + ensure_shellcheck_installed() + run_shellcheck() + + +def ensure_shellcheck_installed() -> None: + if shutil.which("shellcheck") is None: + die("`shellcheck` not installed! You may download this through your operating system's " + "package manager, such as brew, apt, or yum. See " + "https://github.com/koalaman/shellcheck#installing.") + + +def run_shellcheck() -> None: + targets = glob("./build-support/bin/**/*.sh", recursive=True) + [ + "./pants", + "./pants2", + "./build-support/common.sh", + "./build-support/pants_intellij.sh", + "./build-support/pants_venv", + "./build-support/virtualenv", + "./build-support/githooks/pre-commit", + "./build-support/githooks/prepare-commit-msg", + "./build-support/python/clean.sh", + ] + command = ["shellcheck", "--shell=bash", "--external-sources"] + targets + try: + subprocess.run(command, check=True) + except subprocess.CalledProcessError: + die("Please fix the above errors and run again.") + else: + green("./pants passed the shellcheck!") + + +if __name__ == "__main__": + main() diff --git a/build-support/common.sh b/build-support/common.sh index 2398e2b80a8..987987ce479 100644 --- a/build-support/common.sh +++ b/build-support/common.sh @@ -1,3 +1,4 @@ +# shellcheck disable=SC2034 CACHE_ROOT=${XDG_CACHE_HOME:-$HOME/.cache}/pants TRAVIS_FOLD_STATE="/tmp/.travis_fold_current" @@ -23,12 +24,12 @@ function green() { } # Initialization for elapsed() -: ${elapsed_start_time:=$(date +'%s')} +: "${elapsed_start_time:=$(date +'%s')}" export elapsed_start_time function elapsed() { now=$(date '+%s') - elapsed_secs=$(( $now - $elapsed_start_time )) + elapsed_secs=$(( now - elapsed_start_time )) echo $elapsed_secs | awk '{printf "%02d:%02d\n",int($1/60), int($1%60)}' } @@ -64,6 +65,6 @@ function fingerprint_data() { function git_merge_base() { # This prints the tracking branch if set and otherwise falls back to local "master". - git rev-parse --symbolic-full-name --abbrev-ref HEAD@{upstream} 2>/dev/null || echo 'master' + git rev-parse --symbolic-full-name --abbrev-ref HEAD@\{upstream\} 2>/dev/null || echo 'master' } diff --git a/build-support/githooks/prepare-commit-msg b/build-support/githooks/prepare-commit-msg index 19602405cb5..1fe474783ad 100755 --- a/build-support/githooks/prepare-commit-msg +++ b/build-support/githooks/prepare-commit-msg @@ -8,9 +8,9 @@ NUM_NON_MD_FILES=$(git status -s --porcelain | grep -v ".\md$" | wc -l | xargs) # The msg source will be "commit" if we were called with --amend. if [ "${COMMIT_MSG_SRC}" != "commit" ] && [ "${NUM_NON_MD_FILES}" == "0" ]; then -cat <> ${COMMIT_MSG_FILEPATH} +cat <> "${COMMIT_MSG_FILEPATH}" # Delete this line to force a full CI run for documentation-only changes. SKIP_FULL_CI # Documentation-only change. EOF -fi \ No newline at end of file +fi diff --git a/build-support/pants_venv b/build-support/pants_venv index 9114d887c86..32299d7a78d 100755 --- a/build-support/pants_venv +++ b/build-support/pants_venv @@ -2,13 +2,15 @@ # Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). # Licensed under the Apache License, Version 2.0 (see LICENSE). -REPO_ROOT=$(cd $(dirname "${BASH_SOURCE[0]}") && cd .. && pwd -P) -source ${REPO_ROOT}/build-support/common.sh +REPO_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")" && cd .. && pwd -P) + +# shellcheck source=build-support/common.sh +source "${REPO_ROOT}/build-support/common.sh" REQUIREMENTS=( - ${REPO_ROOT}/3rdparty/python/requirements.txt - ${REPO_ROOT}/3rdparty/python/twitter/commons/requirements.txt - ${REPO_ROOT}/pants-plugins/3rdparty/python/requirements.txt + "${REPO_ROOT}/3rdparty/python/requirements.txt" + "${REPO_ROOT}/3rdparty/python/twitter/commons/requirements.txt" + "${REPO_ROOT}/pants-plugins/3rdparty/python/requirements.txt" ) venv_dir_prefix="${REPO_ROOT}/build-support/pants_dev_deps" @@ -19,6 +21,9 @@ function venv_dir() { } function activate_venv() { + # Because the venv/bin/activate script's location is dynamic and not located in a fixed + # place, Shellcheck will not be able to find it so we tell Shellcheck to ignore the file. + # shellcheck source=/dev/null source "$(venv_dir)/bin/activate" } @@ -54,20 +59,20 @@ MESSAGE function activate_pants_venv() { fingerprint="" - for req in ${REQUIREMENTS[@]}; do - fingerprint="${fingerprint}$(cat ${req} | fingerprint_data)" + for req in "${REQUIREMENTS[@]}"; do + fingerprint="${fingerprint}$(fingerprint_data < "${req}")" done fingerprint=$(echo "${fingerprint}" | fingerprint_data) BOOTSTRAPPED_FILE="$(venv_dir)/BOOTSTRAPPED.${fingerprint}" - if ! [ -f ${BOOTSTRAPPED_FILE} ]; then + if ! [ -f "${BOOTSTRAPPED_FILE}" ]; then log "Bootstrapping pants_deps with requirements:" # Use -f ${REPO_ROOT}/third_party if patching in local dependencies like so # pip_extra="-f ${REPO_ROOT}/third_party" pip_extra="" - for req in ${REQUIREMENTS[@]}; do + for req in "${REQUIREMENTS[@]}"; do log " ${req}" done @@ -77,7 +82,7 @@ function activate_pants_venv() { # Needed for compilation of native python distributions. ensure_gcc - for req in ${REQUIREMENTS[@]}; do + for req in "${REQUIREMENTS[@]}"; do pip install ${pip_extra} -r "${req}" || \ die "Failed to install requirements from ${req}." done diff --git a/build-support/python/clean.sh b/build-support/python/clean.sh index d26d62626ad..a553e4664b1 100755 --- a/build-support/python/clean.sh +++ b/build-support/python/clean.sh @@ -1,9 +1,9 @@ #!/bin/bash -PANTS_BASE=$(dirname $0)/../.. -rm -rf ${HOME}/.pex -rm -rf ${PANTS_BASE}/build-support/pants_dev_deps.venv -rm -rf ${PANTS_BASE}/build-support/pants_dev_deps.py{2,3}.venv -rm -rf ${PANTS_BASE}/build-support/pants_dev_deps.py{2,3}?.venv -rm -rf ${PANTS_BASE}/.pants.d -find ${PANTS_BASE} -name '*.pyc' | xargs rm -f +PANTS_BASE=$(dirname "$0")/../.. +rm -rf "${HOME}/.pex" +rm -rf "${PANTS_BASE}/build-support/pants_dev_deps.venv" +rm -rf "${PANTS_BASE}/build-support/pants_dev_deps.py{2,3}.venv" +rm -rf "${PANTS_BASE}/build-support/pants_dev_deps.py{2,3}?.venv" +rm -rf "${PANTS_BASE}/.pants.d" +find "${PANTS_BASE}" -name '*.pyc' -print0 | xargs -0 rm -f diff --git a/build-support/virtualenv b/build-support/virtualenv index c87c544634c..e4fdfeac16a 100755 --- a/build-support/virtualenv +++ b/build-support/virtualenv @@ -6,26 +6,28 @@ set -e VIRTUALENV_VERSION=15.2.0 VIRTUALENV_PACKAGE_LOCATION=${VIRTUALENV_PACKAGE_LOCATION:-https://pypi.io/packages/source/v/virtualenv} -REPO_ROOT=$(cd $(dirname "${BASH_SOURCE[0]}") && git rev-parse --show-toplevel) -source ${REPO_ROOT}/build-support/common.sh +REPO_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")" && git rev-parse --show-toplevel) + +# shellcheck source=build-support/common.sh +source "${REPO_ROOT}/build-support/common.sh" # Locate the binary's path to log to user or die gracefully if not found. -if which "${PY}" >/dev/null; then - PY=`which ${PY}` +if command -v "${PY}" >/dev/null; then + PY="$(command -v "${PY}")" else die "No ${PY} interpreter found on the path. Python will not work!" fi log "Using python at ${PY}" -HERE=$(cd `dirname "${BASH_SOURCE[0]}"` && pwd) +HERE=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) if ! [ -f "${HERE}/virtualenv.dist/BOOTSTRAPPED-${VIRTUALENV_VERSION}" ]; then pushd "${HERE}" >/dev/null VIRTUALENV_PACKAGE_FULL_URL="${VIRTUALENV_PACKAGE_LOCATION}/virtualenv-${VIRTUALENV_VERSION}.tar.gz" log "Downloading ${VIRTUALENV_PACKAGE_FULL_URL}..." - curl -#L -O ${VIRTUALENV_PACKAGE_FULL_URL} || \ + curl -#L -O "${VIRTUALENV_PACKAGE_FULL_URL}" || \ die "Failed to download ${VIRTUALENV_PACKAGE_FULL_URL}." - rm -rf virtualenv-${VIRTUALENV_VERSION} && \ + rm -rf virtualenv-${VIRTUALENV_VERSION} tar zxf virtualenv-${VIRTUALENV_VERSION}.tar.gz || \ die "Failed to extract ${VIRTUALENV_PACKAGE_FULL_URL}." # TODO(ksweeney): Checksum diff --git a/pants b/pants index a20bd6c636b..0f6e9ff69f1 100755 --- a/pants +++ b/pants @@ -37,7 +37,7 @@ set -e -HERE=$(cd `dirname "${BASH_SOURCE[0]}"` && pwd) +HERE=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) # Set RUN_PANTS_FROM_PEX to non-empty to cause this wrapper script to delegate directly # to ./pants.pex. We use this in CI to avoid bootstrapping in every shard. @@ -49,11 +49,13 @@ fi # Exposes: # + activate_pants_venv: Activate a virtualenv for pants requirements, creating it if needed. -source ${HERE}/build-support/pants_venv +# shellcheck source=build-support/pants_venv +source "${HERE}/build-support/pants_venv" # Exposes: # + bootstrap_native_code: Builds target-specific native engine binaries. -source ${HERE}/build-support/bin/native/bootstrap_code.sh +# shellcheck source=build-support/bin/native/bootstrap_code.sh +source "${HERE}/build-support/bin/native/bootstrap_code.sh" # Default to using Python 3 if not otherwise specified. export PY="${PY:-python3}" @@ -69,19 +71,19 @@ export PANTS_PYTHON_SETUP_INTERPRETER_CONSTRAINTS="${PANTS_PYTHON_SETUP_INTERPRE PANTS_EXE="${HERE}/src/python/pants/bin/pants_loader.py" -if [[ ! -z "${WRAPPER_REQUIREMENTS}" ]]; then +if [[ -n "${WRAPPER_REQUIREMENTS}" ]]; then REQUIREMENTS=( - $(echo ${WRAPPER_REQUIREMENTS} | tr : ' ') + $(echo "${WRAPPER_REQUIREMENTS}" | tr : ' ') ${REQUIREMENTS[@]} ) fi PANTS_SRCPATH=( - ${HERE}/src/python + "${HERE}/src/python" ) -if [[ ! -z "${WRAPPER_SRCPATH}" ]]; then +if [[ -n "${WRAPPER_SRCPATH}" ]]; then PANTS_SRCPATH=( - $(echo ${WRAPPER_SRCPATH} | tr : ' ') + $(echo "${WRAPPER_SRCPATH}" | tr : ' ') ${PANTS_SRCPATH[@]} ) fi @@ -92,17 +94,17 @@ function exec_pants_bare() { activate_pants_venv 1>&2 bootstrap_native_code 1>&2 PYTHONPATH="${PANTS_SRCPATH}:${PYTHONPATH}" \ - exec python ${PANTS_EXE} "$@" + exec python "${PANTS_EXE}" "$@" } -if [[ ! -z "${WRAPPER_REQUIREMENTS}" ]]; then +if [[ -n "${WRAPPER_REQUIREMENTS}" ]]; then log "*** Running pants with extra requirements: ${WRAPPER_REQUIREMENTS} ***" fi -if [[ ! -z "${WRAPPER_SRCPATH}" ]]; then +if [[ -n "${WRAPPER_SRCPATH}" ]]; then log "*** Running pants with extra sources ${WRAPPER_SRCPATH} ***" fi -if [[ ! -z "$PANTS_DEV" && "$PANTS_DEV" -eq 0 ]]; then +if [[ -n "$PANTS_DEV" && "$PANTS_DEV" -eq 0 ]]; then # Unexport PANTS_DEV if explicitly set to 0. export -n PANTS_DEV else diff --git a/pants2 b/pants2 index 716f7e9147b..0240631a554 100755 --- a/pants2 +++ b/pants2 @@ -4,7 +4,7 @@ # This bootstrap script invokes Pants using a Python 2 interpreter. -REPO_ROOT=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd -P) +REPO_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P) export PY="${PY:-python2.7}" @@ -13,4 +13,4 @@ export PY="${PY:-python2.7}" # interpreter selection will default to using Python 2 as this is the minimum acceptable interpreter. export PANTS_PYTHON_SETUP_INTERPRETER_CONSTRAINTS="${PANTS_PYTHON_SETUP_INTERPRETER_CONSTRAINTS:-['CPython>=2.7,<3','CPython>=3.6,<4']}" -exec ${REPO_ROOT}/pants "$@" +exec "${REPO_ROOT}/pants" "$@" diff --git a/src/docs/publish_via_git.sh b/src/docs/publish_via_git.sh index 0ec22343767..15df7db8f95 100755 --- a/src/docs/publish_via_git.sh +++ b/src/docs/publish_via_git.sh @@ -23,7 +23,7 @@ set -eo pipefail # If a file "went away", this won't remove it. root=$( - cd $(dirname $0) + cd "$(dirname $0)" /bin/pwd ) @@ -36,9 +36,9 @@ trap "rm -fr $out" 0 1 2 mkdir -p $out cd $out -git clone $repo_url -cd `ls` -mkdir -p ./$path_within_url && cp -R $root/../../dist/docsite/* ./$path_within_url +git clone "$repo_url" +cd "$(ls)" +mkdir -p "./$path_within_url" && cp -R "$root/../../dist/docsite"/* "./$path_within_url" git add . git commit -am "publish by $USER" git push origin master