run_formatter.sh: Warn if `rustfmt` is not installed.

My workstation didn't have `rustfmt` installed, which resulted
in weird cargo errors when running the script. This changes
it to check for `cargo fmt --version` first before trying
to run it, and print a warning otherwise.

+ Fix a series of issues reported by shellcheck, by using
  better quoting an array variables to manage lists.

Change-Id: I7920900d33a3cdca83297d8edda78f4f3b2b3693
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/25820
Reviewed-by: Matt Stark <msta@google.com>
Reviewed-by: Takuto Ikuta <tikuta@google.com>
Commit-Queue: David Turner <digit@google.com>
diff --git a/tools/run_formatter.sh b/tools/run_formatter.sh
index 23466b1..ecb72b7 100755
--- a/tools/run_formatter.sh
+++ b/tools/run_formatter.sh
@@ -1,31 +1,41 @@
 #!/bin/bash -eu
 
-cd $(dirname $(dirname $0))
+# Reformat the C++ and Rust sources.
+
+# Assume this is under tools/.
+cd "$(dirname "$(dirname "$0")")"
 
 if [ "${1:-}" = "--diff" ]; then
-  opts="--dry-run -Werror"
-  fmt_opts="--check"
+  clang_format_opts=(--dry-run -Werror)
+  fmt_opts=(--check)
 else
-  opts="-i"
-  fmt_opts=""
+  clang_format_opts=(-i)
+  fmt_opts=()
 fi
 
 if [ -z "${CLANG_FORMAT:-}" ]; then
   ensure_file=$(mktemp)
   # https://chrome-infra-packages.appspot.com/p/fuchsia/third_party/clang
-  echo 'fuchsia/third_party/clang/${platform} integration' > $ensure_file
-  cipd ensure -ensure-file $ensure_file -root clang
+  # shellcheck disable=SC2016
+  echo 'fuchsia/third_party/clang/${platform} integration' > "$ensure_file"
+  trap 'rm "$ensure_file"' EXIT
+  cipd ensure -ensure-file "$ensure_file" -root clang
   CLANG_FORMAT="./clang/bin/clang-format"
 fi
 
-git ls-files | egrep '\.(h|cc)$' | xargs "$CLANG_FORMAT" $opts
+git ls-files | grep -E '\.(h|cc)$' | xargs "$CLANG_FORMAT" "${clang_format_opts[@]}"
 
 if command -v cargo >/dev/null 2>&1; then
-  cargo_cmd="cargo"
-  extra_opts=""
-  if cargo +nightly --version >/dev/null 2>&1; then
-    cargo_cmd="cargo +nightly"
-    extra_opts="-- --config-path rustfmt-nightly.toml"
+  cargo_cmd=(cargo)
+  if "${cargo_cmd[@]}" +nightly --version >/dev/null 2>&1; then
+    cargo_cmd+=(+nightly)
+    fmt_opts+=(-- --config-path rustfmt-nightly.toml)
   fi
-  (cd src/gn/starlark && $cargo_cmd fmt --all $fmt_opts $extra_opts)
+  # rustfmt is not always installed, so check for it first.
+  cargo_fmt_cmd+=("${cargo_cmd[@]}" fmt)
+  if "${cargo_fmt_cmd[@]}" --version >/dev/null 2>&1; then
+    (cd src/gn/starlark && "${cargo_fmt_cmd[@]}" --all "${fmt_opts[@]}")
+  else
+    echo >&2 "WARNING: rustfmt not installed, reformatting Rust sources skipped."
+  fi
 fi