aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2016-08-06 21:57:31 -0500
committerGitHub <noreply@github.com>2016-08-06 21:57:31 -0500
commitaa900b91aa9417b6aa032b4eff878f2916c480f0 (patch)
treea15f67d4f42c6d29bdf276f62b9fa8b13cfdf95e
parent82f1970e25dcacb05758abcfc3ef3008c169a1e4 (diff)
parentf07d8f188a0621545957a0f348271d29b08704ec (diff)
downloadservo-aa900b91aa9417b6aa032b4eff878f2916c480f0.tar.gz
servo-aa900b91aa9417b6aa032b4eff878f2916c480f0.zip
Auto merge of #12736 - aneeshusa:prohibit-backticks-in-shell-scripts, r=Wafflespeanut
Add more shell script lints <!-- Please describe your changes on the following line: --> The "$(some_command arg1 arg2)" form is preferred to the `some_command arg1 arg2` form because it nests unambiguously. Add a lint for this to tidy. --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [ ] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [x] There are tests for these changes OR - [ ] These changes do not require tests because _____ <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/12736) <!-- Reviewable:end -->
-rwxr-xr-xcomponents/servo/fake-ld.sh2
-rwxr-xr-xetc/ci/lockfile_changed.sh4
-rwxr-xr-xetc/ci/manifest_changed.sh4
-rwxr-xr-xetc/ci/upload_docs.sh2
-rwxr-xr-xetc/ci/upload_nightly.sh4
-rwxr-xr-xports/geckolib/gecko_bindings/tools/regen.sh16
-rwxr-xr-xports/geckolib/gecko_bindings/tools/setup_bindgen.sh18
-rw-r--r--python/tidy/servo_tidy/tidy.py37
-rw-r--r--python/tidy/servo_tidy_tests/shell_tidy.sh7
-rw-r--r--python/tidy/servo_tidy_tests/test_tidy.py4
10 files changed, 63 insertions, 35 deletions
diff --git a/components/servo/fake-ld.sh b/components/servo/fake-ld.sh
index f14e94ea8c9..d0dd042dbf4 100755
--- a/components/servo/fake-ld.sh
+++ b/components/servo/fake-ld.sh
@@ -9,7 +9,7 @@ set -o nounset
set -o pipefail
TARGET_DIR="${OUT_DIR}/../../.."
-arm-linux-androideabi-gcc "$@" \
+arm-linux-androideabi-gcc "${@}" \
"${LDFLAGS-}" -lc -shared \
-o "${TARGET_DIR}/libservo.so"
touch "${TARGET_DIR}/servo"
diff --git a/etc/ci/lockfile_changed.sh b/etc/ci/lockfile_changed.sh
index 1d11acee473..6b3191291cc 100755
--- a/etc/ci/lockfile_changed.sh
+++ b/etc/ci/lockfile_changed.sh
@@ -9,5 +9,5 @@ set -o nounset
set -o pipefail
diff="$(git diff -- */*/Cargo.lock)"
-echo "$diff"
-[[ ! $diff ]]
+echo "${diff}"
+[[ -z "${diff}" ]]
diff --git a/etc/ci/manifest_changed.sh b/etc/ci/manifest_changed.sh
index 195e4b9ef7e..24fc9baec6c 100755
--- a/etc/ci/manifest_changed.sh
+++ b/etc/ci/manifest_changed.sh
@@ -17,5 +17,5 @@ set -o pipefail
./mach test-wpt --manifest-update --binary= SKIP_TESTS > /dev/null
diff="$(git diff -- tests/*/MANIFEST.json)"
-echo "$diff"
-[[ ! $diff ]]
+echo "${diff}"
+[[ -z "${diff}" ]]
diff --git a/etc/ci/upload_docs.sh b/etc/ci/upload_docs.sh
index fc8d7416f65..f55e5cb73db 100755
--- a/etc/ci/upload_docs.sh
+++ b/etc/ci/upload_docs.sh
@@ -12,7 +12,7 @@ set -o errexit
set -o nounset
set -o pipefail
-cd "$(dirname $0)/../.."
+cd "$(dirname ${0})/../.."
./mach doc
# etc/doc.servo.org/index.html overwrites $(mach rust-root)/doc/index.html
diff --git a/etc/ci/upload_nightly.sh b/etc/ci/upload_nightly.sh
index 4f20ab658d4..bd6da3e6625 100755
--- a/etc/ci/upload_nightly.sh
+++ b/etc/ci/upload_nightly.sh
@@ -27,7 +27,7 @@ upload() {
main() {
- if [[ "$#" != 1 ]]; then
+ if [[ "${#}" != 1 ]]; then
usage >&2
return 1
fi
@@ -58,4 +58,4 @@ main() {
upload "${platform}" ${package} "${extension}"
}
-main "$@"
+main "${@}"
diff --git a/ports/geckolib/gecko_bindings/tools/regen.sh b/ports/geckolib/gecko_bindings/tools/regen.sh
index 2d02bebdb34..fc2ed08a833 100755
--- a/ports/geckolib/gecko_bindings/tools/regen.sh
+++ b/ports/geckolib/gecko_bindings/tools/regen.sh
@@ -8,28 +8,28 @@ set -o errexit
set -o nounset
set -o pipefail
-if [ $# -eq 0 ]; then
- echo "Usage: $0 /path/to/gecko/objdir [other-regen.py-flags]"
+if [[ ${#} -eq 0 ]]; then
+ echo "Usage: ${0} /path/to/gecko/objdir [other-regen.py-flags]"
exit 1
fi
# Check for rust-bindgen
-if [ ! -d rust-bindgen ]; then
+if [[ ! -d rust-bindgen ]]; then
echo "rust-bindgen not found. Run setup_bindgen.sh first."
exit 1
fi
# Check for /usr/include
-if [ ! -d /usr/include ]; then
+if [[ ! -d /usr/include ]]; then
echo "/usr/include doesn't exist." \
"Mac users may need to run xcode-select --install."
exit 1
fi
-if [ "$(uname)" == "Linux" ]; then
- LIBCLANG_PATH=/usr/lib/llvm-3.8/lib;
+if [[ "$(uname)" == "Linux" ]]; then
+ LIBCLANG_PATH=/usr/lib/llvm-3.8/lib
else
- LIBCLANG_PATH=`brew --prefix llvm38`/lib/llvm-3.8/lib;
+ LIBCLANG_PATH="$(brew --prefix llvm38)/lib/llvm-3.8/lib"
fi
-./regen.py --target all "$@"
+./regen.py --target all "${@}"
diff --git a/ports/geckolib/gecko_bindings/tools/setup_bindgen.sh b/ports/geckolib/gecko_bindings/tools/setup_bindgen.sh
index d42bfc9adb4..4d1b67e3f43 100755
--- a/ports/geckolib/gecko_bindings/tools/setup_bindgen.sh
+++ b/ports/geckolib/gecko_bindings/tools/setup_bindgen.sh
@@ -9,33 +9,33 @@ set -o nounset
set -o pipefail
# Run in the tools directory.
-cd "$(dirname $0)"
+cd "$(dirname ${0})"
# Setup and build bindgen.
-if [ "$(uname)" == "Linux" ]; then
- export LIBCLANG_PATH=/usr/lib/llvm-3.8/lib;
+if [[ "$(uname)" == "Linux" ]]; then
+ export LIBCLANG_PATH=/usr/lib/llvm-3.8/lib
else
- export LIBCLANG_PATH=`brew --prefix llvm38`/lib/llvm-3.8/lib;
+ export LIBCLANG_PATH="$(brew --prefix llvm38)/lib/llvm-3.8/lib"
fi
# Make sure we have llvm38.
-if [ ! -x "$(command -v clang-3.8)" ]; then
+if [[ ! -x "$(command -v clang-3.8)" ]]; then
echo "llmv38 must be installed." \
"Mac users should |brew install llvm38|, Linux varies by distro."
exit 1
fi
-export LD_LIBRARY_PATH=$LIBCLANG_PATH
-export DYLD_LIBRARY_PATH=$LIBCLANG_PATH
+export LD_LIBRARY_PATH="${LIBCLANG_PATH}"
+export DYLD_LIBRARY_PATH="${LIBCLANG_PATH}"
# Check for multirust
-if [ ! -x "$(command -v multirust)" ]; then
+if [[ ! -x "$(command -v multirust)" ]]; then
echo "multirust must be installed."
exit 1
fi
# Don't try to clone twice.
-if [ ! -d rust-bindgen ]; then
+if [[ ! -d rust-bindgen ]]; then
git clone https://github.com/servo/rust-bindgen.git
fi
diff --git a/python/tidy/servo_tidy/tidy.py b/python/tidy/servo_tidy/tidy.py
index 34eea7f882a..3433e8265ed 100644
--- a/python/tidy/servo_tidy/tidy.py
+++ b/python/tidy/servo_tidy/tidy.py
@@ -318,19 +318,23 @@ def check_shell(file_name, lines):
shebang = "#!/usr/bin/env bash"
required_options = {"set -o errexit", "set -o nounset", "set -o pipefail"}
+ did_shebang_check = False
+
if len(lines) == 0:
yield (0, 'script is an empty file')
- else:
- if lines[0].rstrip() != shebang:
- yield (1, 'script does not have shebang "{}"'.format(shebang))
+ return
- for idx in range(1, len(lines)):
- stripped = lines[idx].rstrip()
+ if lines[0].rstrip() != shebang:
+ yield (1, 'script does not have shebang "{}"'.format(shebang))
+
+ for idx in range(1, len(lines)):
+ stripped = lines[idx].rstrip()
+ # Comments or blank lines are ignored. (Trailing whitespace is caught with a separate linter.)
+ if lines[idx].startswith("#") or stripped == "":
+ continue
- # Comments or blank lines are ignored. (Trailing whitespace is caught with a separate linter.)
- if lines[idx].startswith("#") or stripped == "":
- continue
- elif stripped in required_options:
+ if not did_shebang_check:
+ if stripped in required_options:
required_options.remove(stripped)
else:
# The first non-comment, non-whitespace, non-option line is the first "real" line of the script.
@@ -338,7 +342,20 @@ def check_shell(file_name, lines):
if len(required_options) != 0:
formatted = ['"{}"'.format(opt) for opt in required_options]
yield (idx + 1, "script is missing options {}".format(", ".join(formatted)))
- break
+ did_shebang_check = True
+
+ if "`" in stripped:
+ yield (idx + 1, "script should not use backticks for command substitution")
+
+ if " [ " in stripped or stripped.startswith("[ "):
+ yield (idx + 1, "script should use `[[` instead of `[` for conditional testing")
+
+ for dollar in re.finditer('\$', stripped):
+ next_idx = dollar.end()
+ if next_idx < len(stripped):
+ next_char = stripped[next_idx]
+ if not (next_char == '{' or next_char == '('):
+ yield(idx + 1, "variable substitutions should use the full \"${VAR}\" form")
def check_rust(file_name, lines):
diff --git a/python/tidy/servo_tidy_tests/shell_tidy.sh b/python/tidy/servo_tidy_tests/shell_tidy.sh
index fbf0e784755..e38358fc3b6 100644
--- a/python/tidy/servo_tidy_tests/shell_tidy.sh
+++ b/python/tidy/servo_tidy_tests/shell_tidy.sh
@@ -4,4 +4,11 @@
set -o nounset
+# Talking about some `concept in backticks` # shouldn't trigger
echo "hello world"
+some_var=`echo "command substitution"`
+another_var="$some_var"
+if [ -z "${some_var}" ]; then
+ echo "should have used [["
+fi
+[ -z "${another_var}" ]
diff --git a/python/tidy/servo_tidy_tests/test_tidy.py b/python/tidy/servo_tidy_tests/test_tidy.py
index b08e6057541..92b304a5c1a 100644
--- a/python/tidy/servo_tidy_tests/test_tidy.py
+++ b/python/tidy/servo_tidy_tests/test_tidy.py
@@ -52,6 +52,10 @@ class CheckTidiness(unittest.TestCase):
errors = tidy.collect_errors_for_files(iterFile('shell_tidy.sh'), [], [tidy.check_shell], print_text=False)
self.assertEqual('script does not have shebang "#!/usr/bin/env bash"', errors.next()[2])
self.assertEqual('script is missing options "set -o errexit", "set -o pipefail"', errors.next()[2])
+ self.assertEqual('script should not use backticks for command substitution', errors.next()[2])
+ self.assertEqual('variable substitutions should use the full \"${VAR}\" form', errors.next()[2])
+ self.assertEqual('script should use `[[` instead of `[` for conditional testing', errors.next()[2])
+ self.assertEqual('script should use `[[` instead of `[` for conditional testing', errors.next()[2])
self.assertNoMoreErrors(errors)
def test_rust(self):