81 lines
1.6 KiB
Bash
Executable file
81 lines
1.6 KiB
Bash
Executable file
#! /usr/bin/bash
|
|
|
|
set -euo pipefail
|
|
IFS=$'\n\t'
|
|
|
|
default_editor() {
|
|
if [ -n "${SUDO_EDITOR+set}" ]; then
|
|
echo "${SUDO_EDITOR}"
|
|
elif [ -n "${VISUAL+set}" ]; then
|
|
echo "${VISUAL}"
|
|
elif [ -n "${EDITOR+set}" ]; then
|
|
echo "${EDITOR}"
|
|
else
|
|
echo "No editor configured" 1>&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
try_command() {
|
|
if "$@" 2> /dev/null; then
|
|
return
|
|
elif run0 "$@" > /dev/null; then
|
|
return
|
|
else
|
|
exit 2
|
|
fi
|
|
}
|
|
|
|
make_editable_copy() {
|
|
orig_file="$1"
|
|
tempfile="$2"
|
|
|
|
try_command cp -- "${orig_file}" "${tempfile}"
|
|
}
|
|
|
|
elevate_permissions() {
|
|
tempfile="$1"
|
|
orig_file="$2"
|
|
|
|
try_command chown --reference "${orig_file}" "${tempfile}"
|
|
try_command chmod --reference "${orig_file}" "${tempfile}"
|
|
}
|
|
|
|
update_file() {
|
|
tempfile="$1"
|
|
orig_file="$2"
|
|
|
|
try_command mv --force -- "${tempfile}" "${orig_file}"
|
|
}
|
|
|
|
clean_tempfiles() {
|
|
tempfile="$1"
|
|
|
|
rm --force -- "${tempfile}" "${tempfile}.orig"
|
|
}
|
|
|
|
if [ "$#" -ne "1" ]; then
|
|
echo "Expected exactly one input file. Usage:" 1>&2
|
|
echo " $0 FILE" 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
editor_cmd="$(default_editor)"
|
|
echo "Editing using the command \"${editor_cmd}\""
|
|
|
|
IFS=' ' read -r -a editor <<< "${editor_cmd}"
|
|
|
|
orig_file="$1"
|
|
tempfile="$(mktemp)"
|
|
echo "Using temporary file ${tempfile}"
|
|
make_editable_copy "${orig_file}" "${tempfile}"
|
|
cp "${tempfile}" "${tempfile}.orig"
|
|
"${editor[@]}" "${tempfile}"
|
|
if cmp --quiet "${tempfile}" "${tempfile}.orig"; then
|
|
echo "No change to file"
|
|
else
|
|
elevate_permissions "${tempfile}" "${orig_file}"
|
|
update_file "${tempfile}" "${orig_file}"
|
|
fi
|
|
|
|
clean_tempfiles "${tempfile}"
|