racket-utils/shell.rkt
2024-05-07 15:42:57 +01:00

60 lines
1.7 KiB
Racket

#lang racket
(provide with-cwd
with-env
with-temporary-dir
chomp
run
run/strings)
(define-syntax with-cwd
(syntax-rules ()
((_ cwd body ...)
(parameterize ((current-directory cwd))
body ...))))
(define-syntax with-env
(syntax-rules ()
((_ env body ...)
(parameterize ((current-environment-variables (environment-variables-copy (current-environment-variables))))
(for-each (lambda (v) (putenv (car v) (cdr v))) env)
body ...))))
(define-syntax with-temporary-dir
(syntax-rules ()
((_ body ...)
(let ((tmp (chomp (run "mktemp" "-d"))))
(with-handlers (((lambda (v) #t)
(lambda (v)
(system* "/bin/rm" "-rf" tmp)
(raise v))))
(let ((res (with-cwd tmp body ...)))
(system* "/bin/rm" "-rf" tmp)
res))))))
(define (chomp s)
(string-trim s "\n" #:right? #t))
(define (read-lines port)
(let read-lines ((next-line (read-line port)) (accum '()))
(if (eof-object? next-line)
(reverse accum)
(read-lines (read-line port) (cons next-line accum)))))
(define (split-lines s)
(string-split s #px"(\r\n|\n|\r)"))
(define (run cmd . args)
(define-values (sp out in err) (apply subprocess #f #f #f (find-executable-path cmd) args))
(define stdout (port->string out))
(define stderr (port->string err))
(close-output-port in)
(close-input-port out)
(close-input-port err)
(subprocess-wait sp)
(if (not (zero? (subprocess-status sp)))
(raise-user-error 'run (format "error running ~a: ~a" cmd stderr))
stdout))
(define run/strings (compose split-lines run))