feat(magrathea): add flag passthru for arguments to nix-build

in some cases, users might want to pass through flags for
nix-build (such as `-j`).

magrathea now accepts these as arguments to `mg build`, as long as
they are separated by `--`.

the arguments passed to `mg build` are parsed into a proper record,
which enables us to show users very clear error messages in case they
forget to use the `--` separator and keeping us future-compatible with
more potential arguments to magrathea itself.

Change-Id: I81f5d9db52779a5cc3b8bbdd975316274fffe5fc
Reviewed-on: https://cl.tvl.fyi/c/depot/+/5507
Tested-by: BuildkiteCI
Reviewed-by: ezemtsov <eugene.zemtsov@gmail.com>
Reviewed-by: asmundo <asmundo@gmail.com>
This commit is contained in:
Vincent Ambo 2022-04-27 16:10:52 +02:00 committed by tazjin
parent 55ba5999ed
commit dd691b1bd3

View file

@ -215,22 +215,65 @@ USAGE
[('error . message) (mg-error message)] [('error . message) (mg-error message)]
[_ value])) [_ value]))
(define (execute-build t) (define-record build-args target passthru unknown)
(let ((expr (nix-expr-for t))) (define (execute-build args)
(fprintf (current-error-port) "[mg] building target ~A~%" t) (let ((expr (nix-expr-for (build-args-target args))))
(process-execute "nix-build" (list "-E" expr "--show-trace")))) (fprintf (current-error-port) "[mg] building target ~A~%" (build-args-target args))
(process-execute "nix-build" (append (list "-E" expr "--show-trace")
(or (build-args-passthru args) '())))))
(define (build args) ;; split the arguments used for builds into target/unknown args/nix
;; args, where the latter occur after '--'
(define (parse-build-args acc args)
(match args (match args
;; simplest case: plain mg build with no target spec -> build ;; no arguments remaining, return accumulator as is
;; the current folder's main target. [() acc]
[() (execute-build (empty-target))]
;; single argument should be a target spec ;; next argument is '--' separator, split off passthru and
[(arg) (execute-build ;; return
(guarantee-success (parse-target arg)))] [("--" . passthru)
(begin
(build-args-passthru-set! acc passthru)
acc)]
[other (print "not yet implemented")])) [(arg . rest)
;; set target if not already known (and if the first
;; argument does not look like an accidental unknown
;; parameter)
(if (and (not (build-args-target acc))
(not (substring=? "-" arg)))
(begin
(build-args-target-set! acc (guarantee-success (parse-target arg)))
(parse-build-args acc rest))
;; otherwise, collect unknown arguments
(begin
(build-args-unknown-set! acc (append (or (build-args-unknown acc) '())
(list arg)))
(parse-build-args acc rest)))]))
;; parse the passed build args, applying sanity checks and defaulting
;; the target if necessary, then execute the build
(define (build args)
(let ((parsed (parse-build-args (make-build-args #f #f #f) args)))
;; fail if there are unknown arguments present
(when (build-args-unknown parsed)
(let ((unknown (string-intersperse (build-args-unknown parsed))))
(mg-error (sprintf "unknown arguments: ~a
if you meant to pass these arguments to nix, please separate them with
'--' like so:
mg build ~a -- ~a"
unknown
(or (build-args-target parsed) "")
unknown))))
;; default the target to the current folder's main target
(unless (build-args-target parsed)
(build-args-target-set! parsed (empty-target)))
(execute-build parsed)))
(define (execute-shell t) (define (execute-shell t)
(let ((expr (nix-expr-for t)) (let ((expr (nix-expr-for t))