127 lines
3.2 KiB
Bash
Executable File
127 lines
3.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
((${BASH_VERSION%%.*} >= 4)) || { echo >&2 "$0: Error: Please upgrade Bash."; exit 1; }
|
|
|
|
set -euo pipefail
|
|
|
|
source "tools/codestyle/globals.source"
|
|
|
|
function path_under_any_of_dirs()
|
|
{
|
|
local path="$1" dir
|
|
shift
|
|
for dir in "$@"; do
|
|
if [[ "${path}" == "${dir}/"* ]]; then
|
|
return 0
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
# Files with staged changes that are required to follow the coding style.
|
|
function get_staged_files()
|
|
{
|
|
local tidy_globs=() dir ext
|
|
for dir in "${TIDY_DIRS[@]}"; do
|
|
for ext in "${TIDY_EXTENSIONS[@]}"; do
|
|
tidy_globs+=("${dir}/*.${ext}")
|
|
done
|
|
done
|
|
|
|
local untidy_dirs=() untidy_path
|
|
while IFS= read -r -d '' untidy_path; do
|
|
untidy_dirs+=("${untidy_path%/${UNTIDY_FILE}}")
|
|
done < <(git ls-files -z -- "*/${UNTIDY_FILE}")
|
|
|
|
STAGED_FILES=()
|
|
|
|
local file
|
|
while IFS= read -r -d '' file; do
|
|
if ! path_under_any_of_dirs "${file}" "${untidy_dirs[@]}"; then
|
|
STAGED_FILES+=("${file}")
|
|
fi
|
|
done < <(git diff -z --name-only --cached -- "${tidy_globs[@]}")
|
|
|
|
NUM_STAGED="${#STAGED_FILES[@]}"
|
|
}
|
|
|
|
# Files from STAGED_FILES that also have unstaged changes. Beware, if
|
|
# STAGED_FILES is empty then this will return all unstaged files.
|
|
function get_unstaged_files()
|
|
{
|
|
UNSTAGED_FILES=()
|
|
|
|
while IFS= read -r -d '' unstaged_file; do
|
|
UNSTAGED_FILES+=("${unstaged_file}")
|
|
done < <(git diff -z --name-only -- "${STAGED_FILES[@]}")
|
|
|
|
NUM_UNSTAGED="${#UNSTAGED_FILES[@]}"
|
|
}
|
|
|
|
exit_status=0
|
|
|
|
get_staged_files
|
|
|
|
if ((${NUM_STAGED} == 0)); then
|
|
echo >&2 "$0: Nothing to do."
|
|
exit 0
|
|
fi
|
|
|
|
get_unstaged_files
|
|
|
|
echo >&2 "$0: Tidying staged files..."
|
|
|
|
# Avoid overwriting unstaged changes.
|
|
for file in "${UNSTAGED_FILES[@]}"; do
|
|
mv "${file}" "${file}.unstaged"
|
|
git checkout -- "${file}"
|
|
done
|
|
|
|
# Begin tidying the staged version of each file.
|
|
STAGED_PIDS=()
|
|
for file in "${STAGED_FILES[@]}"; do
|
|
"tools/codestyle/tidy_file.sh" "${file}" & # Run in background. Must not use Git.
|
|
STAGED_PIDS+=( $! ) # store process ID
|
|
done
|
|
|
|
# Begin tidying the unstaged versions to reduce diff with staged versions.
|
|
UNSTAGED_PIDS=()
|
|
for file in "${UNSTAGED_FILES[@]}"; do
|
|
"tools/codestyle/tidy_file.sh" "${file}.unstaged" & # Run in background. Must not use Git.
|
|
UNSTAGED_PIDS+=( $! ) # store process ID
|
|
done
|
|
|
|
# Once the staged files are tidy, re-stage them.
|
|
for idx in "${!STAGED_PIDS[@]}"; do
|
|
# Wait for background process to finish
|
|
if wait "${STAGED_PIDS[${idx}]}"; then
|
|
# Process was successful
|
|
file="${STAGED_FILES[${idx}]}"
|
|
git add -- "${file}" # Run in foreground to avoid git index conflicts.
|
|
else
|
|
# Process failed
|
|
exit_status=$?
|
|
fi
|
|
done
|
|
|
|
# Once the unstaged files are tidy, restore them.
|
|
for idx in "${!UNSTAGED_PIDS[@]}"; do
|
|
# Wait for background process to finish
|
|
if wait "${UNSTAGED_PIDS[${idx}]}"; then
|
|
# Process was successful
|
|
file="${UNSTAGED_FILES[${idx}]}"
|
|
mv "${file}.unstaged" "${file}"
|
|
else
|
|
# Process failed
|
|
exit_status=$?
|
|
fi
|
|
done
|
|
|
|
if ((${exit_status} == 0)); then
|
|
echo >&2 "$0: Tidying complete!"
|
|
else
|
|
echo >&2 "$0: Errors occured."
|
|
fi
|
|
|
|
exit ${exit_status}
|