summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxim Cournoyer <maxim.cournoyer@gmail.com>2021-07-06 12:27:36 -0400
committerMaxim Cournoyer <maxim.cournoyer@gmail.com>2021-07-18 02:10:49 -0400
commit11f0698243da27be93b16cec574fbf262279779a (patch)
tree2f963278251112d113a448ee8c2ab9d92e324ba6
parentb019496fc3643f0bd837c62078086e3ff51b6001 (diff)
pack: Streamline how files are included in tarballs.
Thanks to Guillem Jover <guillem@debian.org> on the OFTC's #debian-dpkg channel for helping with troubleshooting. Letting GNU Tar recursively walk the complete files hierarchy side-steps the risks associated with providing a list of file names: 1. Duplicated files in the archive (recorded as hard links by GNU Tar) 2. Missing parent directories. The above would cause dpkg to malfunction, for example by aborting early and skipping triggers when there were missing parent directories. * guix/scripts/pack.scm (self-contained-tarball/builder): Do not call POPULATE-SINGLE-PROFILE-DIRECTORY, which creates extraneous files such as /root. Instead, call POPULATE-STORE and INSTALL-DATABASE-AND-GC-ROOTS individually to more precisely generate the file system. Replace the list of files by the current directory, "." and streamline the way options are passed. * gnu/system/file-systems.scm (reduce-directories): Remove procedure. * tests/file-systems.scm ("reduce-directories"): Remove test.
-rw-r--r--gnu/system/file-systems.scm22
-rw-r--r--guix/scripts/pack.scm49
-rw-r--r--tests/file-systems.scm7
3 files changed, 17 insertions, 61 deletions
diff --git a/gnu/system/file-systems.scm b/gnu/system/file-systems.scm
index 4a3c1fe008f..b9eda80958e 100644
--- a/gnu/system/file-systems.scm
+++ b/gnu/system/file-systems.scm
@@ -55,7 +55,6 @@
55 file-system-dependencies 55 file-system-dependencies
56 file-system-location 56 file-system-location
57 57
58 reduce-directories
59 file-system-type-predicate 58 file-system-type-predicate
60 btrfs-subvolume? 59 btrfs-subvolume?
61 btrfs-store-subvolume-file-name 60 btrfs-store-subvolume-file-name
@@ -266,27 +265,6 @@ For example:
266(define (file-name-depth file-name) 265(define (file-name-depth file-name)
267 (length (string-tokenize file-name %not-slash))) 266 (length (string-tokenize file-name %not-slash)))
268 267
269(define (reduce-directories file-names)
270 "Eliminate entries in FILE-NAMES that are children of other entries in
271FILE-NAMES. This is for example useful when passing a list of files to GNU
272tar, which would otherwise descend into each directory passed and archive the
273duplicate files as hard links, which can be undesirable."
274 (let* ((file-names/sorted
275 ;; Ascending sort by file hierarchy depth, then by file name length.
276 (stable-sort (delete-duplicates file-names)
277 (lambda (f1 f2)
278 (let ((depth1 (file-name-depth f1))
279 (depth2 (file-name-depth f2)))
280 (if (= depth1 depth2)
281 (string< f1 f2)
282 (< depth1 depth2)))))))
283 (reverse (fold (lambda (file-name results)
284 (if (find (cut file-prefix? <> file-name) results)
285 results ;parent found -- skipping
286 (cons file-name results)))
287 '()
288 file-names/sorted))))
289
290(define* (file-system-device->string device #:key uuid-type) 268(define* (file-system-device->string device #:key uuid-type)
291 "Return the string representations of the DEVICE field of a <file-system> 269 "Return the string representations of the DEVICE field of a <file-system>
292record. When the device is a UUID, its representation is chosen depending on 270record. When the device is a UUID, its representation is chosen depending on
diff --git a/guix/scripts/pack.scm b/guix/scripts/pack.scm
index 78201d6f5f6..9e1f270dfbc 100644
--- a/guix/scripts/pack.scm
+++ b/guix/scripts/pack.scm
@@ -231,17 +231,17 @@ its source property."
231 231
232 (with-imported-modules (source-module-closure 232 (with-imported-modules (source-module-closure
233 `((guix build pack) 233 `((guix build pack)
234 (guix build store-copy)
234 (guix build utils) 235 (guix build utils)
235 (guix build union) 236 (guix build union)
236 (gnu build install) 237 (gnu build install))
237 (gnu system file-systems))
238 #:select? import-module?) 238 #:select? import-module?)
239 #~(begin 239 #~(begin
240 (use-modules (guix build pack) 240 (use-modules (guix build pack)
241 (guix build store-copy)
241 (guix build utils) 242 (guix build utils)
242 ((guix build union) #:select (relative-file-name)) 243 ((guix build union) #:select (relative-file-name))
243 (gnu build install) 244 (gnu build install)
244 ((gnu system file-systems) #:select (reduce-directories))
245 (srfi srfi-1) 245 (srfi srfi-1)
246 (srfi srfi-26) 246 (srfi srfi-26)
247 (ice-9 match)) 247 (ice-9 match))
@@ -279,11 +279,11 @@ its source property."
279 ;; Furthermore GNU tar < 1.30 sometimes fails to extract tarballs 279 ;; Furthermore GNU tar < 1.30 sometimes fails to extract tarballs
280 ;; with hard links: 280 ;; with hard links:
281 ;; <http://lists.gnu.org/archive/html/bug-tar/2017-11/msg00009.html>. 281 ;; <http://lists.gnu.org/archive/html/bug-tar/2017-11/msg00009.html>.
282 (populate-single-profile-directory %root 282 (populate-store (list "profile") %root #:deduplicate? #f)
283 #:profile #$profile 283
284 #:profile-name #$profile-name 284 (when #+localstatedir?
285 #:closure "profile" 285 (install-database-and-gc-roots %root #+database #$profile
286 #:database #+database) 286 #:profile-name #$profile-name))
287 287
288 ;; Create SYMLINKS. 288 ;; Create SYMLINKS.
289 (for-each (cut evaluate-populate-directive <> %root) 289 (for-each (cut evaluate-populate-directive <> %root)
@@ -291,31 +291,14 @@ its source property."
291 291
292 ;; Create the tarball. 292 ;; Create the tarball.
293 (with-directory-excursion %root 293 (with-directory-excursion %root
294 (apply invoke tar 294 ;; GNU Tar recurses directories by default. Simply add the whole
295 `(,@(tar-base-options 295 ;; current directory, which contains all the generated files so far.
296 #:tar tar 296 ;; This avoids creating duplicate files in the archives that would
297 #:compressor '#+(and=> compressor compressor-command)) 297 ;; be stored as hard links by GNU Tar.
298 "-cvf" ,#$output 298 (apply invoke tar "-cvf" #$output "."
299 ;; Avoid adding / and /var to the tarball, so 299 (tar-base-options
300 ;; that the ownership and permissions of those 300 #:tar tar
301 ;; directories will not be overwritten when 301 #:compressor '#+(and=> compressor compressor-command)))))))
302 ;; extracting the archive. Do not include /root
303 ;; because the root account might have a
304 ;; different home directory.
305 ,#$@(if localstatedir?
306 '("./var/guix")
307 '())
308
309 ,(string-append "." (%store-directory))
310
311 ,@(reduce-directories
312 (filter-map (match-lambda
313 (('directory directory)
314 (string-append "." directory))
315 ((source '-> _)
316 (string-append "." source))
317 (_ #f))
318 directives))))))))
319 302
320(define* (self-contained-tarball name profile 303(define* (self-contained-tarball name profile
321 #:key target 304 #:key target
diff --git a/tests/file-systems.scm b/tests/file-systems.scm
index 80acb6d5b91..7f7c373884f 100644
--- a/tests/file-systems.scm
+++ b/tests/file-systems.scm
@@ -1,6 +1,6 @@
1;;; GNU Guix --- Functional package management for GNU 1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2015, 2017 Ludovic Courtès <ludo@gnu.org> 2;;; Copyright © 2015, 2017 Ludovic Courtès <ludo@gnu.org>
3;;; Copyright © 2020, 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com> 3;;; Copyright © 2020 Maxim Cournoyer <maxim.cournoyer@gmail.com>
4;;; 4;;;
5;;; This file is part of GNU Guix. 5;;; This file is part of GNU Guix.
6;;; 6;;;
@@ -50,11 +50,6 @@
50 (device "/foo") 50 (device "/foo")
51 (flags '(bind-mount read-only))))))))) 51 (flags '(bind-mount read-only)))))))))
52 52
53(test-equal "reduce-directories"
54 '("./opt/gnu/" "./opt/gnuism" "a/b/c")
55 (reduce-directories '("./opt/gnu/etc" "./opt/gnu/" "./opt/gnu/bin"
56 "./opt/gnu/lib/debug" "./opt/gnuism" "a/b/c" "a/b/c")))
57
58(test-assert "does not pull (guix config)" 53(test-assert "does not pull (guix config)"
59 ;; This module is meant both for the host side and "build side", so make 54 ;; This module is meant both for the host side and "build side", so make
60 ;; sure it doesn't pull in (guix config), which depends on the user's 55 ;; sure it doesn't pull in (guix config), which depends on the user's