commit 4ba9f0473ec4eff6f71257fc0535c0a76192c3c1
parent 527ab995e78d293eeb381b8a266432d9b25d5091
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Sun, 12 Jan 2025 15:28:47 +0100
Improves checksum portability
sha256sum is no longer a prerequisite: in its absence, git-wad tries to
use shasum and, failing that, sha256. sha256sum is present by default on
GNU/Linux, where shasum should be used on Darwin or DragonFly BSD, and
sha256 on OpenBSD, NetBSD or certain versions of FreeBSD. And so cover a
wide range of POSIX systems.
Diffstat:
| M | README.md | | | 2 | +- |
| M | git-wad | | | 80 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------- |
2 files changed, 70 insertions(+), 12 deletions(-)
diff --git a/README.md b/README.md
@@ -8,7 +8,7 @@ Git filters used to manage files based on their digest.
- POSIX shell
- curl
- rsync
-- sha256sum
+- sha256sum, shasum or sha256
- [mandoc](https://mandoc.bsd.lv)
## Installation
diff --git a/git-wad b/git-wad
@@ -35,6 +35,13 @@ fi
# multi-byte encoding errors.
alias sed__='LC_CTYPE=C sed'
+if ! command -v sha256sum 1> /dev/null 2>&1 \
+&& ! command -v shasum 2> /dev/null \
+&& ! command -v sha256 2> /dev/null; then
+ >&2 printf 'No tool to process SHA256 checksum\n'
+ die
+fi
+
# shellcheck disable=SC2310
working_tree="$(git rev-parse --show-toplevel)" || die "$?"
git_wad_tmpdir="$(mktemp -d "${TMPDIR:-/tmp}/git_wad_XXXXXX")" || die "$?"
@@ -261,6 +268,40 @@ restore() # WAD file
fi
}
+checksum() # [-c]
+{
+ if command -v sha256sum 1> /dev/null 2>&1; then
+ sha256sum "$@"
+
+ elif command -v shasum 1> /dev/null 2>&1; then
+ shasum -a 256 "$@"
+
+ elif command -v sha256 1> /dev/null 2>&1; then
+ sha256re='SHA256 (\([^)]\+\)) = \([0-9a-zA-Z]\{64\}\)$'
+
+ # Calculate checksum
+ if [ "$#" -eq 1 ] || [ "$1" != "-c" ]; then
+ sha256 | sed__ "s/${sha256re}/\2 \1/"
+
+ # Check checksum
+ else
+ shift 1 # Discard the -c option
+
+ in="$(cat -)"
+ ref="$(echo "${in}" | cut -d' ' -f1)"
+ file="$(echo "${in}" | cut -d' ' -f3)"
+
+ sum="$(sha256 "${file}" | sed__ "s/${sha256re}/\2 \1/")"
+ if [ "${ref}" = "${sum}" ]; then
+ printf '%s: OK\n' "${file}"
+ else
+ printf '%s: FAILED\n' "${file}"
+ return 1
+ fi
+ fi
+ fi
+}
+
########################################################################
# Git filters (plumbing)
########################################################################
@@ -275,7 +316,7 @@ log() # str [, arg...]
clean() # stdin
{
tmpclean="${git_wad_tmpdir}/tmpclean"
- digest=$(cat - | tee "${tmpclean}" | sha256sum | cut -d' ' -f1)
+ digest=$(cat - | tee "${tmpclean}" | checksum | cut -d' ' -f1)
size=$(wc -c < "${tmpclean}")
# Copy all bytes that could correspond to a WAD header. Note that null
@@ -424,16 +465,33 @@ fsck()
wads="${git_wad_tmpdir}/wads"
all_objects > "${wads}"
-
- xargs -I {} sh -c \
- "printf '%s %s/%s' \"{}\" \"${GIT_WAD_OBJDIR}\" \"{}\" \
- | sha256sum -c || { \
- if [ ! ${remove} -eq 0 ]; then \
- printf '\e[0;31mremove\e[0m %s\n' \"{}\"; \
- rm -f \"${GIT_WAD_OBJDIR}/{}\"; \
- fi
- }" \
- < "${wads}"
+ n=$(wc -l "${wads}" | cut -d' ' -f1)
+ [ "${n}" -eq 0 ] && return # No WAD, i.e. nothing to do
+
+ # Prepare checksum verification of WADs, i.e. list one line per file
+ # starting with the WAD's checksum (actually its name) followed by 2
+ # spaces and its path.
+ sums="${git_wad_tmpdir}/sums"
+ xargs -I{} printf '%s %s/%s\n' "{}" "${GIT_WAD_OBJDIR}" "{}" \
+ < "${wads}" > "${sums}"
+
+ # Check WAD checksum.
+ #
+ # Redirect the error stream to standard output to ensure that messages
+ # are printed in the order in which they are sent. By using a pipe,
+ # the shell starts a new process for the tee command which, if it only
+ # processes normal messages, will intertwine with the error messages
+ # from the checksum command.
+ result="${git_wad_tmpdir}/result"
+ checksum -c < "${sums}" 2>&1 | tee "${result}"
+
+ # Remove corrupted files
+ if [ ! "${remove}" -eq 0 ]; then
+ corrupted_wads="${git_wad_tmpdir}/corrupted_wads"
+ sed__ -n 's/^\(.\+\): FAILED$/\1/p' "${result}" > "${corrupted_wads}"
+ sed__ 's/^/remove /g' "${corrupted_wads}"
+ xargs -I{} rm -f "{}" < "${corrupted_wads}"
+ fi
}
# Restore the content of WAD files