diff options
| author | Ludovic Courtès <ludo@gnu.org> | 2019-03-16 17:07:57 +0100 |
|---|---|---|
| committer | Ludovic Courtès <ludo@gnu.org> | 2019-03-16 18:15:13 +0100 |
| commit | f0cc5e7e1e4c03af29c5d4855dc5962502c49147 (patch) | |
| tree | 8ed975abe2ac957b165a7f32900c739949f01cf5 /gnu | |
| parent | 22f95e028f038cee342f455dfc55bd32b804907c (diff) | |
booloader: Add 'invoke/quiet'.
* gnu/build/bootloader.scm (G_): New macro.
(open-pipe-with-stderr, invoke/quiet): New procedures.
* tests/build-utils.scm ("invoke/quiet, success")
("invoke/quiet, failure")
("invoke/quiet, failure, message on stderr"): New tests.
* po/guix/POTFILES.in: Add bootloader.scm.
Diffstat (limited to 'gnu')
| -rw-r--r-- | gnu/build/bootloader.scm | 63 |
1 files changed, 62 insertions, 1 deletions
diff --git a/gnu/build/bootloader.scm b/gnu/build/bootloader.scm index d00674dd40f..c5febcde1ea 100644 --- a/gnu/build/bootloader.scm +++ b/gnu/build/bootloader.scm | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | ;;; GNU Guix --- Functional package management for GNU | 1 | ;;; GNU Guix --- Functional package management for GNU |
| 2 | ;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com> | 2 | ;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com> |
| 3 | ;;; Copyright © 2019 Ludovic Courtès <ludo@gnu.org> | ||
| 3 | ;;; | 4 | ;;; |
| 4 | ;;; This file is part of GNU Guix. | 5 | ;;; This file is part of GNU Guix. |
| 5 | ;;; | 6 | ;;; |
| @@ -17,8 +18,15 @@ | |||
| 17 | ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. | 18 | ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. |
| 18 | 19 | ||
| 19 | (define-module (gnu build bootloader) | 20 | (define-module (gnu build bootloader) |
| 21 | #:use-module (srfi srfi-34) | ||
| 22 | #:use-module (srfi srfi-35) | ||
| 20 | #:use-module (ice-9 binary-ports) | 23 | #:use-module (ice-9 binary-ports) |
| 21 | #:export (write-file-on-device)) | 24 | #:use-module (ice-9 popen) |
| 25 | #:use-module (ice-9 match) | ||
| 26 | #:use-module (ice-9 rdelim) | ||
| 27 | #:use-module (ice-9 format) | ||
| 28 | #:export (write-file-on-device | ||
| 29 | invoke/quiet)) | ||
| 22 | 30 | ||
| 23 | 31 | ||
| 24 | ;;; | 32 | ;;; |
| @@ -35,3 +43,56 @@ | |||
| 35 | (seek output offset SEEK_SET) | 43 | (seek output offset SEEK_SET) |
| 36 | (put-bytevector output bv)) | 44 | (put-bytevector output bv)) |
| 37 | #:binary #t))))) | 45 | #:binary #t))))) |
| 46 | |||
| 47 | (define-syntax-rule (G_ str) str) ;for xgettext | ||
| 48 | |||
| 49 | (define (open-pipe-with-stderr program . args) | ||
| 50 | "Run PROGRAM with ARGS in an input pipe, but, unlike 'open-pipe*', redirect | ||
| 51 | both its standard output and standard error to the pipe. Return two value: | ||
| 52 | the pipe to read PROGRAM's data from, and the PID of the child process running | ||
| 53 | PROGRAM." | ||
| 54 | ;; 'open-pipe*' doesn't attempt to capture stderr in any way, which is why | ||
| 55 | ;; we need to roll our own. | ||
| 56 | (match (pipe) | ||
| 57 | ((input . output) | ||
| 58 | (match (primitive-fork) | ||
| 59 | (0 | ||
| 60 | (dynamic-wind | ||
| 61 | (const #t) | ||
| 62 | (lambda () | ||
| 63 | (close-port input) | ||
| 64 | (dup2 (fileno output) 1) | ||
| 65 | (dup2 (fileno output) 2) | ||
| 66 | (apply execlp program program args)) | ||
| 67 | (lambda () | ||
| 68 | (primitive-exit 127)))) | ||
| 69 | (pid | ||
| 70 | (close-port output) | ||
| 71 | (values input pid)))))) | ||
| 72 | |||
| 73 | ;; TODO: Move to (guix build utils) on the next rebuild cycle. | ||
| 74 | (define (invoke/quiet program . args) | ||
| 75 | "Invoke PROGRAM with ARGS and capture PROGRAM's standard output and standard | ||
| 76 | error. If PROGRAM succeeds, print nothing and return the unspecified value; | ||
| 77 | otherwise, raise a '&message' error condition that includes the status code | ||
| 78 | and the output of PROGRAM." | ||
| 79 | (define-values (pipe pid) | ||
| 80 | (apply open-pipe-with-stderr program args)) | ||
| 81 | |||
| 82 | (let loop ((lines '())) | ||
| 83 | (match (read-line pipe) | ||
| 84 | ((? eof-object?) | ||
| 85 | (close-port pipe) | ||
| 86 | (match (waitpid pid) | ||
| 87 | ((_ . status) | ||
| 88 | (unless (zero? status) | ||
| 89 | (raise (condition | ||
| 90 | (&message | ||
| 91 | (message (format #f (G_ "'~a~{ ~a~}' exited with status ~a; \ | ||
| 92 | output follows:~%~%~{ ~a~%~}") | ||
| 93 | program args | ||
| 94 | (or (status:exit-val status) | ||
| 95 | status) | ||
| 96 | (reverse lines)))))))))) | ||
| 97 | (line | ||
| 98 | (loop (cons line lines)))))) | ||
