Subject: [bug#49149] [PATCH 0/7] Add deb format for guix pack.

From: Ludovic Courtès <[email-masked]>
Date: Wed, 30 Jun 2021 12:06:34 +0200

Hi,

Maxim Cournoyer <[email-masked]> skribis:

> Tar translate duplicate files in the archive into hard links.  These can cause
> problems, as not every tool support them; for example dpkg doesn't.
>
> * gnu/system/file-systems.scm (reduce-directories): New procedure.
> (file-prefix?): Lift the restriction on file prefix.  The procedure can be
> useful for comparing relative file names.  Adjust doc.
> (file-name-depth): New procedure, extracted from ...
> (btrfs-store-subvolume-file-name): ... here.
> * guix/scripts/pack.scm (self-contained-tarball/builder): Use
> reduce-directories.
> * tests/file-systems.scm ("reduce-directories"): New test.

[...]

>  (define (file-prefix? file1 file2)
> -  "Return #t if FILE1 denotes the name of a file that is a parent of FILE2,
> -where both FILE1 and FILE2 are absolute file name.  For example:
> +  "Return #t if FILE1 denotes the name of a file that is a parent of FILE2.
> +For example:
>  
>    (file-prefix? \"/gnu\" \"/gnu/store\")
>    => #t
> @@ -240,19 +241,41 @@ where both FILE1 and FILE2 are absolute file name.  For example:
>    (file-prefix? \"/gn\" \"/gnu/store\")
>    => #f
>  "
> -  (and (string-prefix? "/" file1)
> -       (string-prefix? "/" file2)

Doesn’t it have the effect that now:

  (file-prefix? "gnu" "/gnu/store") => #t

?

I’d rather insist on absolute file names and preserve the initial
semantics, to avoid bad surprises.

> +(define (reduce-directories file-names)
> +  "Eliminate entries in FILE-NAMES that are children of other entries in
> +FILE-NAMES.  This is for example useful when passing a list of files to GNU
> +tar, which would otherwise descend into each directory passed and archive the
> +duplicate files as hard links, which can be undesirable."
> +  (let* ((file-names/sorted
> +          ;; Ascending sort by file hierarchy depth, then by file name length.
> +          (stable-sort (delete-duplicates file-names)
> +                       (lambda (f1 f2)
> +                         (let ((depth1 (file-name-depth f1))
> +                               (depth2 (file-name-depth f2)))
> +                           (if (= depth1 depth2)
> +                               (string< f1 f2)
> +                               (< depth1 depth2)))))))
> +    (reverse (fold (lambda (file-name results)
> +                     (if (find (cut file-prefix? <> file-name) results)
> +                         results        ;parent found -- skipping
> +                         (cons file-name results)))
> +                   '()
> +                   file-names/sorted))))

Likewise, I suspect it doesn’t work as intended if there are relative
file names in the list, no?

Perhaps we could add an example to the docstring.  Also, the word
“reduce” doesn’t appear in the docstring, which to me suggests
suboptimal naming.  ;-)

Thanks,
Ludo’.