|
| 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