commit 157f056fd93b2dd5524f979394fe9f8fca45aed2
parent 12b555d9492a47bd3ffd2240ee810fc5fa95d53b
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Sat, 10 Feb 2024 19:39:43 +0100
Improve the status subcommand
Writes internal functions to help list WAD file paths. Previously, we
list the hashes of blobs and check each of them in an internal loop to
not only reject files not WAD but above all find their paths in the
current working tree. This could be ineffective with many WAD files
because finding a path required running the "git ls-tree" command for
each file. This commit offers a more elegant solution based on joints,
xargs and pipes.
Diffstat:
| M | git-wad | | | 83 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------- |
1 file changed, 57 insertions(+), 26 deletions(-)
diff --git a/git-wad b/git-wad
@@ -70,6 +70,62 @@ encode() # digest, size
printf "%s %s %d" "${GIT_WAD_HEADER}" "$1" "$2"
}
+# List hashes of WAD file from the current working tree
+# shellcheck disable=SC2120 # t $1 is optional
+wad_hashes() # [--all]
+{
+
+ rev="HEAD"
+
+ if [ $# -ge 1 ]; then
+ case "$1" in
+ "--all") rev="--all" ;;
+ *)
+ # shellsheck disable=SC2120
+ >&2 log "Invalid option %s\n" "$1"
+ return 1
+ ;;
+ esac
+ fi
+
+ # Regular expression of a WAD
+ wad_re="^${GIT_WAD_HEADER} [0-9a-z]\{64\} [0-9]\{1,\}$"
+
+
+ # The following command line can be translated as follows:
+ # Print the IDs of all objects in HEAD
+ # | Get their hash
+ # | Print object information of these hashes
+ # | Keep only objects that are blobs
+ # | Get their hash
+ # | Keep only the hash of blob objects that are WADs
+ git rev-list --objects "${rev}" \
+ | cut -d' ' -f1 \
+ | git cat-file --batch-check \
+ | sed -n "/[a-z0-9]\{40\} blob [0-9]\{1,\}/p" \
+ | cut -d' ' -f1 \
+ | xargs -I{} sh -c \
+ " git cat-file blob {} \
+ | sed -e '/${wad_re}/!d' -e 's/^.\{1,\}$/{}\n/'"
+}
+
+# List paths of WAD file from the current working tree
+wad_paths()
+{
+ # Store the hash of WAD file
+ hashes="$(mktemp -p "${GIT_WAD_OBJDIR}")"
+ wad_hashes | sort -b > "${hashes}"
+
+ # Lists the current tree, printing the hash and path of its files
+ # | Sort the result in ascending order
+ # | Print path for WAD files only
+ git ls-tree -r --format="%(objectname) %(path)" HEAD "${working_tree}" \
+ | sort -b \
+ | join -o 2.2 "${hashes}" - \
+
+ rm "${hashes}" # Remove temporary file
+}
+
# List WAD objects from the current working tree
wad_objects() # [--all]
{
@@ -331,32 +387,7 @@ status() # [--all]
unrestored="$(mktemp -p "${GIT_WAD_OBJDIR}")"
orphaned="$(mktemp -p "${GIT_WAD_OBJDIR}")"
- # The following command line can be translated as follows:
- # Print the IDs of all objects in HEAD
- # | Get their hash
- # | Print object information of these hashes
- # | Keep only objects that are blobs
- # | Get their hash
- # | And loop over them
- git rev-list --objects HEAD \
- | cut -d' ' -f1 \
- | git cat-file --batch-check \
- | grep -e "[a-z0-9]\{40\} blob [0-9]\{1,\}" \
- | cut -d' ' -f1 \
- | while read -r hash; do
-
- # Test if the object is a WAD
- is_wad="$(git cat-file blob "${hash}" \
- | sed -n "/^${GIT_WAD_HEADER} [0-9a-z]\{64\} [0-9]\{1,\}$/{p;q}")"
- [ -z "${is_wad}" ] && continue
-
- # From here on, the current hash refers to a WAD
-
- # Find the file name of the WAD in the current working tree
- wad="$(git ls-tree -r --format="%(objectname) %(path)" HEAD "${working_tree}" \
- | grep -e "^${hash} " \
- | cut -d' ' -f2)"
-
+ wad_paths | while read -r wad; do
# Read the WAD bytes corresponding to its header before it is restored
header_size="$(sizeof_header)"
header="$(dd if="${wad}" ibs=1 count="${header_size}" 2> /dev/null)"