Subject: [bug#29951] [PATCH] WIP guix: Add wrap-script.

From: [email-masked] (Ludovic Courtès)
Date: Fri, 12 Jan 2018 23:52:14 +0100

Hi!

Ricardo Wurmus <[email-masked]> skribis:

> * guix/build/utils.scm (wrap-script): New procedure.

[...]

> +(define wrap-script
> +  (let ((interpreter-regex
> +         (make-regexp
> +          (string-append "^#! ?(/bin/sh|/gnu/store/[^/]+/bin/("
> +                         (string-join '("python[^ ]*"
> +                                        "Rscript"
> +                                        "perl"
> +                                        "ruby"
> +                                        "bash"
> +                                        "sh") "|")
> +                         ") ?.*)")))
> +        (coding-line-regex
> +         (make-regexp
> +          ".*#.*coding[=:][[:space:]]*([-[a-zA-Z_0-9].]+)")))
> +    (lambda* (prog #:rest vars)
> +      "Wrap the script PROG such that VARS are set first.  The format of VARS
> +is the same as in the WRAP-PROGRAM procedure.  This procedure differs from
> +WRAP-PROGRAM in that it does not create a separate shell script.  Instead,
> +PROG is modified directly by prepending a Guile script, which is interpreted
> +as a comment in the script's language.
> +
> +Special encoding comments as supported by Python are recreated on the second
> +line.
> +
> +Note that this procedure can only be used once per file as Guile scripts are
> +not supported."

Nice!

> +      (let-values (((interpreter coding-line)
> +                    (call-with-ascii-input-file prog
> +                      (lambda (p)
> +                        (values (false-if-exception
> +                                 (and=> (regexp-exec interpreter-regex (read-line p))
> +                                        (lambda (m) (match:substring m 1))))
> +                                (false-if-exception
> +                                 (and=> (regexp-exec coding-line-regex (read-line p))
> +                                        (lambda (m) (match:substring m 0)))))))))

‘false-if-exception’ is problematic because it can hide errors.  Could
you narrow that down to the exception type of interest?  Or is there a
risk of random decoding errors and the likes when passed a binary file?

> +        (when interpreter

Should it return #t on success and #f on failure?  Or just thrown an
exception on failure?

> +                                 (which "guile")

Let’s add #:guile defaulting to (which "guile").

I wonder if ‘wrap-program’ could automatically call ‘wrap-script’ when
appropriate so that users don’t have to choose by themselves.  WDYT?

Thanks!

Ludo’.