~ruther/guix-local

15a01c72209b2d43239fe7516a22e531b7fcb85f — Ludovic Courtès 10 years ago 9193702
gexp: Add 'program-file'.

* guix/gexp.scm (<program-file>): New record type.
  (program-file, program-file-compiler): New procedures.
* tests/gexp.scm ("program-file"): New test.
* doc/guix.texi (G-Expressions): Document it.
3 files changed, 63 insertions(+), 4 deletions(-)

M doc/guix.texi
M guix/gexp.scm
M tests/gexp.scm
M doc/guix.texi => doc/guix.texi +13 -4
@@ 3345,10 3345,10 @@ The other arguments are as for @code{derivation} (@pxref{Derivations}).
@end deffn

@cindex file-like objects
The @code{local-file}, @code{plain-file}, and @code{computed-file}
procedures below return @dfn{file-like objects}.  That is, when unquoted
in a G-expression, these objects lead to a file in the store.  Consider
this G-expression:
The @code{local-file}, @code{plain-file}, @code{computed-file}, and
@code{program-file} procedures below return @dfn{file-like objects}.
That is, when unquoted in a G-expression, these objects lead to a file
in the store.  Consider this G-expression:

@example
#~(system* (string-append #$glibc "/sbin/nscd") "-f"


@@ 3421,6 3421,15 @@ executable file @file{/gnu/store/@dots{}-list-files} along these lines:
@end example
@end deffn

@deffn {Scheme Procedure} program-file @var{name} @var{exp} @
          [#:modules '()] [#:guile #f]
Return an object representing the executable store item @var{name} that
runs @var{gexp}.  @var{guile} is the Guile package used to execute that
script, and @var{modules} is the list of modules visible to that script.

This is the declarative counterpart of @code{gexp->script}.
@end deffn

@deffn {Monadic Procedure} gexp->file @var{name} @var{exp}
Return a derivation that builds a file @var{name} containing @var{exp}.


M guix/gexp.scm => guix/gexp.scm +33 -0
@@ 50,6 50,13 @@
            computed-file-modules
            computed-file-options

            program-file
            program-file?
            program-file-name
            program-file-gexp
            program-file-modules
            program-file-guile

            gexp->derivation
            gexp->file
            gexp->script


@@ 247,6 254,32 @@ This is the declarative counterpart of 'gexp->derivation'."
    (($ <computed-file> name gexp modules options)
     (apply gexp->derivation name gexp #:modules modules options))))

(define-record-type <program-file>
  (%program-file name gexp modules guile)
  program-file?
  (name       program-file-name)                  ;string
  (gexp       program-file-gexp)                  ;gexp
  (modules    program-file-modules)               ;list of module names
  (guile      program-file-guile))                ;package

(define* (program-file name gexp
                       #:key (modules '()) (guile #f))
  "Return an object representing the executable store item NAME that runs
GEXP.  GUILE is the Guile package used to execute that script, and MODULES is
the list of modules visible to that script.

This is the declarative counterpart of 'gexp->script'."
  (%program-file name gexp modules guile))

(define-gexp-compiler (program-file-compiler (file program-file?)
                                             system target)
  ;; Compile FILE by returning a derivation that builds the script.
  (match file
    (($ <program-file> name gexp modules guile)
     (gexp->script name gexp
                   #:modules modules
                   #:guile (or guile (default-guile))))))


;;;
;;; Inputs & outputs.

M tests/gexp.scm => tests/gexp.scm +17 -0
@@ 619,6 619,23 @@
      (return (and (zero? (close-pipe pipe))
                   (= (expt n 2) (string->number str)))))))

(test-assertm "program-file"
  (let* ((n      (random (expt 2 50)))
         (exp    (gexp (begin
                         (use-modules (guix build utils))
                         (display (ungexp n)))))
         (file   (program-file "program" exp
                               #:modules '((guix build utils))
                               #:guile %bootstrap-guile)))
    (mlet* %store-monad ((drv (lower-object file))
                         (out -> (derivation->output-path drv)))
      (mbegin %store-monad
        (built-derivations (list drv))
        (let* ((pipe  (open-input-pipe out))
               (str   (get-string-all pipe)))
          (return (and (zero? (close-pipe pipe))
                       (= n (string->number str)))))))))

(test-assert "text-file*"
  (let ((references (store-lift references)))
    (run-with-store %store