2021-09-15 14:58:09 +08:00
|
|
|
#!/bin/bash
|
|
|
|
|
2021-09-15 17:00:50 +08:00
|
|
|
onoe() {
|
|
|
|
echo "$*" >&2
|
|
|
|
}
|
|
|
|
|
|
|
|
odie() {
|
|
|
|
onoe "$@"
|
|
|
|
exit 1
|
|
|
|
}
|
|
|
|
|
2021-09-15 14:58:09 +08:00
|
|
|
# HOMEBREW_PREFIX is set by extend/ENV/super.rb
|
|
|
|
# shellcheck disable=SC2154
|
2021-09-15 17:00:50 +08:00
|
|
|
if [[ -z "${HOMEBREW_PREFIX}" ]]
|
2021-09-15 14:58:09 +08:00
|
|
|
then
|
2021-09-15 17:00:50 +08:00
|
|
|
odie "${0##*/}: This program is internal and must be run via brew."
|
2021-09-15 14:58:09 +08:00
|
|
|
fi
|
|
|
|
|
|
|
|
# HOMEBREW_PREFIX is set by extend/ENV/super.rb
|
|
|
|
# shellcheck disable=SC2154
|
|
|
|
SHFMT="${HOMEBREW_PREFIX}/opt/shfmt/bin/shfmt"
|
|
|
|
if [[ ! -x "${SHFMT}" ]]
|
|
|
|
then
|
2021-09-15 17:00:50 +08:00
|
|
|
odie "${0##*/}: Please install shfmt by running \`brew install shfmt\`."
|
|
|
|
fi
|
|
|
|
|
2021-09-27 21:13:11 +08:00
|
|
|
# HOMEBREW_PREFIX is set by extend/ENV/super.rb
|
|
|
|
# shellcheck disable=SC2154
|
|
|
|
DIFF="${HOMEBREW_PREFIX}/opt/diffutils/bin/diff"
|
|
|
|
DIFF_ARGS=("-d" "-C" "1")
|
|
|
|
if [[ ! -x "${DIFF}" ]]
|
2021-09-15 17:00:50 +08:00
|
|
|
then
|
2021-09-27 21:13:11 +08:00
|
|
|
# HOMEBREW_PATH is set by global.rb
|
|
|
|
# shellcheck disable=SC2154
|
|
|
|
if [[ -x "$(PATH="${HOMEBREW_PATH}" command -v diff)" ]]
|
|
|
|
then
|
|
|
|
DIFF="$(PATH="${HOMEBREW_PATH}" command -v diff)" # fall back to `diff` in PATH without coloring
|
|
|
|
else
|
|
|
|
odie "${0##*/}: Please install diff by running \`brew install diffutils\`."
|
|
|
|
fi
|
|
|
|
else
|
|
|
|
DIFF_ARGS+=("--color") # enable color output for GNU diff
|
2021-09-15 14:58:09 +08:00
|
|
|
fi
|
|
|
|
|
|
|
|
SHFMT_ARGS=()
|
|
|
|
INPLACE=''
|
|
|
|
while [[ $# -gt 0 ]]
|
|
|
|
do
|
|
|
|
arg="$1"
|
|
|
|
if [[ "${arg}" == "--" ]]
|
|
|
|
then
|
|
|
|
shift
|
|
|
|
break
|
|
|
|
fi
|
|
|
|
if [[ "${arg}" == "-w" ]]
|
|
|
|
then
|
|
|
|
shift
|
|
|
|
INPLACE=1
|
|
|
|
continue
|
|
|
|
fi
|
|
|
|
SHFMT_ARGS+=("${arg}")
|
|
|
|
shift
|
|
|
|
done
|
2021-09-16 23:16:07 +08:00
|
|
|
unset arg
|
2021-09-15 14:58:09 +08:00
|
|
|
|
|
|
|
FILES=()
|
|
|
|
for file in "$@"
|
|
|
|
do
|
|
|
|
if [[ -f "${file}" ]]
|
|
|
|
then
|
2021-09-15 22:12:39 +08:00
|
|
|
if [[ -w "${file}" ]]
|
|
|
|
then
|
|
|
|
FILES+=("${file}")
|
|
|
|
else
|
|
|
|
onoe "${0##*/}: File \"${file}\" is not writable."
|
|
|
|
fi
|
2021-09-15 14:58:09 +08:00
|
|
|
else
|
2021-09-15 22:12:39 +08:00
|
|
|
onoe "${0##*/}: File \"${file}\" does not exist."
|
2021-09-15 14:58:09 +08:00
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
done
|
2021-09-16 23:16:07 +08:00
|
|
|
unset file
|
2021-09-15 14:58:09 +08:00
|
|
|
|
|
|
|
if [[ "${#FILES[@]}" == 0 ]]
|
|
|
|
then
|
|
|
|
exit
|
|
|
|
fi
|
|
|
|
|
2021-09-15 17:00:50 +08:00
|
|
|
###
|
|
|
|
### Custom shell script styling
|
|
|
|
###
|
|
|
|
|
2021-09-16 23:16:07 +08:00
|
|
|
# Check for specific patterns and prompt messages if detected
|
|
|
|
no_forbidden_patten() {
|
2021-09-15 17:00:50 +08:00
|
|
|
local file="$1"
|
2021-09-15 23:40:14 +08:00
|
|
|
local tempfile="$2"
|
2021-09-16 23:16:07 +08:00
|
|
|
local subject="$3"
|
|
|
|
local message="$4"
|
|
|
|
local regex_pos="$5"
|
|
|
|
local regex_neg="${6:-}"
|
2021-09-15 23:40:14 +08:00
|
|
|
local line
|
|
|
|
local num=0
|
|
|
|
local retcode=0
|
2021-09-15 17:00:50 +08:00
|
|
|
|
2021-09-15 23:40:14 +08:00
|
|
|
while IFS='' read -r line
|
|
|
|
do
|
|
|
|
num="$((num + 1))"
|
2021-09-16 23:16:07 +08:00
|
|
|
if [[ "${line}" =~ ${regex_pos} ]] &&
|
|
|
|
[[ -z "${regex_neg}" || ! "${line}" =~ ${regex_neg} ]]
|
2021-09-15 23:40:14 +08:00
|
|
|
then
|
2021-09-16 23:16:07 +08:00
|
|
|
onoe "${subject} detected at \"${file}\", line ${num}."
|
|
|
|
[[ -n "${message}" ]] && onoe "${message}"
|
2021-09-15 23:40:14 +08:00
|
|
|
retcode=1
|
|
|
|
fi
|
|
|
|
done <"${file}"
|
|
|
|
return "${retcode}"
|
2021-09-15 17:00:50 +08:00
|
|
|
}
|
|
|
|
|
2021-09-16 23:16:07 +08:00
|
|
|
# Check pattern:
|
|
|
|
# '^\t+'
|
|
|
|
#
|
|
|
|
# Replace tabs with 2 spaces instead
|
|
|
|
#
|
|
|
|
no_tabs() {
|
|
|
|
local file="$1"
|
|
|
|
local tempfile="$2"
|
|
|
|
|
|
|
|
no_forbidden_patten "${file}" "${tempfile}" \
|
|
|
|
"Indent with tab" \
|
|
|
|
'Replace tabs with 2 spaces instead.' \
|
|
|
|
'^[[:space:]]+' \
|
|
|
|
'^ +'
|
|
|
|
}
|
|
|
|
|
2021-09-15 17:00:50 +08:00
|
|
|
# Check pattern:
|
|
|
|
# for var in ... \
|
|
|
|
# ...; do
|
|
|
|
#
|
|
|
|
# Use the followings instead (keep for statements only one line):
|
2021-09-15 23:40:14 +08:00
|
|
|
# ARRAY=(
|
|
|
|
# ...
|
|
|
|
# )
|
|
|
|
# for var in "${ARRAY[@]}"
|
|
|
|
# do
|
2021-09-15 17:00:50 +08:00
|
|
|
#
|
|
|
|
no_multiline_for_statements() {
|
|
|
|
local file="$1"
|
2021-09-15 23:40:14 +08:00
|
|
|
local tempfile="$2"
|
|
|
|
local regex='^ *for [_[:alnum:]]+ in .*\\$'
|
2021-09-16 23:16:07 +08:00
|
|
|
local message
|
|
|
|
message="$(
|
|
|
|
cat <<EOMSG
|
2021-09-15 23:40:14 +08:00
|
|
|
Use the followings instead (keep for statements only one line):
|
|
|
|
ARRAY=(
|
|
|
|
...
|
|
|
|
)
|
|
|
|
for var in "\${ARRAY[@]}"
|
|
|
|
do
|
|
|
|
...
|
|
|
|
done
|
|
|
|
EOMSG
|
2021-09-16 23:16:07 +08:00
|
|
|
)"
|
|
|
|
|
|
|
|
no_forbidden_patten "${file}" "${tempfile}" \
|
|
|
|
"Multiline for statement" \
|
|
|
|
"${message}" \
|
|
|
|
"${regex}"
|
2021-09-15 17:00:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
# Check pattern:
|
|
|
|
# IFS=$'\n'
|
|
|
|
#
|
|
|
|
# Use the followings instead:
|
2021-09-15 23:40:14 +08:00
|
|
|
# while IFS='' read -r line
|
|
|
|
# do
|
|
|
|
# ...
|
|
|
|
# done < <(command)
|
2021-09-15 17:00:50 +08:00
|
|
|
#
|
|
|
|
no_IFS_newline() {
|
|
|
|
local file="$1"
|
2021-09-15 23:40:14 +08:00
|
|
|
local tempfile="$2"
|
|
|
|
local regex="^[^#]*IFS=\\\$'\\\\n'"
|
2021-09-16 23:16:07 +08:00
|
|
|
local message
|
|
|
|
message="$(
|
|
|
|
cat <<EOMSG
|
2021-09-15 23:40:14 +08:00
|
|
|
Use the followings instead:
|
|
|
|
while IFS='' read -r line
|
|
|
|
do
|
|
|
|
...
|
|
|
|
done < <(command)
|
|
|
|
EOMSG
|
2021-09-16 23:16:07 +08:00
|
|
|
)"
|
|
|
|
|
|
|
|
no_forbidden_patten "${file}" "${tempfile}" \
|
|
|
|
"Pattern \`IFS=\$'\\n'\`" \
|
|
|
|
"${message}" \
|
|
|
|
"${regex}"
|
2021-09-15 23:40:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
# Combine all forbidden styles
|
2021-09-16 23:16:07 +08:00
|
|
|
no_forbidden_styles() {
|
2021-09-15 23:40:14 +08:00
|
|
|
local file="$1"
|
|
|
|
local tempfile="$2"
|
|
|
|
|
|
|
|
no_tabs "${file}" "${tempfile}" || return 1
|
|
|
|
no_multiline_for_statements "${file}" "${tempfile}" || return 1
|
|
|
|
no_IFS_newline "${file}" "${tempfile}" || return 1
|
2021-09-15 17:00:50 +08:00
|
|
|
}
|
|
|
|
|
2021-09-15 22:12:39 +08:00
|
|
|
# Align multiline if condition (indent with 3 spaces or 6 spaces (start with "-"))
|
2021-09-15 17:00:50 +08:00
|
|
|
# before: after:
|
2021-09-15 23:40:14 +08:00
|
|
|
# if [[ ... ]] || if [[ ... ]] ||
|
|
|
|
# [[ ... ]] [[ ... ]]
|
|
|
|
# then then
|
2021-09-15 17:00:50 +08:00
|
|
|
#
|
|
|
|
# before: after:
|
2021-09-16 23:26:23 +08:00
|
|
|
# if [[ -n ... || if [[ -n ... ||
|
2021-09-15 23:40:14 +08:00
|
|
|
# -n ... ]] -n ... ]]
|
|
|
|
# then then
|
2021-09-15 17:00:50 +08:00
|
|
|
#
|
2021-09-15 22:12:39 +08:00
|
|
|
align_multiline_if_condition() {
|
|
|
|
local line
|
|
|
|
local lastline=''
|
2021-09-16 23:26:23 +08:00
|
|
|
local base_indent='' # indents before `if`
|
|
|
|
local extra_indent='' # 2 extra spaces for `elif`
|
|
|
|
local multiline_if_begin_regex='^( *)(el)?if '
|
|
|
|
local multiline_then_end_regex='^(.*)\; (then( *#.*)?)$'
|
|
|
|
local within_test_regex='^( *)(((! )?-[fdLrwxeszn] )|([^\[]+ == ))'
|
|
|
|
|
|
|
|
trim() {
|
|
|
|
[[ "$1" =~ [^[:space:]](.*[^[:space:]])? ]]
|
|
|
|
printf "%s" "${BASH_REMATCH[0]}"
|
|
|
|
}
|
2021-09-15 22:12:39 +08:00
|
|
|
|
|
|
|
if [[ "$1" =~ ${multiline_if_begin_regex} ]]
|
|
|
|
then
|
|
|
|
base_indent="${BASH_REMATCH[1]}"
|
|
|
|
[[ -n "${BASH_REMATCH[2]}" ]] && extra_indent=' '
|
|
|
|
echo "$1"
|
|
|
|
shift
|
|
|
|
fi
|
2021-09-15 17:00:50 +08:00
|
|
|
|
2021-09-15 22:12:39 +08:00
|
|
|
while [[ "$#" -gt 0 ]]
|
|
|
|
do
|
|
|
|
line="$1"
|
|
|
|
shift
|
|
|
|
if [[ "${line}" =~ ${multiline_then_end_regex} ]]
|
|
|
|
then
|
|
|
|
line="${BASH_REMATCH[1]}"
|
|
|
|
lastline="${base_indent}${BASH_REMATCH[2]}"
|
|
|
|
fi
|
|
|
|
if [[ "${line}" =~ ${within_test_regex} ]]
|
|
|
|
then
|
2021-09-16 23:26:23 +08:00
|
|
|
echo "${base_indent}${extra_indent} $(trim "${line}")"
|
2021-09-15 22:12:39 +08:00
|
|
|
else
|
2021-09-16 23:26:23 +08:00
|
|
|
echo "${base_indent}${extra_indent} $(trim "${line}")"
|
2021-09-15 22:12:39 +08:00
|
|
|
fi
|
|
|
|
done
|
|
|
|
|
|
|
|
echo "${lastline}"
|
2021-09-15 17:00:50 +08:00
|
|
|
}
|
|
|
|
|
2021-09-15 22:12:39 +08:00
|
|
|
# Wrap `then` and `do` to a separated line
|
2021-09-15 17:00:50 +08:00
|
|
|
# before: after:
|
2021-09-15 23:40:14 +08:00
|
|
|
# if [[ ... ]]; then if [[ ... ]]
|
|
|
|
# then
|
2021-09-15 17:00:50 +08:00
|
|
|
#
|
|
|
|
# before: after:
|
2021-09-15 23:40:14 +08:00
|
|
|
# if [[ ... ]] || if [[ ... ]] ||
|
2021-09-16 23:26:23 +08:00
|
|
|
# [[ ... ]]; then [[ ... ]]
|
2021-09-15 23:40:14 +08:00
|
|
|
# then
|
2021-09-15 17:00:50 +08:00
|
|
|
#
|
|
|
|
# before: after:
|
2021-09-15 23:40:14 +08:00
|
|
|
# for var in ...; do for var in ...
|
|
|
|
# do
|
2021-09-15 17:00:50 +08:00
|
|
|
#
|
2021-09-15 22:12:39 +08:00
|
|
|
wrap_then_do() {
|
2021-09-15 17:00:50 +08:00
|
|
|
local file="$1"
|
2021-09-15 23:40:14 +08:00
|
|
|
local tempfile="$2"
|
2021-09-15 17:00:50 +08:00
|
|
|
|
2021-09-16 23:26:23 +08:00
|
|
|
local -a processed=()
|
|
|
|
local -a buffer=()
|
2021-09-15 22:12:39 +08:00
|
|
|
local line
|
|
|
|
local singleline_then_regex='^( *)(el)?if (.+)\; (then( *#.*)?)$'
|
|
|
|
local singleline_do_regex='^( *)(for|while) (.+)\; (do( *#.*)?)$'
|
|
|
|
local multiline_if_begin_regex='^( *)(el)?if '
|
|
|
|
local multiline_then_end_regex='^(.*)\; (then( *#.*)?)$'
|
|
|
|
|
|
|
|
while IFS='' read -r line
|
|
|
|
do
|
|
|
|
if [[ "${#buffer[@]}" == 0 ]]
|
|
|
|
then
|
|
|
|
if [[ "${line}" =~ ${singleline_then_regex} ]]
|
|
|
|
then
|
|
|
|
processed+=("${BASH_REMATCH[1]}${BASH_REMATCH[2]}if ${BASH_REMATCH[3]}")
|
|
|
|
processed+=("${BASH_REMATCH[1]}${BASH_REMATCH[4]}")
|
|
|
|
elif [[ "${line}" =~ ${singleline_do_regex} ]]
|
|
|
|
then
|
|
|
|
processed+=("${BASH_REMATCH[1]}${BASH_REMATCH[2]} ${BASH_REMATCH[3]}")
|
|
|
|
processed+=("${BASH_REMATCH[1]}${BASH_REMATCH[4]}")
|
|
|
|
elif [[ "${line}" =~ ${multiline_if_begin_regex} ]]
|
|
|
|
then
|
|
|
|
buffer=("${line}")
|
|
|
|
else
|
|
|
|
processed+=("${line}")
|
|
|
|
fi
|
|
|
|
else
|
|
|
|
buffer+=("${line}")
|
|
|
|
if [[ "${line}" =~ ${multiline_then_end_regex} ]]
|
|
|
|
then
|
|
|
|
while IFS='' read -r line
|
|
|
|
do
|
|
|
|
processed+=("${line}")
|
|
|
|
done < <(align_multiline_if_condition "${buffer[@]}")
|
|
|
|
buffer=()
|
|
|
|
fi
|
|
|
|
fi
|
2021-09-15 23:40:14 +08:00
|
|
|
done <"${tempfile}"
|
2021-09-15 22:12:39 +08:00
|
|
|
|
2021-09-15 23:40:14 +08:00
|
|
|
printf "%s\n" "${processed[@]}" >"${tempfile}"
|
2021-09-15 17:00:50 +08:00
|
|
|
}
|
|
|
|
|
2021-09-16 23:26:23 +08:00
|
|
|
# TODO: It's hard to align multiline switch cases
|
2021-09-15 17:00:50 +08:00
|
|
|
align_multiline_switch_cases() {
|
|
|
|
true
|
|
|
|
}
|
|
|
|
|
2021-10-07 19:42:25 +08:00
|
|
|
# Return codes:
|
|
|
|
# 0: success, good styles
|
|
|
|
# 1: file system permission errors
|
|
|
|
# 2: shfmt failed
|
|
|
|
# 3: forbidden styles detected
|
|
|
|
# 4: bad styles but can be auto-fixed
|
2021-09-15 17:00:50 +08:00
|
|
|
format() {
|
|
|
|
local file="$1"
|
2021-09-16 23:16:07 +08:00
|
|
|
local tempfile
|
2021-09-15 22:12:39 +08:00
|
|
|
if [[ ! -f "${file}" || ! -r "${file}" ]]
|
|
|
|
then
|
|
|
|
onoe "File \"${file}\" is not readable."
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
|
2021-09-16 23:16:07 +08:00
|
|
|
tempfile="$(dirname "${file}")/.${file##*/}.temp"
|
2021-09-15 22:12:39 +08:00
|
|
|
trap 'rm -f "${tempfile}" 2>/dev/null' RETURN
|
2021-09-15 17:00:50 +08:00
|
|
|
cp -af "${file}" "${tempfile}"
|
|
|
|
|
2021-09-15 22:12:39 +08:00
|
|
|
if [[ ! -f "${tempfile}" || ! -w "${tempfile}" ]]
|
|
|
|
then
|
|
|
|
onoe "File \"${tempfile}\" is not writable."
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
|
2021-09-15 17:00:50 +08:00
|
|
|
# Format with `shfmt` first
|
2021-09-15 22:12:39 +08:00
|
|
|
if ! "${SHFMT}" -w "${SHFMT_ARGS[@]}" "${tempfile}"
|
|
|
|
then
|
2021-09-16 23:16:07 +08:00
|
|
|
onoe "Failed to run \`shfmt\` for file \"${file}\"."
|
2021-10-07 19:42:25 +08:00
|
|
|
return 2
|
2021-09-15 22:12:39 +08:00
|
|
|
fi
|
2021-09-15 17:00:50 +08:00
|
|
|
|
2021-09-16 23:16:07 +08:00
|
|
|
# Fail fast when forbidden styles detected
|
2021-10-07 19:42:25 +08:00
|
|
|
no_forbidden_styles "${file}" "${tempfile}" || return 3
|
2021-09-15 17:00:50 +08:00
|
|
|
|
|
|
|
# Tweak it with custom shell script styles
|
2021-09-15 23:40:14 +08:00
|
|
|
wrap_then_do "${file}" "${tempfile}"
|
|
|
|
align_multiline_switch_cases "${file}" "${tempfile}"
|
2021-09-15 17:00:50 +08:00
|
|
|
|
2021-09-27 21:13:11 +08:00
|
|
|
if ! "${DIFF}" -q "${file}" "${tempfile}" &>/dev/null
|
2021-09-15 17:00:50 +08:00
|
|
|
then
|
2021-09-15 22:12:39 +08:00
|
|
|
if [[ -n "${INPLACE}" ]]
|
|
|
|
then
|
2021-09-15 17:00:50 +08:00
|
|
|
cp -af "${tempfile}" "${file}"
|
2021-10-07 19:42:25 +08:00
|
|
|
else
|
|
|
|
# Show differences
|
|
|
|
"${DIFF}" "${DIFF_ARGS[@]}" "${file}" "${tempfile}"
|
2021-09-15 17:00:50 +08:00
|
|
|
fi
|
2021-10-07 19:42:25 +08:00
|
|
|
return 4
|
2021-09-15 17:00:50 +08:00
|
|
|
else
|
|
|
|
# File is identical between code formations (good styling)
|
2021-09-15 22:12:39 +08:00
|
|
|
return 0
|
2021-09-15 17:00:50 +08:00
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2021-09-15 22:12:39 +08:00
|
|
|
RETCODE=0
|
2021-09-15 17:00:50 +08:00
|
|
|
for file in "${FILES[@]}"
|
|
|
|
do
|
2021-10-07 19:42:25 +08:00
|
|
|
retcode=''
|
|
|
|
if [[ -n "${INPLACE}" ]]
|
2021-09-15 22:12:39 +08:00
|
|
|
then
|
2021-10-07 19:42:25 +08:00
|
|
|
INPLACE=1 format "${file}"
|
|
|
|
retcode="$?"
|
|
|
|
if [[ "${retcode}" == 4 ]]
|
2021-09-15 22:12:39 +08:00
|
|
|
then
|
2021-10-07 19:42:25 +08:00
|
|
|
onoe "${0##*/}: Bad styles detected in file \"${file}\", apply auto-fix."
|
|
|
|
retcode=''
|
2021-09-15 22:12:39 +08:00
|
|
|
fi
|
2021-10-07 19:42:25 +08:00
|
|
|
fi
|
|
|
|
if [[ -z "${retcode}" ]]
|
|
|
|
then
|
|
|
|
INPLACE='' format "${file}"
|
|
|
|
retcode="$?"
|
|
|
|
fi
|
|
|
|
if [[ "${retcode}" != 0 ]]
|
|
|
|
then
|
|
|
|
case "${retcode}" in
|
|
|
|
1) onoe "${0##*/}: Failed to format file \"${file}\". Formatter exited with code 1 (permission error)." ;;
|
|
|
|
2) onoe "${0##*/}: Failed to format file \"${file}\". Formatter exited with code 2 (\`shfmt\` failed)." ;;
|
|
|
|
3) onoe "${0##*/}: Failed to format file \"${file}\". Formatter exited with code 3 (forbidden styles detected)." ;;
|
|
|
|
4) onoe "${0##*/}: Fixable bad styles detected in file \"${file}\", run \`brew style --fix\` to apply. Formatter exited with code 4." ;;
|
|
|
|
*) onoe "${0##*/}: Failed to format file \"${file}\". Formatter exited with code ${retcode}." ;;
|
|
|
|
esac
|
2021-09-15 22:12:39 +08:00
|
|
|
onoe
|
|
|
|
RETCODE=1
|
|
|
|
fi
|
2021-09-15 17:00:50 +08:00
|
|
|
done
|
2021-09-15 22:12:39 +08:00
|
|
|
|
|
|
|
exit "${RETCODE}"
|