Skip to content

Commit a17483c

Browse files
committed
Add *pipefile* and *errexit* to sh-dsl.
These dynamic bindings are analogs to set -o pipefile and set -o errexit
1 parent 3bdcf58 commit a17483c

File tree

3 files changed

+52
-3
lines changed

3 files changed

+52
-3
lines changed

spork/declare-cc.janet

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@
201201
be run in the environment dictated by (dyn :modpath)."
202202
[&opt root-directory]
203203
(var errors-found 0)
204+
# TODO - flycheck all tests before running them - fail quickly
204205
(defn dodir
205206
[dir]
206207
(each sub (sort (os/dir dir))

spork/sh-dsl.janet

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
### sh-dsl.janet
66
###
77

8+
(defdyn *pipefail* "When set, the return value of a pipeline is the last non-zero exit code instead of the default right-most exit code")
9+
(defdyn *errexit* "When set, error immediately if pipelines run with `$`, `$<`, or `$<_` return with a non-zero exit code.")
10+
811
(def- parse-env-set-peg (peg/compile '(* '(to "=") "=" ':S*)))
912

1013
# Re-implements ev/go-gather
@@ -40,6 +43,25 @@
4043

4144
# End ev/go-gather
4245

46+
(defn- last-nonzero
47+
[xs]
48+
(var ret 0)
49+
(each x xs (when (not= 0 x) (set ret x)))
50+
ret)
51+
52+
(defn- pipeline-results
53+
[xs]
54+
(def status-codes (filter number? xs))
55+
(assert (next status-codes)) # we must have at least 1 status code
56+
(let [rc (if (dyn *pipefail*)
57+
(last-nonzero status-codes)
58+
(last status-codes))]
59+
(if (not= 0 rc)
60+
(if (dyn *errexit*)
61+
(error (string/format "non-zero exit code %v" rc))
62+
rc)
63+
(last xs))))
64+
4365
(defn- string-token [x]
4466
(if (bytes? x)
4567
(string x)
@@ -73,6 +95,7 @@
7395
(def procs @[])
7496
(def fds @[])
7597
(var pipein nil)
98+
(var out nil)
7699
(defn getfd [f] (array/push fds f) f)
77100

78101
(defer
@@ -140,8 +163,10 @@
140163
(ev/read final-pipe :all capture-buf)
141164
capture-buf)))
142165

143-
(def out (wait-thunks thunks))
144-
(if return-all out (last out))))
166+
(set out (wait-thunks thunks)))
167+
168+
# Outside defer for better stack trace on error
169+
(if return-all out (pipeline-results out)))
145170

146171
###
147172
### DSL Parsing

test/suite-sh-dsl.janet

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,29 @@
3131

3232
# More pipes using just janet
3333
(def version (buffer janet/version "-" janet/build))
34-
(assert (deep= version ($<_ ,janet --version | ,janet -e '(prin (:read stdin :all)))) "janet pipe example"))
34+
(assert (deep= version ($<_ ,janet --version | ,janet -e '(prin (:read stdin :all)))) "janet pipe example")
35+
36+
# Pipefail
37+
(setdyn *pipefail* true)
38+
(assert ($< echo) "echo pipefail 1")
39+
(assert (deep= @"hi\n" ($< echo hi)) "echo pipefail 2")
40+
(assert (deep= @"hi" ($<_ echo hi)) "echo pipefail 3")
41+
(assert (= 1 ($< ,janet -e "(os/exit 0)" | ,janet -e "(os/exit 1)" | ,janet -e "(os/exit 0)")) "pipefail 1")
42+
43+
# Errexit
44+
(setdyn *pipefail* false)
45+
(setdyn *errexit* true)
46+
(assert ($< echo) "echo errexit 1")
47+
(assert (deep= @"hi\n" ($< echo hi)) "echo errexit 2")
48+
(assert (deep= @"hi" ($<_ echo hi)) "echo errexit 3")
49+
(assert-error "errexit grep" ($ echo hi | grep nope))
50+
51+
# Pipefail and Errexit
52+
(setdyn *pipefail* true)
53+
(assert ($< echo) "echo pipefail + errexit 1")
54+
(assert (deep= @"hi\n" ($< echo hi)) "echo pipefail + errexit 2")
55+
(assert (deep= @"hi" ($<_ echo hi)) "echo pipefail + errexit 3")
56+
(assert-error "pipefail + errexit grep" ($ echo hi | grep nope))
57+
(assert-error "pipefail + errexit grep" ($ echo hi | grep nope | ,janet -e "(os/exit 0)")))
3558

3659
(end-suite)

0 commit comments

Comments
 (0)