diff --git a/build/build b/build/build
index 4d48c7d55..7a83506b2 100755
--- a/build/build
+++ b/build/build
@@ -1,4 +1,4 @@
-#!/bin/sh
+#! /usr/bin/env sh
set -e
main() {
diff --git a/build/checksums b/build/checksums
index a0225cf56..5549e85db 100755
--- a/build/checksums
+++ b/build/checksums
@@ -1,2 +1,2 @@
-#!/bin/sh
+#! /usr/bin/env sh
find build/artifacts -type f -name '*.sha256' -exec cat {} +
diff --git a/build/release b/build/release
index f16011c33..da67429cd 100755
--- a/build/release
+++ b/build/release
@@ -1,4 +1,4 @@
-#!/bin/sh
+#! /usr/bin/env sh
set -e
if [ $# -ne 1 ]; then
diff --git a/build/rust-version b/build/rust-version
index e500392df..218b91685 100755
--- a/build/rust-version
+++ b/build/rust-version
@@ -1,4 +1,4 @@
-#! /usr/bin/env bash
+#! /usr/bin/env sh
set -euo pipefail
if ! version=$(grep -m 1 -oP '^\s*channel\s*=\s*"?\K([\d\.]+)' rust-toolchain.toml)
diff --git a/build/tag b/build/tag
index 82c38ff52..6a6a03010 100755
--- a/build/tag
+++ b/build/tag
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! /usr/bin/env sh
set -e
if [ $# -ne 1 ]; then
diff --git a/build/upload b/build/upload
index bed1533cb..69ce4d4a0 100755
--- a/build/upload
+++ b/build/upload
@@ -1,4 +1,4 @@
-#!/bin/sh
+#! /usr/bin/env sh
set -e
SSH_LOGIN=${SSH_LOGIN:-release}
diff --git a/build/version b/build/version
index b1de9c37d..83c2557e5 100755
--- a/build/version
+++ b/build/version
@@ -1,4 +1,4 @@
-#!/bin/sh
+#! /usr/bin/env sh
if ! version="$(git describe --match='releases/*' --candidates=1 2>/dev/null)"; then
echo "fatal: no version tag found by 'git describe'" >&2 ; exit 1
diff --git a/flake.nix b/flake.nix
index b7e60f2fd..950026533 100644
--- a/flake.nix
+++ b/flake.nix
@@ -294,7 +294,10 @@
clippy = rustup.toolchain;
};
};
- shellcheck.enable = true;
+ shellcheck = {
+ enable = true;
+ args = ["--shell" "sh" "--exclude" "SC3040"];
+ };
}
// grep.hooks;
};
diff --git a/justfile b/justfile
index b2f3cd173..f33cf2377 100644
--- a/justfile
+++ b/justfile
@@ -90,7 +90,7 @@ check-spelling: (verify-tool "codespell")
[parallel]
check-scripts: (verify-tool "shellcheck")
@echo "{{CHECK}}Checking shell scripts…{{NORMAL}}"
- @find . -type f -name "*.sh" -exec shellcheck {} +
+ @find . -type f -name "*.sh" -exec shellcheck --shell sh --exclude SC3040 {} +
# Run checks for forbidden keywords
[group('pre-commit')]
diff --git a/scripts/build-man-pages.sh b/scripts/build-man-pages.sh
index c05073f2d..e9c5a9bb5 100755
--- a/scripts/build-man-pages.sh
+++ b/scripts/build-man-pages.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#! /usr/bin/env sh
set -e
diff --git a/scripts/cache-cobs b/scripts/cache-cobs
index b29013ac0..3916e94aa 100755
--- a/scripts/cache-cobs
+++ b/scripts/cache-cobs
@@ -1,4 +1,4 @@
-#!/bin/sh
+#! /usr/bin/env sh
set -e
DIRECTORY="$(rad path)/storage"
diff --git a/scripts/changelog b/scripts/changelog
index 4451a5113..37d57fe99 100755
--- a/scripts/changelog
+++ b/scripts/changelog
@@ -1,4 +1,4 @@
-#!/bin/sh
+#! /usr/bin/env sh
set -e
render_commit_footnotes() {
diff --git a/scripts/clear-refs-db.sh b/scripts/clear-refs-db.sh
index 32fb3fd95..1f989d57e 100755
--- a/scripts/clear-refs-db.sh
+++ b/scripts/clear-refs-db.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#! /usr/bin/env sh
set -e
DB="$(rad path)/node/node.db"
diff --git a/scripts/create-env.sh b/scripts/create-env.sh
index ff4674806..6fecc78f7 100755
--- a/scripts/create-env.sh
+++ b/scripts/create-env.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#! /usr/bin/env sh
set -e
unset SSH_AUTH_SOCK
diff --git a/scripts/delete-remote-branches.sh b/scripts/delete-remote-branches.sh
index 414e7f6e7..02fdd4989 100755
--- a/scripts/delete-remote-branches.sh
+++ b/scripts/delete-remote-branches.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#! /usr/bin/env sh
# Delete all remote branches that don't have a local copy.
remote="rad"
diff --git a/scripts/git-hook-template.sh b/scripts/git-hook-template.sh
index 8977dff37..ece378580 100644
--- a/scripts/git-hook-template.sh
+++ b/scripts/git-hook-template.sh
@@ -1,35 +1,35 @@
-#! /usr/bin/env bash
+#! /usr/bin/env sh
set -euo pipefail
readonly HOOK="${HOOK:-$(basename "$0")}"
-if ! [[ "$HOOK" =~ ^(pre-(commit|push)|post-checkout|commit-msg)$ ]]
-then
- echo "Unknown hook '${HOOK}'."
- exit 1
-fi
+case "$HOOK" in
+ pre-commit|pre-push|post-checkout|commit-msg) ;;
+ *)
+ echo "Unknown hook '${HOOK}'."
+ exit 1
+ ;;
+esac
-readonly SENSITIVE_FILES=("justfile" "build.rs" "rust-toolchain.toml")
readonly BASE_BRANCH="main"
-# Check which files were modified compared to the base branch.
-mapfile -t CHANGED_FILES < <(comm -12 \
- <(git diff --name-only "${BASE_BRANCH}" | sort) \
- <(IFS=$'\n'; echo "${SENSITIVE_FILES[*]}" | sort) \
-)
+# Check which sensitive files were modified compared to the base branch.
+CHANGED_FILES=$(git diff --name-only "$BASE_BRANCH" -- \
+ justfile build.rs rust-toolchain.toml)
-if [ ${#CHANGED_FILES[@]} -gt 0 ]
+if [ -n "$CHANGED_FILES" ]
then
echo "⚠️ WARNING: Sensitive files have been modified relative to $BASE_BRANCH."
echo "Executing this hook may run arbitrary code from the modified files."
echo ""
- git --no-pager diff "$BASE_BRANCH" -- "${SENSITIVE_FILES[@]}"
+ git --no-pager diff "$BASE_BRANCH" -- justfile build.rs rust-toolchain.toml
# Read from /dev/tty because stdin is not attached to the terminal in Git hooks.
exec < /dev/tty
- read -r -p "⚠️ Do you want to continue executing the '${HOOK}' hook? [y/N] " response
+ printf "⚠️ Do you want to continue executing the '%s' hook? [y/N] " "$HOOK"
+ read -r response
case "$response" in
[yY][eE][sS]|[yY])
echo "Continuing with '${HOOK}' hook…"
diff --git a/scripts/import-issue.sh b/scripts/import-issue.sh
index d293e72ea..c870edac6 100755
--- a/scripts/import-issue.sh
+++ b/scripts/import-issue.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#! /usr/bin/env sh
#
# Import a GitHub issue into Radicle.
#
@@ -16,25 +16,8 @@ if ! command -v rad > /dev/null; then
echo "Error: rad is not installed" ; exit 1
fi
-if ! command -v pcregrep > /dev/null; then
- echo "Error: pcregrep is not installed" ; exit 1
-fi
-
-if ! command -v sed > /dev/null; then
- echo "Error: sed is not installed" ; exit 1
-fi
-
-function removeImgTags {
- local html
- html="$(cat)"
- local imgTags
- imgTags="$(echo "$html" | pcregrep -M '
]*>')"
-
- # shellcheck disable=SC2066
- for imgTag in "$imgTags"; do
- html="$(echo "$html" | sed -z "s@$imgTag@@")"
- done
- echo "$html"
+removeImgTags() {
+ jq -Rrs 'gsub("
]*>"; "")'
}
# Check if the correct number of arguments is provided
@@ -53,13 +36,17 @@ url="https://api.github.com/repos/${owner}/${repo}/issues/${issue}"
response="$(curl -s "$url")"
# Extract the title and body from the JSON response
-title="$(echo "$response" | jq -r '.title')"
-body="$(echo "$response" | jq -r '.body' | removeImgTags)"
-labels="$(echo "$response" | jq -r '.labels | .[].name')"
+title="$(printf '%s\n' "$response" | jq -r '.title')"
+body="$(printf '%s\n' "$response" | jq -r '.body' | removeImgTags)"
+labels="$(printf '%s\n' "$response" | jq -r '.labels | .[].name')"
-tags=()
-for label in $labels; do
- tags+=("--label" "$label")
-done
+set --
+while IFS= read -r label; do
+ if [ -n "$label" ]; then
+ set -- "$@" --label "$label"
+ fi
+done < "$tmp/tracked"
+# The child shell expands these variables.
+# shellcheck disable=SC2016
+xargs -0 sh -c '
+ for file do
+ if [ -f "$file" ] && [ ! -L "$file" ]; then
+ printf "%s\000" "$file"
+ fi
+ done
+' sh < "$tmp/tracked" > "$tmp/files"
-if [ ${#files[@]} -eq 0 ]; then
+if [ ! -s "$tmp/files" ]; then
exit 0
fi
# Checksum files before sed so we detect only changes it makes.
-before=$(printf '%s\0' "${files[@]}" | xargs -0 md5sum)
+xargs -0 md5sum < "$tmp/files" > "$tmp/before"
standalone_wildcard='^[[:space:]]*\.\.\.[[:space:]]*$'
git_hex_range='[0-9a-f]{4,}\.\.\.[0-9a-f]{4,}'
@@ -30,20 +36,20 @@ bracket_wildcard='\[[[:space:]]*\.\.\.[[:space:]]*\]'
# Detect GNU vs BSD sed to apply the correct in-place flag
if sed --version >/dev/null 2>&1; then
- sed_cmd=(sed -i -E)
+ set -- -i -E
else
- sed_cmd=(sed -i '' -E)
+ set -- -i '' -E
fi
-printf '%s\0' "${files[@]}" | xargs -0 "${sed_cmd[@]}" \
+xargs -0 sed "$@" \
-e "/${standalone_wildcard}/b" \
-e "/${git_hex_range}/b" \
-e "/${git_ref_range}/b" \
- -e "/${bracket_wildcard}/b" \
+ -e "/${bracket_wildcard}/b" < "$tmp/files"
-after=$(printf '%s\0' "${files[@]}" | xargs -0 md5sum)
+xargs -0 md5sum < "$tmp/files" > "$tmp/after"
-changed=$(diff <(echo "$before") <(echo "$after") | grep '^>' | sed 's/^> [a-f0-9]* //' || true)
+changed=$(diff "$tmp/before" "$tmp/after" | grep '^>' | sed 's/^> [a-f0-9]* //' || true)
if [ -n "$changed" ]; then
echo "error: Replaced '...' with '…' (U+2026) in the following files:"
diff --git a/scripts/just/check-hooks.sh b/scripts/just/check-hooks.sh
index ce5f45172..6fd764ca6 100755
--- a/scripts/just/check-hooks.sh
+++ b/scripts/just/check-hooks.sh
@@ -1,11 +1,11 @@
-#! /usr/bin/env bash
+#! /usr/bin/env sh
set -e
HOOK_SCRIPT=$1
HOOKS=$2
TEMPLATE="$HOOK_SCRIPT"
-OUTDATED=()
+OUTDATED=""
MISSING=0
TOTAL=0
@@ -13,9 +13,9 @@ for hook in $HOOKS; do
TOTAL=$((TOTAL + 1))
if [ ! -f ".git/hooks/$hook" ]; then
MISSING=$((MISSING + 1))
- OUTDATED+=("$hook")
+ OUTDATED="$OUTDATED $hook"
elif ! cmp -s "$TEMPLATE" ".git/hooks/$hook"; then
- OUTDATED+=("$hook")
+ OUTDATED="$OUTDATED $hook"
fi
done
@@ -23,12 +23,12 @@ if [ "$MISSING" -eq "$TOTAL" ] && [ "$TOTAL" -gt 0 ]; then
echo ""
echo "${HINT}No git hooks are installed. Run 'just install-hooks' to install them.${NORMAL}"
echo ""
-elif [ ${#OUTDATED[@]} -gt 0 ]; then
+elif [ -n "$OUTDATED" ]; then
echo ""
echo "${WARN}WARNING: The following git hooks are missing or out of date:${NORMAL}"
echo ""
- for hook in "${OUTDATED[@]}"; do
- echo -e "\t$hook"
+ for hook in $OUTDATED; do
+ printf '\t%s\n' "$hook"
done
echo ""
echo "${HINT}Check them with 'diff $HOOK_SCRIPT .git/hooks/' then run 'just install-hooks'${NORMAL}"
diff --git a/scripts/just/check-keywords.sh b/scripts/just/check-keywords.sh
index 828a9e967..c63d92241 100755
--- a/scripts/just/check-keywords.sh
+++ b/scripts/just/check-keywords.sh
@@ -1,4 +1,4 @@
-#! /usr/bin/env bash
+#! /usr/bin/env sh
set -e
echo "${CHECK}Checking for forbidden words in staged files…${NORMAL}"
diff --git a/scripts/just/commit-msg.sh b/scripts/just/commit-msg.sh
index 004e459c5..a987720d1 100755
--- a/scripts/just/commit-msg.sh
+++ b/scripts/just/commit-msg.sh
@@ -1,4 +1,4 @@
-#! /usr/bin/env bash
+#! /usr/bin/env sh
set -euo pipefail
FILE=$1
diff --git a/scripts/just/format-nix.sh b/scripts/just/format-nix.sh
index f8c6a9a37..46a314969 100755
--- a/scripts/just/format-nix.sh
+++ b/scripts/just/format-nix.sh
@@ -1,4 +1,4 @@
-#! /usr/bin/env bash
+#! /usr/bin/env sh
if command -v alejandra >/dev/null 2>&1; then
alejandra --check .
diff --git a/scripts/just/install-hooks.sh b/scripts/just/install-hooks.sh
index 5f7439bad..9e03a4660 100755
--- a/scripts/just/install-hooks.sh
+++ b/scripts/just/install-hooks.sh
@@ -1,11 +1,12 @@
-#! /usr/bin/env bash
+#! /usr/bin/env sh
set -e
HOOK_SCRIPT=$1
HOOKS=$2
-read -r -p "Overwrite existing hooks '${HOOKS}'? [y/N] " confirm
-[[ "$confirm" == "y" ]] || exit 1
+printf "Overwrite existing hooks '%s'? [y/N] " "$HOOKS"
+read -r confirm
+[ "$confirm" = "y" ] || exit 1
for hook in $HOOKS; do
if [ -f ".git/hooks/$hook" ]; then
diff --git a/scripts/just/verify-tool.sh b/scripts/just/verify-tool.sh
index ebb584a6c..ca7122aea 100755
--- a/scripts/just/verify-tool.sh
+++ b/scripts/just/verify-tool.sh
@@ -1,4 +1,4 @@
-#! /usr/bin/env bash
+#! /usr/bin/env sh
set -e
TOOL=$1
PKG_NAME=$2
diff --git a/scripts/patch-rebase.sh b/scripts/patch-rebase.sh
index 3f68ee38c..a8d495ae1 100755
--- a/scripts/patch-rebase.sh
+++ b/scripts/patch-rebase.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#! /usr/bin/env sh
set -e
if [ "$#" -lt 1 ]; then
diff --git a/scripts/show-sigrefs.sh b/scripts/show-sigrefs.sh
index 8279502c5..13a89e550 100755
--- a/scripts/show-sigrefs.sh
+++ b/scripts/show-sigrefs.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#! /usr/bin/env sh
set -e
if [ "$#" -lt 2 ]; then
@@ -23,4 +23,9 @@ actual=$(echo "$actual" | sed "s@refs/namespaces/$REMOTE/@@")
# Remove `sigrefs` itself.
actual=$(echo "$actual" | grep -v "refs/rad/sigrefs$")
-diff <(echo "$signed") <(echo "$actual") --color=always -y --minimal -W 240
+tmp=$(mktemp -d)
+trap 'rm -rf "$tmp"' 0
+trap 'exit 1' HUP INT TERM
+printf '%s\n' "$signed" > "$tmp/signed"
+printf '%s\n' "$actual" > "$tmp/actual"
+diff --color=always -y --minimal -W 240 "$tmp/signed" "$tmp/actual"