pack: Allow embedding custom control files in deb packs.
* guix/scripts/pack.scm (self-contained-tarball/builder) [extra-options]: New argument. (self-contained-tarball, squashfs-image, docker-image) (debian-archive): Likewise. Remove two TODO comments. Document EXTRA-OPTIONS. Use the custom control files when provided. (%deb-format-options): New variable. (show-deb-format-options, show-deb-format-options/detailed): New procedures. (%options): Register new options. (show-help): Augment with new usage. (guix-pack): Validate and propagate new argument values. * doc/guix.texi (Invoking guix pack)[deb]: Document how to list advanced options. Add an example. * tests/pack.scm (deb archive...): Provide extra-options to the debian-archive procedure, and validate that the provided files are embedded in the pack.master
parent
15b4372b60
commit
aeded14b83
|
@ -6047,6 +6047,14 @@ such file or directory'' message.
|
|||
This produces a Debian archive (a package with the @samp{.deb} file
|
||||
extension) containing all the specified binaries and symbolic links,
|
||||
that can be installed on top of any dpkg-based GNU(/Linux) distribution.
|
||||
Advanced options can be revealed via the @option{--help-deb-format}
|
||||
option. They allow embedding control files for more fine-grained
|
||||
control, such as activating specific triggers or providing a maintainer
|
||||
configure script to run arbitrary setup code upon installation.
|
||||
|
||||
@example
|
||||
guix pack -f deb -C xz -S /usr/bin/hello=bin/hello hello
|
||||
@end example
|
||||
|
||||
@quotation Note
|
||||
Because archives produced with @command{guix pack} contain a collection
|
||||
|
|
|
@ -205,7 +205,8 @@ its source property."
|
|||
(compressor (first %compressors))
|
||||
localstatedir?
|
||||
(symlinks '())
|
||||
(archiver tar))
|
||||
(archiver tar)
|
||||
(extra-options '()))
|
||||
"Return the G-Expression of the builder used for self-contained-tarball."
|
||||
(define database
|
||||
(and localstatedir?
|
||||
|
@ -324,7 +325,8 @@ its source property."
|
|||
(compressor (first %compressors))
|
||||
localstatedir?
|
||||
(symlinks '())
|
||||
(archiver tar))
|
||||
(archiver tar)
|
||||
(extra-options '()))
|
||||
"Return a self-contained tarball containing a store initialized with the
|
||||
closure of PROFILE, a derivation. The tarball contains /gnu/store; if
|
||||
LOCALSTATEDIR? is true, it also contains /var/guix, including /var/guix/db
|
||||
|
@ -389,7 +391,8 @@ to the search paths of PROFILE."
|
|||
entry-point
|
||||
localstatedir?
|
||||
(symlinks '())
|
||||
(archiver squashfs-tools))
|
||||
(archiver squashfs-tools)
|
||||
(extra-options '()))
|
||||
"Return a squashfs image containing a store initialized with the closure of
|
||||
PROFILE, a derivation. The image contains a subset of /gnu/store, empty mount
|
||||
points for virtual file systems (like procfs), and optional symlinks.
|
||||
|
@ -567,7 +570,8 @@ added to the pack."
|
|||
entry-point
|
||||
localstatedir?
|
||||
(symlinks '())
|
||||
(archiver tar))
|
||||
(archiver tar)
|
||||
(extra-options '()))
|
||||
"Return a derivation to construct a Docker image of PROFILE. The
|
||||
image is a tarball conforming to the Docker Image Specification, compressed
|
||||
with COMPRESSOR. It can be passed to 'docker load'. If TARGET is true, it
|
||||
|
@ -654,8 +658,6 @@ the image."
|
|||
;;; TODO: When relocatable option is selected, install to a unique prefix.
|
||||
;;; This would enable installation of multiple deb packs with conflicting
|
||||
;;; files at the same time.
|
||||
;;; TODO: Allow passing a custom control file from the CLI.
|
||||
;;; TODO: Allow providing a postinst script.
|
||||
(define* (debian-archive name profile
|
||||
#:key target
|
||||
(profile-name "guix-profile")
|
||||
|
@ -664,7 +666,8 @@ the image."
|
|||
(compressor (first %compressors))
|
||||
localstatedir?
|
||||
(symlinks '())
|
||||
(archiver tar))
|
||||
(archiver tar)
|
||||
(extra-options '()))
|
||||
"Return a Debian archive (.deb) containing a store initialized with the
|
||||
closure of PROFILE, a derivation. The archive contains /gnu/store; if
|
||||
LOCALSTATEDIR? is true, it also contains /var/guix, including /var/guix/db
|
||||
|
@ -672,7 +675,8 @@ with a properly initialized store database. The supported compressors are
|
|||
\"none\", \"gz\" or \"xz\".
|
||||
|
||||
SYMLINKS must be a list of (SOURCE -> TARGET) tuples denoting symlinks to be
|
||||
added to the pack."
|
||||
added to the pack. EXTRA-OPTIONS may contain the CONFIG-FILE, POSTINST-FILE
|
||||
or TRIGGERS-FILE keyword arguments."
|
||||
;; For simplicity, limit the supported compressors to the superset of
|
||||
;; compressors able to compress both the control file (gz or xz) and the
|
||||
;; data tarball (gz, bz2 or xz).
|
||||
|
@ -714,21 +718,23 @@ Valid compressors are: ~a~%") compressor-name %valid-compressors)))
|
|||
(guix build utils)
|
||||
(guix profiles)
|
||||
(ice-9 match)
|
||||
((oop goops) #:select (get-keyword))
|
||||
(srfi srfi-1))
|
||||
|
||||
(define machine-type
|
||||
;; Extract the machine type from the specified target, else from the
|
||||
;; current system.
|
||||
(and=> (or #$target %host-type) (lambda (triplet)
|
||||
(first (string-split triplet #\-)))))
|
||||
(and=> (or #$target %host-type)
|
||||
(lambda (triplet)
|
||||
(first (string-split triplet #\-)))))
|
||||
|
||||
(define (gnu-machine-type->debian-machine-type type)
|
||||
"Translate machine TYPE from the GNU to Debian terminology."
|
||||
;; Debian has its own jargon, different from the one used in GNU, for
|
||||
;; machine types (see data/cputable in the sources of dpkg).
|
||||
(match type
|
||||
("i586" "i386")
|
||||
("i486" "i386")
|
||||
("i586" "i386")
|
||||
("i686" "i386")
|
||||
("x86_64" "amd64")
|
||||
("aarch64" "arm64")
|
||||
|
@ -773,21 +779,40 @@ Valid compressors are: ~a~%") compressor-name %valid-compressors)))
|
|||
|
||||
(copy-file #+data-tarball data-tarball-file-name)
|
||||
|
||||
;; Generate the control archive.
|
||||
(define control-file
|
||||
(get-keyword #:control-file '#$extra-options))
|
||||
|
||||
(define postinst-file
|
||||
(get-keyword #:postinst-file '#$extra-options))
|
||||
|
||||
(define triggers-file
|
||||
(get-keyword #:triggers-file '#$extra-options))
|
||||
|
||||
(define control-tarball-file-name
|
||||
(string-append "control.tar"
|
||||
#$(compressor-extension compressor)))
|
||||
|
||||
;; Write the compressed control tarball. Only the control file is
|
||||
;; mandatory (see: 'man deb' and 'man deb-control').
|
||||
(call-with-output-file "control"
|
||||
(lambda (port)
|
||||
(format port "\
|
||||
(if control-file
|
||||
(copy-file control-file "control")
|
||||
(call-with-output-file "control"
|
||||
(lambda (port)
|
||||
(format port "\
|
||||
Package: ~a
|
||||
Version: ~a
|
||||
Description: Debian archive generated by GNU Guix.
|
||||
Maintainer: GNU Guix
|
||||
Architecture: ~a
|
||||
~%" package-name package-version architecture)))
|
||||
~%" package-name package-version architecture))))
|
||||
|
||||
(when postinst-file
|
||||
(copy-file postinst-file "postinst")
|
||||
(chmod "postinst" #o755))
|
||||
|
||||
(when triggers-file
|
||||
(copy-file triggers-file "triggers"))
|
||||
|
||||
(define tar (string-append #+archiver "/bin/tar"))
|
||||
|
||||
|
@ -796,7 +821,9 @@ Architecture: ~a
|
|||
#:tar tar
|
||||
#:compressor '#+(and=> compressor compressor-command))
|
||||
"-cvf" ,control-tarball-file-name
|
||||
"control"))
|
||||
"control"
|
||||
,@(if postinst-file '("postinst") '())
|
||||
,@(if triggers-file '("triggers") '())))
|
||||
|
||||
;; Create the .deb archive using GNU ar.
|
||||
(invoke (string-append #+binutils "/bin/ar") "-rv" #$output
|
||||
|
@ -1157,6 +1184,34 @@ last resort for relocation."
|
|||
deb Debian archive installable via dpkg/apt"))
|
||||
(newline))
|
||||
|
||||
(define %deb-format-options
|
||||
(let ((required-option (lambda (symbol)
|
||||
(option (list (symbol->string symbol)) #t #f
|
||||
(lambda (opt name arg result . rest)
|
||||
(apply values
|
||||
(alist-cons symbol arg result)
|
||||
rest))))))
|
||||
(list (required-option 'control-file)
|
||||
(required-option 'postinst-file)
|
||||
(required-option 'triggers-file))))
|
||||
|
||||
(define (show-deb-format-options)
|
||||
(display (G_ "
|
||||
--help-deb-format list options specific to the deb format")))
|
||||
|
||||
(define (show-deb-format-options/detailed)
|
||||
(display (G_ "
|
||||
--control-file=FILE
|
||||
Embed the provided control FILE"))
|
||||
(display (G_ "
|
||||
--postinst-file=FILE
|
||||
Embed the provided postinst script"))
|
||||
(display (G_ "
|
||||
--triggers-file=FILE
|
||||
Embed the provided triggers FILE"))
|
||||
(newline)
|
||||
(exit 0))
|
||||
|
||||
(define %options
|
||||
;; Specifications of the command-line options.
|
||||
(cons* (option '(#\h "help") #f #f
|
||||
|
@ -1250,7 +1305,12 @@ last resort for relocation."
|
|||
(lambda (opt name arg result)
|
||||
(alist-cons 'bootstrap? #t result)))
|
||||
|
||||
(append %transformation-options
|
||||
(option '("help-deb-format") #f #f
|
||||
(lambda args
|
||||
(show-deb-format-options/detailed)))
|
||||
|
||||
(append %deb-format-options
|
||||
%transformation-options
|
||||
%standard-build-options)))
|
||||
|
||||
(define (show-help)
|
||||
|
@ -1260,6 +1320,8 @@ Create a bundle of PACKAGE.\n"))
|
|||
(newline)
|
||||
(show-transformation-options-help)
|
||||
(newline)
|
||||
(show-deb-format-options)
|
||||
(newline)
|
||||
(display (G_ "
|
||||
-f, --format=FORMAT build a pack in the given FORMAT"))
|
||||
(display (G_ "
|
||||
|
@ -1369,6 +1431,18 @@ Create a bundle of PACKAGE.\n"))
|
|||
(else
|
||||
(packages->manifest packages))))))
|
||||
|
||||
(define (process-file-arg opts name)
|
||||
;; Validate that the file exists and return it as a <local-file> object,
|
||||
;; else #f.
|
||||
(let ((value (assoc-ref opts name)))
|
||||
(match value
|
||||
((and (? string?) (not (? file-exists?)))
|
||||
(leave (G_ "file provided with option ~a does not exist: ~a~%")
|
||||
(string-append "--" (symbol->string name)) value))
|
||||
((? string?)
|
||||
(local-file value))
|
||||
(#f #f))))
|
||||
|
||||
(with-error-handling
|
||||
(with-store store
|
||||
(with-status-verbosity (assoc-ref opts 'verbosity)
|
||||
|
@ -1401,6 +1475,15 @@ Create a bundle of PACKAGE.\n"))
|
|||
manifest)
|
||||
manifest)))
|
||||
(pack-format (assoc-ref opts 'format))
|
||||
(extra-options (match pack-format
|
||||
('deb
|
||||
(list #:control-file
|
||||
(process-file-arg opts 'control-file)
|
||||
#:postinst-file
|
||||
(process-file-arg opts 'postinst-file)
|
||||
#:triggers-file
|
||||
(process-file-arg opts 'triggers-file)))
|
||||
(_ '())))
|
||||
(target (assoc-ref opts 'target))
|
||||
(bootstrap? (assoc-ref opts 'bootstrap?))
|
||||
(compressor (if bootstrap?
|
||||
|
@ -1465,7 +1548,9 @@ to your package list.")))
|
|||
#:profile-name
|
||||
profile-name
|
||||
#:archiver
|
||||
archiver)))
|
||||
archiver
|
||||
#:extra-options
|
||||
extra-options)))
|
||||
(mbegin %store-monad
|
||||
(mwhen derivation?
|
||||
(return (format #t "~a~%"
|
||||
|
|
|
@ -277,17 +277,25 @@
|
|||
(built-derivations (list check))))
|
||||
|
||||
(unless store (test-skip 1))
|
||||
(test-assertm "deb archive with symlinks" store
|
||||
(test-assertm "deb archive with symlinks and control files" store
|
||||
(mlet* %store-monad
|
||||
((guile (set-guile-for-build (default-guile)))
|
||||
(profile (profile-derivation (packages->manifest
|
||||
(list %bootstrap-guile))
|
||||
#:hooks '()
|
||||
#:locales? #f))
|
||||
(deb (debian-archive "deb-pack" profile
|
||||
#:compressor %gzip-compressor
|
||||
#:symlinks '(("/opt/gnu/bin" -> "bin"))
|
||||
#:archiver %tar-bootstrap))
|
||||
(deb (debian-archive
|
||||
"deb-pack" profile
|
||||
#:compressor %gzip-compressor
|
||||
#:symlinks '(("/opt/gnu/bin" -> "bin"))
|
||||
#:archiver %tar-bootstrap
|
||||
#:extra-options
|
||||
(list #:triggers-file
|
||||
(plain-file "triggers"
|
||||
"activate-noawait /usr/share/icons/hicolor\n")
|
||||
#:postinst-file
|
||||
(plain-file "postinst"
|
||||
"echo running configure script\n"))))
|
||||
(check
|
||||
(gexp->derivation "check-deb-pack"
|
||||
(with-imported-modules '((guix build utils))
|
||||
|
@ -344,6 +352,15 @@
|
|||
(unless (null? hard-links)
|
||||
(error "hard links found in data.tar.gz" hard-links))
|
||||
|
||||
;; Verify the presence of the control files.
|
||||
(invoke "tar" "-xf" "control.tar.gz")
|
||||
(assert (file-exists? "control"))
|
||||
(assert (and (file-exists? "postinst")
|
||||
(= #o111 ;script is executable
|
||||
(logand #o111 (stat:perms
|
||||
(stat "postinst"))))))
|
||||
(assert (file-exists? "triggers"))
|
||||
|
||||
(mkdir #$output))))))
|
||||
(built-derivations (list check)))))
|
||||
|
||||
|
|
Reference in New Issue