diff mbox series

[bug#54997,01/12] gexp: Add 'references-file'.

Message ID 20220417210453.27884-1-ludo@gnu.org
State Accepted
Headers show
Series Add "least authority" program wrapper | expand

Checks

Context Check Description
cbaines/comparison success View comparision
cbaines/git branch success View Git branch
cbaines/applying patch success View Laminar job
cbaines/issue success View issue

Commit Message

Ludovic Courtès April 17, 2022, 9:04 p.m. UTC
* gnu/services/base.scm (references-file): Remove.
* guix/gexp.scm (references-file): New procedure.
* tests/gexp.scm ("references-file"): New test.
---
 gnu/services/base.scm | 22 ----------------------
 guix/gexp.scm         | 43 +++++++++++++++++++++++++++++++++++++++++++
 tests/gexp.scm        | 18 ++++++++++++++++++
 3 files changed, 61 insertions(+), 22 deletions(-)

Comments

Thiago Jung Bauermann April 22, 2022, 5:01 a.m. UTC | #1
Hello Ludo,

This is an awesome series! It will be yet another strength of Guix to
have many services as possible (and even desktop apps, hopefully)
isolated.

I have one question:

Ludovic Courtès <ludo@gnu.org> writes:

> +                             (define (read-graph port)
> +                               ;; Return the list of references read from
> +                               ;; PORT.  This is a stripped-down version of
> +                               ;; 'read-reference-graph'.
> +                               (let loop ((items '()))
> +                                 (match (read-line port)
> +                                   ((? eof-object?)
> +                                    items)
> +                                   ((? string? item)
> +                                    (let ((deriver (read-line port))
> +                                          (count
> +                                           (string->number (read-line port))))
> +                                      (drop-lines port count)
> +                                      (loop (cons item items)))))))

I'm sure I'm being dense, but I don't see how ‘item’ can change between
iterations of this loop. Which in my mind means that ‘read-graph’ can
only return a list where the original ‘item’ argument from
‘references-file’ is repeated many times over. I ran the tests/gexp.scm
test and all tests pass, so this code must be working...
Ludovic Courtès April 26, 2022, 8:17 p.m. UTC | #2
Hi Thiago,

Thiago Jung Bauermann <bauermann@kolabnow.com> skribis:

> This is an awesome series! It will be yet another strength of Guix to
> have many services as possible (and even desktop apps, hopefully)
> isolated.

Thanks.  :-)

> Ludovic Courtès <ludo@gnu.org> writes:
>
>> +                             (define (read-graph port)
>> +                               ;; Return the list of references read from
>> +                               ;; PORT.  This is a stripped-down version of
>> +                               ;; 'read-reference-graph'.
>> +                               (let loop ((items '()))
>> +                                 (match (read-line port)
>> +                                   ((? eof-object?)
>> +                                    items)
>> +                                   ((? string? item)
>> +                                    (let ((deriver (read-line port))
>> +                                          (count
>> +                                           (string->number (read-line port))))
>> +                                      (drop-lines port count)
>> +                                      (loop (cons item items)))))))
>
> I'm sure I'm being dense, but I don't see how ‘item’ can change between
> iterations of this loop.

Each iteration reads a new line from PORT, an input port on a text file.

The file is created by guix-daemon and has a format like this:

     FILE
     DERIVER
     NUMBER-OF-REFERENCES
     REF1
     ...
     REFN

where each FILE is a store item (see store-copy.scm for details).

Here we only care about FILE and REF*.

> Which in my mind means that ‘read-graph’ can only return a list where
> the original ‘item’ argument from ‘references-file’ is repeated many
> times over. I ran the tests/gexp.scm test and all tests pass, so this
> code must be working...

I think it does!  :-)  It wouldn’t hurt to add a call to
‘delete-duplicates’ though.

Ludo’.
diff mbox series

Patch

diff --git a/gnu/services/base.scm b/gnu/services/base.scm
index 5d7c69a9cd..182badd97f 100644
--- a/gnu/services/base.scm
+++ b/gnu/services/base.scm
@@ -219,8 +219,6 @@  (define-module (gnu services base)
             pam-limits-service-type
             pam-limits-service
 
-            references-file
-
             %base-services))
 
 ;;; Commentary:
@@ -1768,26 +1766,6 @@  (define (guix-activation config)
               (substitute-key-authorization authorized-keys guix)
               #~#f))))
 
-(define* (references-file item #:optional (name "references"))
-  "Return a file that contains the list of references of ITEM."
-  (if (struct? item)                              ;lowerable object
-      (computed-file name
-                     (with-extensions (list guile-gcrypt) ;for store-copy
-                       (with-imported-modules (source-module-closure
-                                               '((guix build store-copy)))
-                         #~(begin
-                             (use-modules (guix build store-copy))
-
-                             (call-with-output-file #$output
-                               (lambda (port)
-                                 (write (map store-info-item
-                                             (call-with-input-file "graph"
-                                               read-reference-graph))
-                                        port))))))
-                     #:options `(#:local-build? #f
-                                 #:references-graphs (("graph" ,item))))
-      (plain-file name "()")))
-
 (define guix-service-type
   (service-type
    (name 'guix)
diff --git a/guix/gexp.scm b/guix/gexp.scm
index 9fdb7a30be..9ef7622062 100644
--- a/guix/gexp.scm
+++ b/guix/gexp.scm
@@ -118,6 +118,7 @@  (define-module (guix gexp)
             mixed-text-file
             file-union
             directory-union
+            references-file
 
             imported-files
             imported-modules
@@ -2173,6 +2174,48 @@  (define log-port
                                            #:resolve-collision
                                            (ungexp resolve-collision)))))))))
 
+(define* (references-file item #:optional (name "references")
+                          #:key guile)
+  "Return a file that contains the list of direct and indirect references (the
+closure) of ITEM."
+  (if (struct? item)                              ;lowerable object
+      (computed-file name
+                     (gexp (begin
+                             (use-modules (ice-9 rdelim)
+                                          (ice-9 match))
+
+                             (define (drop-lines port n)
+                               ;; Drop N lines read from PORT.
+                               (let loop ((n n))
+                                 (unless (zero? n)
+                                   (read-line port)
+                                   (loop (- n 1)))))
+
+                             (define (read-graph port)
+                               ;; Return the list of references read from
+                               ;; PORT.  This is a stripped-down version of
+                               ;; 'read-reference-graph'.
+                               (let loop ((items '()))
+                                 (match (read-line port)
+                                   ((? eof-object?)
+                                    items)
+                                   ((? string? item)
+                                    (let ((deriver (read-line port))
+                                          (count
+                                           (string->number (read-line port))))
+                                      (drop-lines port count)
+                                      (loop (cons item items)))))))
+
+                             (call-with-output-file (ungexp output)
+                               (lambda (port)
+                                 (write (call-with-input-file "graph"
+                                          read-graph)
+                                        port)))))
+                     #:guile guile
+                     #:options `(#:local-build? #t
+                                 #:references-graphs (("graph" ,item))))
+      (plain-file name "()")))
+
 
 ;;;
 ;;; Syntactic sugar.
diff --git a/tests/gexp.scm b/tests/gexp.scm
index c80ca13fab..35bd99e6d4 100644
--- a/tests/gexp.scm
+++ b/tests/gexp.scm
@@ -1606,6 +1606,24 @@  (define (contents=? file str)
                    (not (member (derivation-file-name native) refs))
                    (member (derivation-file-name cross) refs))))))
 
+(test-assertm "references-file"
+  (let* ((exp      #~(symlink #$%bootstrap-guile #$output))
+         (computed (computed-file "computed" exp
+                                  #:guile %bootstrap-guile))
+         (refs     (references-file computed "refs"
+                                    #:guile %bootstrap-guile)))
+    (mlet* %store-monad ((drv0 (lower-object %bootstrap-guile))
+                         (drv1 (lower-object computed))
+                         (drv2 (lower-object refs)))
+      (mbegin %store-monad
+        (built-derivations (list drv2))
+        (mlet %store-monad ((refs ((store-lift requisites)
+                                   (list (derivation->output-path drv1)))))
+          (return (lset= string=?
+                         (call-with-input-file (derivation->output-path drv2)
+                           read)
+                         refs)))))))
+
 (test-assert "lower-object & gexp-input-error?"
   (guard (c ((gexp-input-error? c)
              (gexp-error-invalid-input c)))