summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/guix.texi19
-rw-r--r--guix/scripts/system.scm10
-rw-r--r--guix/ui.scm55
3 files changed, 68 insertions, 16 deletions
diff --git a/doc/guix.texi b/doc/guix.texi
index a4aa1b67fab..a97436cc0c1 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -5995,6 +5995,25 @@ For the @code{vm-image} and @code{disk-image} actions, create an image
5995of the given @var{size}. @var{size} may be a number of bytes, or it may 5995of the given @var{size}. @var{size} may be a number of bytes, or it may
5996include a unit as a suffix (@pxref{Block size, size specifications,, 5996include a unit as a suffix (@pxref{Block size, size specifications,,
5997coreutils, GNU Coreutils}). 5997coreutils, GNU Coreutils}).
5998
5999@item --on-error=@var{strategy}
6000Apply @var{strategy} when an error occurs when reading @var{file}.
6001@var{strategy} may be one of the following:
6002
6003@table @code
6004@item nothing-special
6005Report the error concisely and exit. This is the default strategy.
6006
6007@item backtrace
6008Likewise, but also display a backtrace.
6009
6010@item debug
6011Report the error and enter Guile's debugger. From there, you can run
6012commands such as @code{,bt} to get a backtrace, @code{,locals} to
6013display local variable values, and more generally inspect the program's
6014state. @xref{Debug Commands,,, guile, GNU Guile Reference Manual}, for
6015a list of available debugging commands.
6016@end table
5998@end table 6017@end table
5999 6018
6000Note that all the actions above, except @code{build} and @code{init}, 6019Note that all the actions above, except @code{build} and @code{init},
diff --git a/guix/scripts/system.scm b/guix/scripts/system.scm
index 277f31f6f46..b6d7d0d045c 100644
--- a/guix/scripts/system.scm
+++ b/guix/scripts/system.scm
@@ -383,6 +383,9 @@ Build the operating system declared in FILE according to ACTION.\n"))
383 383
384 (show-build-options-help) 384 (show-build-options-help)
385 (display (_ " 385 (display (_ "
386 --on-error=STRATEGY
387 apply STRATEGY when an error occurs while reading FILE"))
388 (display (_ "
386 --image-size=SIZE for 'vm-image', produce an image of SIZE")) 389 --image-size=SIZE for 'vm-image', produce an image of SIZE"))
387 (display (_ " 390 (display (_ "
388 --no-grub for 'init', do not install GRUB")) 391 --no-grub for 'init', do not install GRUB"))
@@ -422,6 +425,10 @@ Build the operating system declared in FILE according to ACTION.\n"))
422 (option '(#\V "version") #f #f 425 (option '(#\V "version") #f #f
423 (lambda args 426 (lambda args
424 (show-version-and-exit "guix system"))) 427 (show-version-and-exit "guix system")))
428 (option '("on-error") #t #f
429 (lambda (opt name arg result)
430 (alist-cons 'on-error (string->symbol arg)
431 result)))
425 (option '("image-size") #t #f 432 (option '("image-size") #t #f
426 (lambda (opt name arg result) 433 (lambda (opt name arg result)
427 (alist-cons 'image-size (size->number arg) 434 (alist-cons 'image-size (size->number arg)
@@ -514,7 +521,8 @@ Build the operating system declared in FILE according to ACTION.\n"))
514 (action (assoc-ref opts 'action)) 521 (action (assoc-ref opts 'action))
515 (system (assoc-ref opts 'system)) 522 (system (assoc-ref opts 'system))
516 (os (if file 523 (os (if file
517 (read-operating-system file) 524 (load* file %user-module
525 #:on-error (assoc-ref opts 'on-error))
518 (leave (_ "no configuration file specified~%")))) 526 (leave (_ "no configuration file specified~%"))))
519 527
520 (dry? (assoc-ref opts 'dry-run?)) 528 (dry? (assoc-ref opts 'dry-run?))
diff --git a/guix/ui.scm b/guix/ui.scm
index d590eef0407..7490de080c5 100644
--- a/guix/ui.scm
+++ b/guix/ui.scm
@@ -43,6 +43,8 @@
43 #:use-module (ice-9 match) 43 #:use-module (ice-9 match)
44 #:use-module (ice-9 format) 44 #:use-module (ice-9 format)
45 #:use-module (ice-9 regex) 45 #:use-module (ice-9 regex)
46 #:autoload (system repl repl) (start-repl)
47 #:autoload (system repl debug) (make-debug stack->vector)
46 #:replace (symlink) 48 #:replace (symlink)
47 #:export (_ 49 #:export (_
48 N_ 50 N_
@@ -51,7 +53,6 @@
51 leave 53 leave
52 make-user-module 54 make-user-module
53 load* 55 load*
54 report-load-error
55 warn-about-load-error 56 warn-about-load-error
56 show-version-and-exit 57 show-version-and-exit
57 show-bug-report-information 58 show-bug-report-information
@@ -146,7 +147,8 @@ messages."
146 modules) 147 modules)
147 module)) 148 module))
148 149
149(define (load* file user-module) 150(define* (load* file user-module
151 #:key (on-error 'nothing-special))
150 "Load the user provided Scheme source code FILE." 152 "Load the user provided Scheme source code FILE."
151 (define (frame-with-source frame) 153 (define (frame-with-source frame)
152 ;; Walk from FRAME upwards until source location information is found. 154 ;; Walk from FRAME upwards until source location information is found.
@@ -158,6 +160,14 @@ messages."
158 frame 160 frame
159 (loop (frame-previous frame) frame))))) 161 (loop (frame-previous frame) frame)))))
160 162
163 (define (error-string frame args)
164 (call-with-output-string
165 (lambda (port)
166 (apply display-error frame port (cdr args)))))
167
168 (define tag
169 (make-prompt-tag "user-code"))
170
161 (catch #t 171 (catch #t
162 (lambda () 172 (lambda ()
163 ;; XXX: Force a recompilation to avoid ABI issues. 173 ;; XXX: Force a recompilation to avoid ABI issues.
@@ -170,11 +180,14 @@ messages."
170 180
171 ;; Hide the "auto-compiling" messages. 181 ;; Hide the "auto-compiling" messages.
172 (parameterize ((current-warning-port (%make-void-port "w"))) 182 (parameterize ((current-warning-port (%make-void-port "w")))
173 ;; Give 'load' an absolute file name so that it doesn't try to 183 (call-with-prompt tag
174 ;; search for FILE in %LOAD-PATH. Note: use 'load', not 184 (lambda ()
175 ;; 'primitive-load', so that FILE is compiled, which then allows us 185 ;; Give 'load' an absolute file name so that it doesn't try to
176 ;; to provide better error reporting with source line numbers. 186 ;; search for FILE in %LOAD-PATH. Note: use 'load', not
177 (load (canonicalize-path file)))))) 187 ;; 'primitive-load', so that FILE is compiled, which then allows us
188 ;; to provide better error reporting with source line numbers.
189 (load (canonicalize-path file)))
190 (const #f))))))
178 (lambda _ 191 (lambda _
179 ;; XXX: Errors are reported from the pre-unwind handler below, but 192 ;; XXX: Errors are reported from the pre-unwind handler below, but
180 ;; calling 'exit' from there has no effect, so we call it here. 193 ;; calling 'exit' from there has no effect, so we call it here.
@@ -182,31 +195,43 @@ messages."
182 (rec (handle-error . args) 195 (rec (handle-error . args)
183 ;; Capture the stack up to this procedure call, excluded, and pass 196 ;; Capture the stack up to this procedure call, excluded, and pass
184 ;; the faulty stack frame to 'report-load-error'. 197 ;; the faulty stack frame to 'report-load-error'.
185 (let* ((stack (make-stack #t handle-error)) 198 (let* ((stack (make-stack #t handle-error tag))
186 (depth (stack-length stack)) 199 (depth (stack-length stack))
187 (last (and (> depth 0) (stack-ref stack 0))) 200 (last (and (> depth 0) (stack-ref stack 0)))
188 (frame (frame-with-source 201 (frame (frame-with-source
189 (if (> depth 1) 202 (if (> depth 1)
190 (stack-ref stack 1) ;skip the 'throw' frame 203 (stack-ref stack 1) ;skip the 'throw' frame
191 last)))) 204 last))))
192 (report-load-error file args frame))))) 205
206 (report-load-error file args frame)
207
208 (case on-error
209 ((debug)
210 (newline)
211 (display (_ "entering debugger; type ',bt' for a backtrace\n"))
212 (start-repl #:debug (make-debug (stack->vector stack) 0
213 (error-string frame args)
214 #f)))
215 ((backtrace)
216 (newline (current-error-port))
217 (display-backtrace stack (current-error-port)))
218 (else
219 #t))))))
193 220
194(define* (report-load-error file args #:optional frame) 221(define* (report-load-error file args #:optional frame)
195 "Report the failure to load FILE, a user-provided Scheme file, and exit. 222 "Report the failure to load FILE, a user-provided Scheme file.
196ARGS is the list of arguments received by the 'throw' handler." 223ARGS is the list of arguments received by the 'throw' handler."
197 (match args 224 (match args
198 (('system-error . _) 225 (('system-error . _)
199 (let ((err (system-error-errno args))) 226 (let ((err (system-error-errno args)))
200 (leave (_ "failed to load '~a': ~a~%") file (strerror err)))) 227 (report-error (_ "failed to load '~a': ~a~%") file (strerror err))))
201 (('syntax-error proc message properties form . rest) 228 (('syntax-error proc message properties form . rest)
202 (let ((loc (source-properties->location properties))) 229 (let ((loc (source-properties->location properties)))
203 (format (current-error-port) (_ "~a: error: ~a~%") 230 (format (current-error-port) (_ "~a: error: ~a~%")
204 (location->string loc) message) 231 (location->string loc) message)))
205 (exit 1)))
206 ((error args ...) 232 ((error args ...)
207 (report-error (_ "failed to load '~a':~%") file) 233 (report-error (_ "failed to load '~a':~%") file)
208 (apply display-error frame (current-error-port) args) 234 (apply display-error frame (current-error-port) args))))
209 (exit 1))))
210 235
211(define (warn-about-load-error file args) ;FIXME: factorize with ↑ 236(define (warn-about-load-error file args) ;FIXME: factorize with ↑
212 "Report the failure to load FILE, a user-provided Scheme file, without 237 "Report the failure to load FILE, a user-provided Scheme file, without