Browse Source

Do not always create cache

If exit status is not zero, do not create cache, but allow user to
override the default match.
Alois Mahdal 6 years ago
parent
commit
d1e64e537a
1 changed files with 48 additions and 6 deletions
  1. 48
    6
      src/cached.sh.skel

+ 48
- 6
src/cached.sh.skel View File

@@ -33,10 +33,11 @@ cached() {
33 33
     # Usage:
34 34
     #
35 35
     #     CACHED__ROOT=$HOME/.cache/myapp
36
-    #     cached [-m] [-w] [-a ATTR] CMD [ARG]
36
+    #     cached [-m] [-w] [-a ATTR] [-e ES_EXPR] CMD [ARG]
37 37
     #
38 38
     # Look up CMD with any ARGs in local cache and return result on hit.
39
-    # In case of miss, run command to create the cache first.
39
+    # In case of miss, run command and if exit status is zero (can be changed
40
+    # by -e argument; see below), create the cache and return it.
40 41
     #
41 42
     # Cache objects are identified by computing a MD5 hash from combination
42 43
     # of several attributes.  By default, only CMD and ARGs are included;
@@ -62,6 +63,19 @@ cached() {
62 63
     # All cache objects are queried or created under directory specified by
63 64
     # global variable $CACHED__ROOT, which must be specified beforehand.
64 65
     #
66
+    # Exit status has to match ES_EXPR in order to be matched.  ES_EXPR has
67
+    # form of comma-separated list of exit statuses or simple exit status
68
+    # ranges. Valid ranges are: `N` which matches exactly `N` or `M-N`,
69
+    # which matches any status from `M` to `N` inclusively.
70
+    #
71
+    # For example, following commands do or do not create cache (assuming
72
+    # no cache hit):
73
+    #
74
+    #     cached false              # no: by default ES_EXPR is only 0
75
+    #     cached -e 0,1 false       # yes: 1 matches `0,1`
76
+    #     cached -e 0-3,9 exit_4    # no: 4 does not match `0-3,9`
77
+    #     cached -e 0-3,9 exit_3    # yes: 3 matches `0-3,9`
78
+    #
65 79
     # NOTE: Caching of commands that process standard input is not supported.
66 80
     # (I.e. cached() will close standard input immediately.)
67 81
     #
@@ -73,9 +87,11 @@ cached() {
73 87
     local ObjPath           # cache object path
74 88
     local MatchWD=false     # does workdir matter?
75 89
     local Attr              # custom attribute
90
+    local EsExpr=0          # allowed exit status
76 91
     while true; do case $1 in
77 92
         --)     shift; break ;;
78 93
         -a)     Attr=$2; shift 2 || return 2 ;;
94
+        -e)     EsExpr=$2; shift 2 || return 2 ;;
79 95
         -w)     MatchWD=true; shift ;;
80 96
         -m)     Miss=true; shift ;;
81 97
         -*)     warn "bad argument: $1"; return 2 ;;
@@ -161,6 +177,20 @@ __cached__describe() {
161 177
     test -n "$Attr" && echo "Attr=$Attr"
162 178
 }
163 179
 
180
+__cached__es_match() {
181
+    #
182
+    # True if exit status $1 matches expression $EsExpr
183
+    #
184
+    local es=$1
185
+    local part
186
+    for part in ${EsExpr//,/ }; do
187
+        test -n "$part" || continue
188
+        #FIXME: a rather funny implementation (works, though...)
189
+        eval "echo {${part/-/..}}" | grep -qwF "$es" && return 0
190
+    done
191
+    return 1
192
+}
193
+
164 194
 __cached__hit() {
165 195
     #
166 196
     # True if $Command has cache hit
@@ -194,16 +224,28 @@ __cached__pull() {
194 224
 
195 225
 __cached__run() {
196 226
     #
197
-    # Run command, creating cache object
227
+    # Run command, creating cache object if exit status matches $EsExpr
198 228
     #
199 229
     local es        # command exit status
200 230
     rm -rf "$ObjPath"
201 231
     mkdir -p "$ObjPath"
202 232
     __cached__describe >"$ObjPath/desc"
203 233
     eval "$Command" \
204
-        >"$ObjPath/out"\
205
-        2>"$ObjPath/err"; es=$?
206
-    echo $es>"$ObjPath/es"
234
+        >"$ObjPath/out.tmp"\
235
+        2>"$ObjPath/err.tmp"; es=$?
236
+    echo $es>"$ObjPath/es.tmp"
237
+    if __cached__es_match $es; then
238
+        mv "$ObjPath/out.tmp" "$ObjPath/out"
239
+        mv "$ObjPath/err.tmp" "$ObjPath/err"
240
+        mv "$ObjPath/es.tmp" "$ObjPath/es"
241
+    else
242
+        warn "bad exit status; skipping cache creation: $es does not match $EsExpr"
243
+        cat "$ObjPath/out.tmp"
244
+        cat "$ObjPath/err.tmp" >&2
245
+        rm "$ObjPath/out.tmp"
246
+        rm "$ObjPath/err.tmp"
247
+        rm "$ObjPath/es.tmp"
248
+    fi
207 249
     return $es
208 250
 }
209 251