diff options
Diffstat (limited to 'guix/derivations.scm')
-rw-r--r-- | guix/derivations.scm | 48 |
1 files changed, 38 insertions, 10 deletions
diff --git a/guix/derivations.scm b/guix/derivations.scm index 4b0048b54b..7737e39b2d 100644 --- a/guix/derivations.scm +++ b/guix/derivations.scm @@ -60,6 +60,7 @@ derivation-input-path derivation-input-sub-derivations derivation-input-output-paths + valid-derivation-input? &derivation-error derivation-error? @@ -187,12 +188,25 @@ download with a fixed hash (aka. `fetchurl')." (map (cut derivation-path->output-path path <>) sub-drvs)))) -(define (derivation-prerequisites drv) - "Return the list of derivation-inputs required to build DRV, recursively." +(define (valid-derivation-input? store input) + "Return true if INPUT is valid--i.e., if all the outputs it requests are in +the store." + (every (cut valid-path? store <>) + (derivation-input-output-paths input))) + +(define* (derivation-prerequisites drv #:optional (cut? (const #f))) + "Return the list of derivation-inputs required to build DRV, recursively. + +CUT? is a predicate that is passed a derivation-input and returns true to +eliminate the given input and its dependencies from the search. An example of +search a predicate is 'valid-derivation-input?'; when it is used as CUT?, the +result is the set of prerequisites of DRV not already in valid." (let loop ((drv drv) (result '()) (input-set (set))) - (let ((inputs (remove (cut set-contains? input-set <>) + (let ((inputs (remove (lambda (input) + (or (set-contains? input-set input) + (cut? input))) (derivation-inputs drv)))) (fold2 loop (append inputs result) @@ -225,22 +239,36 @@ download with a fixed hash (aka. `fetchurl')." (define* (substitution-oracle store drv) "Return a one-argument procedure that, when passed a store file name, returns #t if it's substitutable and #f otherwise. The returned procedure -knows about all substitutes for all the derivations listed in DRV and their -prerequisites. +knows about all substitutes for all the derivations listed in DRV; it also +knows about their prerequisites, unless they are themselves substitutable. Creating a single oracle (thus making a single 'substitutable-paths' call) and reusing it is much more efficient than calling 'has-substitutes?' or similar repeatedly, because it avoids the costs associated with launching the substituter many times." + (define valid? + (cut valid-path? store <>)) + + (define valid-input? + (cut valid-derivation-input? store <>)) + + (define (dependencies drv) + ;; Skip prerequisite sub-trees of DRV whose root is valid. This allows us + ;; to ask the substituter for just as much as needed, instead of asking it + ;; for the whole world, which can be significantly faster when substitute + ;; info is not already in cache. + (append-map derivation-input-output-paths + (derivation-prerequisites drv valid-input?))) + (let* ((paths (delete-duplicates (fold (lambda (drv result) (let ((self (match (derivation->output-paths drv) (((names . paths) ...) - paths))) - (deps (append-map derivation-input-output-paths - (derivation-prerequisites - drv)))) - (append self deps result))) + paths)))) + (if (every valid? self) + result + (append (append self (dependencies drv)) + result)))) '() drv))) (subst (list->set (substitutable-paths store paths)))) |