~ruther/guix-local

9b5364a3afb03414bd6e3ded2fbfdacabe4e8870 — Ludovic Courtès 9 years ago aa04277
daemon: Allow check builds of 'builtin:download' derivations.

Fixes <http://bugs.gnu.org/25089>.
Reported by Leo Famulari <leo@famulari.name>.

* nix/libstore/build.cc (DerivationGoal::runChild): In the 'isBuiltin'
case, check whether DRV's output is in 'redirectedOutputs', and pass an
'output' argument to the built-in builder.
(DerivationGoal::addHashRewrite): Add 'printMsg' call.
* nix/libstore/builtins.hh (derivationBuilder): Add 'output' parameter.
* nix/libstore/builtins.cc (builtinDownload): Likewise.
Add OUTPUT to ARGV.
* guix/scripts/perform-download.scm (perform-download): Add 'output'
parameter.
(guix-perform-download): Adjust 'match' clauses accordingly.
* tests/derivations.scm ("'download' built-in builder, check mode"): New
test.
M guix/scripts/perform-download.scm => guix/scripts/perform-download.scm +13 -8
@@ 1,5 1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2016 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2016, 2017 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;


@@ 19,7 19,7 @@
(define-module (guix scripts perform-download)
  #:use-module (guix ui)
  #:use-module (guix derivations)
  #:use-module ((guix store) #:select (derivation-path?))
  #:use-module ((guix store) #:select (derivation-path? store-path?))
  #:use-module (guix build download)
  #:use-module (ice-9 match)
  #:export (guix-perform-download))


@@ 41,10 41,13 @@
    (module-use! module (resolve-interface '(guix base32)))
    module))

(define (perform-download drv)
  "Perform the download described by DRV, a fixed-output derivation."
(define (perform-download drv output)
  "Perform the download described by DRV, a fixed-output derivation, to
OUTPUT.

Note: We don't read the value of 'out' in DRV since the actual output is
different from that when we're doing a 'bmCheck' or 'bmRepair' build."
  (derivation-let drv ((url "url")
                       (output "out")
                       (executable "executable")
                       (mirrors "mirrors")
                       (content-addressed-mirrors "content-addressed-mirrors"))


@@ 93,18 96,20 @@ of GnuTLS over HTTPS, before we have built GnuTLS.  See
<http://bugs.gnu.org/22774>."
  (with-error-handling
    (match args
      (((? derivation-path? drv))
      (((? derivation-path? drv) (? store-path? output))
       ;; This program must be invoked by guix-daemon under an unprivileged
       ;; UID to prevent things downloading from 'file:///etc/shadow' or
       ;; arbitrary code execution via the content-addressed mirror
       ;; procedures.  (That means we exclude users who did not pass
       ;; '--build-users-group'.)
       (assert-low-privileges)
       (perform-download (call-with-input-file drv read-derivation)))
       (perform-download (call-with-input-file drv read-derivation)
                         output))
      (("--version")
       (show-version-and-exit))
      (x
       (leave (_ "fixed-output derivation name expected~%"))))))
       (leave
        (_ "fixed-output derivation and output file name expected~%"))))))

;; Local Variables:
;; eval: (put 'derivation-let 'scheme-indent-function 2)

M nix/libstore/build.cc => nix/libstore/build.cc +13 -2
@@ 2271,8 2271,17 @@ void DerivationGoal::runChild()
                logType = ltFlat;

		auto buildDrv = lookupBuiltinBuilder(drv.builder);
                if (buildDrv != NULL)
                    buildDrv(drv, drvPath);
                if (buildDrv != NULL) {
		    /* Check what the output file name is.  When doing a
		       'bmCheck' build, the output file name is different from
		       that specified in DRV due to hash rewriting.  */
		    Path output = drv.outputs["out"].path;
		    auto redirected = redirectedOutputs.find(output);
		    if (redirected != redirectedOutputs.end())
			output = redirected->second;

                    buildDrv(drv, drvPath, output);
		}
                else
                    throw Error(format("unsupported builtin function '%1%'") % string(drv.builder, 8));
                _exit(0);


@@ 2742,6 2751,8 @@ Path DerivationGoal::addHashRewrite(const Path & path)
    rewritesToTmp[h1] = h2;
    rewritesFromTmp[h2] = h1;
    redirectedOutputs[path] = p;
    printMsg(lvlChatty, format("output '%1%' redirected to '%2%'")
	     % path % p);
    return p;
}


M nix/libstore/builtins.cc => nix/libstore/builtins.cc +7 -3
@@ 1,5 1,5 @@
/* GNU Guix --- Functional package management for GNU
   Copyright (C) 2016 Ludovic Courtès <ludo@gnu.org>
   Copyright (C) 2016, 2017 Ludovic Courtès <ludo@gnu.org>

   This file is part of GNU Guix.



@@ 25,7 25,8 @@
namespace nix {

static void builtinDownload(const Derivation &drv,
			    const std::string &drvPath)
			    const std::string &drvPath,
			    const std::string &output)
{
    /* Invoke 'guix perform-download'.  */
    Strings args;


@@ 35,7 36,10 @@ static void builtinDownload(const Derivation &drv,
    /* Close all other file descriptors. */
    closeMostFDs(set<int>());

    const char *const argv[] = { "download", drvPath.c_str(), NULL };
    const char *const argv[] =
      {
	"download", drvPath.c_str(), output.c_str(), NULL
      };

    /* XXX: Hack our way to use the 'download' script from 'LIBEXECDIR/guix'
       or just 'LIBEXECDIR', depending on whether we're running uninstalled or

M nix/libstore/builtins.hh => nix/libstore/builtins.hh +3 -2
@@ 1,5 1,5 @@
/* GNU Guix --- Functional package management for GNU
   Copyright (C) 2016 Ludovic Courtès <ludo@gnu.org>
   Copyright (C) 2016, 2017 Ludovic Courtès <ludo@gnu.org>

   This file is part of GNU Guix.



@@ 33,7 33,8 @@ namespace nix {

    /* Build DRV, which lives at DRVPATH.  */
    typedef void (*derivationBuilder) (const Derivation &drv,
				       const std::string &drvPath);
				       const std::string &drvPath,
				       const std::string &output);

    /* Return the built-in builder called BUILDER, or NULL if none was
       found.  */

M tests/derivations.scm => tests/derivations.scm +26 -1
@@ 1,5 1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2012, 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;


@@ 279,6 279,27 @@
      (build-derivations %store (list drv))
      #f)))

(unless (force %http-server-socket)
  (test-skip 1))
(test-assert "'download' built-in builder, check mode"
  ;; Make sure rebuilding the 'builtin:download' derivation in check mode
  ;; works.  See <http://bugs.gnu.org/25089>.
  (let* ((text (random-text))
         (drv (derivation %store "world"
                          "builtin:download" '()
                          #:env-vars `(("url"
                                        . ,(object->string (%local-url))))
                          #:hash-algo 'sha256
                          #:hash (sha256 (string->utf8 text)))))
    (and (with-http-server 200 text
           (build-derivations %store (list drv)))
         (with-http-server 200 text
           (build-derivations %store (list drv)
                              (build-mode check)))
         (string=? (call-with-input-file (derivation->output-path drv)
                     get-string-all)
                   text))))

(test-equal "derivation-name"
  "foo-0.0"
  (let ((drv (derivation %store "foo-0.0" %bash '())))


@@ 1109,3 1130,7 @@
         (call-with-input-file out get-string-all))))

(test-end)

;; Local Variables:
;; eval: (put 'with-http-server 'scheme-indent-function 2)
;; End: