Skip to content

Commit be79571

Browse files
committed
system call API
1 parent 9340e10 commit be79571

File tree

5 files changed

+421
-3
lines changed

5 files changed

+421
-3
lines changed

docs/gtp-plot.scrbl

+25-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,29 @@
11
#lang scribble/manual
2-
@require[(for-label racket/base)]
2+
@require[
3+
(for-label
4+
racket/base
5+
racket/contract
6+
(only-in openssl/md5 md5))]
37

48
@title{GTP plot}
9+
@author{Ben Greenman}
510

6-
TBA
11+
@;@defmodule[gtp-plot/plot]{
12+
@;
13+
@;}
14+
15+
@defmodule[gtp-plot/system]{
16+
Convenience API for making system calls.
17+
}
18+
19+
See also @racketmodname[racket/system].
20+
21+
@defproc[(shell [cmd path-string?] [arg* (or/c path-string? (listof path-string?))] ...) string?]{
22+
Finds the executable that @racket[cmd] denotes, then invokes it with the given arguments.
23+
Returns a string containing all output from the system call.
24+
Raises an @racket[exn:fail:user?] exception if the executable exits uncleanly.
25+
}
26+
27+
@defproc[(md5sum [filename path-string?]) string?]{
28+
Same as @racket[(call-with-input-file filename md5)].
29+
}

private/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
private
22
===
33

4-
Implementation of `gtp-plot` package.
4+
Implementation of `gtp-plot`

private/system.rkt

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#lang racket/base
2+
3+
;; API for making system calls
4+
5+
(require racket/contract)
6+
(provide
7+
(contract-out
8+
[shell
9+
(-> path-string? (or/c path-string? (listof path-string?)) string?)]
10+
;; `(shell cmd arg*)` finds the executable that `cmd` denotes,
11+
;; then invokes the executable with arguments `arg*`.
12+
;; Raises an exception if the executable exists uncleanly,
13+
;; otherwise returns a string containing all output produced by the exe.
14+
15+
[md5sum
16+
(-> path-string? string?)]
17+
;; Compute MD5 hash of the contents of the given file
18+
19+
))
20+
21+
(require
22+
gtp-plot/private/util
23+
(only-in openssl/md5
24+
md5)
25+
(only-in racket/port
26+
with-output-to-string)
27+
(only-in racket/string
28+
string-trim)
29+
(only-in racket/system
30+
system*))
31+
32+
;; =============================================================================
33+
34+
(define (shell pre-exe pre-cmd)
35+
(define exe (find-exe pre-exe))
36+
(define success? (box #f))
37+
(define cmd* (map path-string->string (if (path-string? pre-cmd) (list pre-cmd) pre-cmd)))
38+
(define str
39+
(with-output-to-string
40+
(lambda ()
41+
(set-box! success? (apply system* exe cmd*)))))
42+
(if (unbox success?)
43+
(string-trim str)
44+
(raise-user-error 'shell "failed to apply '~a' to arguments '~a'" exe cmd*)))
45+
46+
;; find-exe : path-string? -> path-string?
47+
(define (find-exe pre-exe)
48+
(define fep (find-executable-path pre-exe))
49+
(if (path? fep)
50+
fep
51+
(raise-user-error 'shell "cannot find executable '~a', please install and try again" pre-exe)))
52+
53+
(define (md5sum ps)
54+
(call-with-input-file ps md5))
55+
56+
;; =============================================================================
57+
58+
(module+ test
59+
(require rackunit racket/runtime-path (only-in racket/string string-split))
60+
(define-runtime-path a-text-file "README.md")
61+
62+
(test-case "shell"
63+
(check-regexp-match #rx"^Welcome to Racket"
64+
(shell "racket" '("--version"))))
65+
66+
(test-case "find-exe"
67+
(check-equal?
68+
(find-exe "racket")
69+
(find-executable-path "racket"))
70+
(check-exn exn:fail:user?
71+
(lambda () (find-exe "this-is-not-racket-this-is-sparta"))))
72+
73+
(test-case "md5sum"
74+
(define (check-md5 ps)
75+
(define openssl-md5 (md5sum a-text-file))
76+
(define system-md5 (car (string-split (shell "md5sum" (path->string a-text-file)))))
77+
(check-equal? openssl-md5 system-md5))
78+
79+
(check-md5 a-text-file)
80+
)
81+
)

0 commit comments

Comments
 (0)