Subject: Re: [bug#76376] [PATCH] guix: gexp: canonicalize file paths for import

From: Ludovic Courtès <[email-masked]>
Date: Tue, 25 Feb 2025 16:08:24 +0100

Hello Ryan,

Ludovic Courtès <[email-masked]> skribis:

>>       ((final-path . (? string? file-name))
>> -      (mlet %store-monad ((file (interned-file file-name
>> +      (mlet %store-monad ((file (interned-file (canonicalize-path file-name)
>>                                                 (basename final-path))))
>
> Instead of calling ‘canonicalize-path’, which leads to many syscalls,
> I’d suggest:
>
>    (interned-file file-name (basename final-path)
>                   #:recursive? #f)

It was missing one bit; attached is an version of it that works.

I chose ‘readlink*’ because it’s less expensive that
‘canonicalize-path’: only one extra syscall (readlink) when ‘file-name’
is already a regular file.

For the record, I stumbled upon this bug just today while working on
<https://issues.guix.gnu.org/75810>: the "imported-files does not create
symlinks" in ‘tests/gexp.scm’ would fail when running in an isolated
environment because file “x” would be a symlink to a file outside the
store.

Ludo’.

diff --git a/guix/gexp.scm b/guix/gexp.scm
index ad51bc55b78..ddd2e1a0812 100644
--- a/guix/gexp.scm
+++ b/guix/gexp.scm
@@ -1584,8 +1584,9 @@ (define* (imported-files/derivation files
   (define file-pair
     (match-lambda
      ((final-path . (? string? file-name))
-      (mlet %store-monad ((file (interned-file file-name
-                                               (basename final-path))))
+      (mlet %store-monad ((file (interned-file (readlink* file-name)
+                                               (basename final-path)
+                                               #:recursive? #f)))
         (return (list final-path file))))
      ((final-path . file-like)
       (mlet %store-monad ((file (lower-object file-like system)))