Skip to content

Commit 5b4b46c

Browse files
authored
Fix #181: support :discard or ProcessBuilder$Redirect for :out and :err (#182)
* discard * Fix #181: support :discard or ProcessBuilder$Redirect for :out and :err * defmacro * wip
1 parent 2064066 commit 5b4b46c

File tree

3 files changed

+39
-5
lines changed

3 files changed

+39
-5
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
[Babashka process](https://github.com/babashka/process)
44
Clojure library for shelling out / spawning sub-processes
55

6+
## 0.6.24 (2025-12-07)
7+
8+
- [#181](https://github.com/babashka/process/issues/181): support `:discard` or `ProcessBuilder$Redirect` as `:out` and `:err` options
9+
610
## 0.6.23 (2025-03-31)
711

812
- [#163](https://github.com/babashka/process/issues/163), [#164](https://github.com/babashka/process/issues/164): Program resolution strategy for `exec` and Windows now matches macOS/Linux/PowerShell ([@lread](https://github.com/lread))

src/babashka/process.cljc

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,12 @@
219219
:escape default-escape
220220
:program-resolver default-program-resolver})
221221

222-
(defn- normalize-opts [{:keys [:out :err :in :inherit] :as opts}]
222+
(def ^java.io.File null-file
223+
(delay (io/file (if windows?
224+
"NUL"
225+
"/dev/null"))))
226+
227+
(defn- normalize-opts [{:keys [out err in inherit] :as opts}]
223228
(cond-> opts
224229
(and inherit (not out))
225230
(-> (assoc :out :inherit))
@@ -265,13 +270,21 @@
265270
:inherit (.redirectOutput pb ProcessBuilder$Redirect/INHERIT)
266271
:write (.redirectOutput pb (ProcessBuilder$Redirect/to (io/file (str out-file))))
267272
:append (.redirectOutput pb (ProcessBuilder$Redirect/appendTo (io/file (str out-file))))
268-
nil)
273+
:discard (.redirectOutput pb (if-before-jdk8
274+
(ProcessBuilder$Redirect/to @null-file)
275+
ProcessBuilder$Redirect/DISCARD))
276+
(when (instance? java.lang.ProcessBuilder$Redirect out)
277+
(.redirectOutput pb out)))
269278
(case err
270279
:out (.redirectErrorStream pb true)
271280
:inherit (.redirectError pb ProcessBuilder$Redirect/INHERIT)
272281
:write (.redirectError pb (ProcessBuilder$Redirect/to (io/file (str err-file))))
273282
:append (.redirectError pb (ProcessBuilder$Redirect/appendTo (io/file (str err-file))))
274-
nil)
283+
:discard (.redirectError pb (if-before-jdk8
284+
(ProcessBuilder$Redirect/to @null-file)
285+
ProcessBuilder$Redirect/DISCARD))
286+
(when (instance? java.lang.ProcessBuilder$Redirect err)
287+
(.redirectError pb err)))
275288
(case in
276289
:inherit (.redirectInput pb ProcessBuilder$Redirect/INHERIT)
277290
(when (or (instance? java.io.File in)
@@ -385,12 +398,14 @@
385398
stderr (.getErrorStream proc)
386399
out (if (and out (or (identical? :string out)
387400
(identical? :bytes out)
388-
(not (keyword? out))))
401+
(and (not (keyword? out))
402+
(not (instance? java.lang.ProcessBuilder$Redirect out)))))
389403
(future (copy stdout out out-enc))
390404
stdout)
391405
err (if (and err (or (identical? :string err)
392406
(identical? :bytes err)
393-
(not (keyword? err))))
407+
(and (not (keyword? err))
408+
(not (instance? java.lang.ProcessBuilder$Redirect err)))))
394409
(future (copy stderr err err-enc))
395410
stderr)]
396411
;; wrap in futures, see https://github.com/clojure/clojure/commit/7def88afe28221ad78f8d045ddbd87b5230cb03e
@@ -470,6 +485,7 @@
470485
For writing output to a file, you can set `:out` and `:err` to a `java.io.File` object, or a keyword:
471486
- `:write` + an additional `:out-file`/`:err-file` + file to write to the file.
472487
- `:append` + an additional `:out-file`/`:err-file` + file to append to the file.
488+
To discard `:out` or `:err`, use `:discard`
473489
- `:prev`: output from `:prev` will be piped to the input of this process. Overrides `:in`.
474490
- `:inherit`: if true, sets `:in`, `:out` and `:err` to `:inherit`.
475491
- `:dir`: working directory.

test/babashka/process_test.cljc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,3 +627,17 @@
627627
:out)]
628628
(is (bytes? result))
629629
(is (= (seq ba) (seq result))))))
630+
631+
(defmacro if-pre-jdk9+ [then else]
632+
(if (identical? ::pre-jdk9
633+
(try (import 'java.lang.ProcessHandle)
634+
(catch Exception _ ::pre-jdk9)))
635+
then else))
636+
637+
(deftest discard-test
638+
(when-let [bb (u/find-bb)]
639+
(doseq [out [:discard (if-pre-jdk9+ :discard java.lang.ProcessBuilder$Redirect/DISCARD)]]
640+
(is (= "" (slurp (:out @(p/process {:out out} bb "-e" "(println :dude) (binding [*out* *err*] (println :bye))")))))
641+
(is (= (with-out-str (println :bye)) (slurp (:err @(p/process {:out out} bb "-e" "(println :dude) (binding [*out* *err*] (println :bye))")))))
642+
(is (= "" (slurp (:err @(p/process {:err out} bb "-e" "(println :dude) (binding [*out* *err*] (println :bye))")))))
643+
(is (= (with-out-str (println :dude)) (slurp (:out @(p/process {:err out} bb "-e" "(println :dude) (binding [*out* *err*] (println :bye))"))))))))

0 commit comments

Comments
 (0)