The core protocol of WoopChain
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
woop/scripts/xargs_by_dir.sh

58 lines
1.3 KiB

#!/usr/bin/env bash
#
# usage: xargs_by_dir.sh cmd [args...] < pathnames
#
# Run a command with pathnames given over stdin, grouping pathnames by its
# dirname and supplying each invocation of the command with pathnames in the
# same directory. This is useful for commands that require all pathname
# arguments to be in the same directory, such as go generate.
set -eu
dirname() {
case "${1}" in
*/*) echo "${1%/*}";;
*) echo ".";;
esac
}
unset -v cmd ok
declare -a cmd=("${@}")
ok=true
run_cmd() {
case $# in 0) return;; esac
"${cmd[@]}" "${@}" || ok=false
}
# sort the input list by directory; replace stdin with the sorted list
unset -v sorted_list
trap 'case "${sorted_list-}" in ?*) rm -f "${sorted_list}";; esac' EXIT
sorted_list=$(mktemp)
sort -t/ > "${sorted_list}"
exec < "${sorted_list}"
unset -v last_dir dir path
set --
while read -r path
do
# dirname of the next item to consider
dir=$(dirname "${path}")
# the same dir as the last one?
case "${last_dir-}" in
"${dir}")
# same dir; do not flush the list
;;
*)
# dir change; run with items seen so far and flush the list
run_cmd "${@}"
set --
;;
esac
# add the item, update the last-seen dir for the next iteration
set -- "${@}" "${path}"
last_dir="${dir}"
done
# seen the last file; run with items seen so far
run_cmd "${@}"
${ok} && exit 0 || exit 1