From ef3b12193f2102fca88abd9530f3dfb8ffc14616 Mon Sep 17 00:00:00 2001 From: "Kyle J. McKay" Date: Sun, 1 Dec 2013 22:58:12 -0800 Subject: [PATCH] shlib.sh: Add new bang_eval function The bang function provides a means to run commands with a well-defined failure mode. However, since it executes the arguments directly it's clumsy to use when the command that needs to be bang'd involves any redirection. Introduce a new bang_eval function that provides the same well-defined failure mode as the bang function but evals its command instead of directly executing it. --- shlib.sh | 79 ++++++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 22 deletions(-) diff --git a/shlib.sh b/shlib.sh index cc8cf57..79e961f 100644 --- a/shlib.sh +++ b/shlib.sh @@ -19,6 +19,35 @@ eval $(perl -I@basedir@ $__girocco_extrainc -M$__girocco_conf -le \ git() { "$cfg_git_bin" "$@"; } +# Supports both the bang CMD... and bang_eval CMD... functions +# Called when the command fails +# Should only be called from bang and bang_eval functions +bang_err() { + if ! [ -e .banged ]; then + bangmailok=true + ! [ -f HEAD -a -f config -a -d objects ] || + bangmailok="$(GIT_DIR=. git config --bool gitweb.statusupdates 2>/dev/null || echo true)" + bangaddrs='' + [ "$bangmailok" = "false" -o -z "$mail" ] || bangaddrs="$mail" + [ -z "$cfg_admincc" -o "$cfg_admincc" = "0" -o -z "$cfg_admin" ] || + if [ -z "$bangaddrs" ]; then bangaddrs="$cfg_admin"; else bangaddrs="$bangaddrs,$cfg_admin"; fi + [ -z "$bangaddrs" ] || + { + echo "$* failed with error code $errcode" + echo "" + [ ! -n "$bang_once" ] || echo "you will not receive any more notifications until recovery" + echo "this status message may be disabled on the project admin page" + echo "" + echo "Log follows:" + echo "" + cat "$bang_log" + } | mail -s "[$cfg_name] $proj $bang_action failed" "$bangaddrs" + fi + touch .banged + bang_trap + exit 1 +} + # bang CMD... will execute the command with well-defined failure mode; # set bang_action to string of the failed action ('clone', 'update', ...); # pre-set bang_once=1 to make sure jobs banging on a repo repeatedly will @@ -47,29 +76,35 @@ bang() { errcode="$?" fi fi - if ! [ -e .banged ]; then - bangmailok=true - ! [ -f HEAD -a -f config -a -d objects ] || - bangmailok="$(GIT_DIR=. git config --bool gitweb.statusupdates 2>/dev/null || echo true)" - bangaddrs='' - [ "$bangmailok" = "false" -o -z "$mail" ] || bangaddrs="$mail" - [ -z "$cfg_admincc" -o "$cfg_admincc" = "0" -o -z "$cfg_admin" ] || - if [ -z "$bangaddrs" ]; then bangaddrs="$cfg_admin"; else bangaddrs="$bangaddrs,$cfg_admin"; fi - [ -z "$bangaddrs" ] || - { - echo "$* failed with error code $errcode" - echo "" - [ ! -n "$bang_once" ] || echo "you will not receive any more notifications until recovery" - echo "this status message may be disabled on the project admin page" - echo "" - echo "Log follows:" - echo "" - cat "$bang_log" - } | mail -s "[$cfg_name] $proj $bang_action failed" "$bangaddrs" + bang_err "$@" +} + +# bang_eval CMD... will evaluate the command with well-defined failure mode; +# Identical to bang CMD... except the command is eval'd instead of executed. +bang_eval() { + if [ -n "$show_progress" ]; then + exec 3>&1 + errcode= + read -r errcode <<-EOT || : + $( + exec 4>&3 3>&1 1>&4 4>&- + { eval "$*" 3>&- || echo $? >&3; } 2>&1 | tee -a "$bang_log" + ) + EOT + exec 3>&- + if [ -z "$errcode" ]; then + # All right. Cool. + return; + fi + else + if eval "$*" >>"$bang_log" 2>&1; then + # All right. Cool. + return; + else + errcode="$?" + fi fi - touch .banged - bang_trap - exit 1 + bang_err "$@" } # Default bang settings: -- 2.11.4.GIT