1
0
forked from tribes/guix

Compare commits

..

3 Commits

Author SHA1 Message Date
Jan (janneke) Nieuwenhuizen 89a8bd9257 gnu: commencement: mes-boot: Use new package style.
* gnu/packages/commencement.scm (mes-boot)[arguments]: Use gexp for modify
phases.
2022-05-14 21:39:06 +02:00
Jan (janneke) Nieuwenhuizen f99f4a2257 gnu: commencement: stage0-posix: Use new package style.
* gnu/packages/commencement.scm (stage0-posix)[arguments]: Also use gexps for
inputs and output.
2022-05-14 21:35:00 +02:00
Jan (janneke) Nieuwenhuizen 02874b2a43 gnu: commencement: bootstrap-seeds: Use new package style.
* gnu/packages/commencement.scm (bootstrap-seeds)[arguments]: Also use gexps
for inputs and output.
2022-05-14 21:33:33 +02:00
1787 changed files with 778864 additions and 1258030 deletions
+27 -50
View File
@@ -6,33 +6,39 @@
(sentence-end-double-space . t)
;; For use with 'bug-reference-prog-mode'.
(bug-reference-url-format . "http://bugs.gnu.org/%s")
(bug-reference-bug-regexp
. "\\(<https?://\\bugs\\.gnu\\.org/\\([0-9]+\\)>\\)")
(bug-reference-url-format . "https://bugs.gnu.org/%s")
(eval . (add-to-list 'completion-ignored-extensions ".go"))
. "<https?://\\(debbugs\\|bugs\\)\\.gnu\\.org/\\([0-9]+\\)>")
;; Emacs-Guix
(eval . (setq-local guix-directory
(locate-dominating-file default-directory
".dir-locals.el")))
;; YASnippet
(eval . (with-eval-after-load
'yasnippet
(let ((guix-yasnippets
(expand-file-name
"etc/snippets/yas"
(locate-dominating-file default-directory
".dir-locals.el"))))
(unless (member guix-yasnippets yas-snippet-dirs)
(add-to-list 'yas-snippet-dirs guix-yasnippets)
(yas-reload-all)))))
;; Geiser
;; This allows automatically setting the `geiser-guile-load-path'
;; variable when using various Guix checkouts (e.g., via git worktrees).
(geiser-repl-per-project-p . t)))
(eval . (let ((root-dir-unexpanded (locate-dominating-file
default-directory ".dir-locals.el")))
;; While Guix should in theory always have a .dir-locals.el
;; (we are reading this file, after all) there seems to be a
;; strange problem where this code "escapes" to some other buffers,
;; at least vc-mode. See:
;; https://lists.gnu.org/archive/html/guix-devel/2020-11/msg00296.html
;; Upstream report: <https://bugs.gnu.org/44698>
;; Hence the following "when", which might otherwise be unnecessary;
;; it prevents causing an error when root-dir-unexpanded is nil.
(when root-dir-unexpanded
(let* ((root-dir (expand-file-name root-dir-unexpanded))
;; Workaround for bug https://issues.guix.gnu.org/43818.
(root-dir* (directory-file-name root-dir)))
(unless (boundp 'geiser-guile-load-path)
(defvar geiser-guile-load-path '()))
(make-local-variable 'geiser-guile-load-path)
(require 'cl-lib)
(cl-pushnew root-dir* geiser-guile-load-path
:test #'string-equal)))))))
(c-mode . ((c-file-style . "gnu")))
(scheme-mode
@@ -41,7 +47,7 @@
(eval . (put 'eval-when 'scheme-indent-function 1))
(eval . (put 'call-with-prompt 'scheme-indent-function 1))
(eval . (put 'test-assert 'scheme-indent-function 1))
(eval . (put 'test-assertm 'scheme-indent-function 2))
(eval . (put 'test-assertm 'scheme-indent-function 1))
(eval . (put 'test-equalm 'scheme-indent-function 1))
(eval . (put 'test-equal 'scheme-indent-function 1))
(eval . (put 'test-eq 'scheme-indent-function 1))
@@ -50,11 +56,7 @@
(eval . (put 'guard 'scheme-indent-function 1))
(eval . (put 'lambda* 'scheme-indent-function 1))
(eval . (put 'substitute* 'scheme-indent-function 1))
(eval . (put 'match-record 'scheme-indent-function 3))
(eval . (put 'match-record-lambda 'scheme-indent-function 2))
;; TODO: Contribute these to Emacs' scheme-mode.
(eval . (put 'let-keywords 'scheme-indent-function 3))
(eval . (put 'match-record 'scheme-indent-function 2))
;; 'modify-inputs' and its keywords.
(eval . (put 'modify-inputs 'scheme-indent-function 1))
@@ -78,6 +80,7 @@
(eval . (put 'origin 'scheme-indent-function 0))
(eval . (put 'build-system 'scheme-indent-function 0))
(eval . (put 'bag 'scheme-indent-function 0))
(eval . (put 'gexp->derivation 'scheme-indent-function 1))
(eval . (put 'graft 'scheme-indent-function 0))
(eval . (put 'operating-system 'scheme-indent-function 0))
(eval . (put 'file-system 'scheme-indent-function 0))
@@ -115,11 +118,9 @@
(eval . (put 'munless 'scheme-indent-function 1))
(eval . (put 'mlet* 'scheme-indent-function 2))
(eval . (put 'mlet 'scheme-indent-function 2))
(eval . (put 'mparameterize 'scheme-indent-function 2))
(eval . (put 'run-with-store 'scheme-indent-function 1))
(eval . (put 'run-with-state 'scheme-indent-function 1))
(eval . (put 'wrap-program 'scheme-indent-function 1))
(eval . (put 'wrap-script 'scheme-indent-function 1))
(eval . (put 'with-imported-modules 'scheme-indent-function 1))
(eval . (put 'with-extensions 'scheme-indent-function 1))
(eval . (put 'with-parameters 'scheme-indent-function 1))
@@ -154,31 +155,7 @@
;; preceding symbol is one of these.
(eval . (modify-syntax-entry ?~ "'"))
(eval . (modify-syntax-entry ?$ "'"))
(eval . (modify-syntax-entry ?+ "'"))
;; Emacs 28 changed the behavior of 'lisp-fill-paragraph', which causes the
;; first line of package descriptions to extrude past 'fill-column', and
;; somehow that is deemed more correct upstream (see:
;; https://issues.guix.gnu.org/56197).
(eval . (progn
(require 'lisp-mode)
(defun emacs27-lisp-fill-paragraph (&optional justify)
(interactive "P")
(or (fill-comment-paragraph justify)
(let ((paragraph-start
(concat paragraph-start
"\\|\\s-*\\([(;\"]\\|\\s-:\\|`(\\|#'(\\)"))
(paragraph-separate
(concat paragraph-separate "\\|\\s-*\".*[,\\.]$"))
(fill-column (if (and (integerp emacs-lisp-docstring-fill-column)
(derived-mode-p 'emacs-lisp-mode))
emacs-lisp-docstring-fill-column
fill-column)))
(fill-paragraph justify))
;; Never return nil.
t))
(setq-local fill-paragraph-function #'emacs27-lisp-fill-paragraph)))))
(eval . (modify-syntax-entry ?+ "'"))))
(emacs-lisp-mode . ((indent-tabs-mode . nil)))
(texinfo-mode . ((indent-tabs-mode . nil)
(fill-column . 72))))
-16
View File
@@ -1,16 +0,0 @@
root = true
[*.{c,h,cpp,hpp,el,scm,ac,am,m4,po}{,.in}]
end_of_line = lf
insert_final_newline = true
charset = utf-8
trim_trailing_whitespace = true
[*.{c,h,cpp,hpp,ac,am,m4,el,scm}{,.in}]
max_line_length = 85
[*.{c,h,cpp,hpp,ac,m4,el,scm}{,.in}]
indent_style = space
[*.{c,h,cpp,hpp}{,.in}]
indent_size = 4
-3
View File
@@ -68,7 +68,6 @@
/doc/version.texi
/doc/version-*.texi
/etc/committer.scm
/etc/teams.scm
/etc/gnu-store.mount
/etc/guix-daemon.cil
/etc/guix-daemon.conf
@@ -158,5 +157,3 @@ tmp
/gnu/packages/bootstrap
/gnu/packages/aux-files/guile-guile-launcher.o
/guile
.DS_Store
.mumi/current-issue
+21 -20
View File
@@ -4,13 +4,12 @@
(authorizations
(version 0)
(;; primary: "D963 A5A3 8A80 3D52 4461 F914 7483 0A27 6C32 8EC2"
("2841 9AC6 5038 7440 C7E9 2FFA 2208 D209 58C1 DEB0"
(name "abcdw"))
(("AD17 A21E F8AE D8F1 CC02 DBD9 F7D5 C9BF 765C 61E3"
(name "andreas"))
("4FB9 9F49 2B12 A365 7997 E664 8246 0C08 2A0E E98F"
(name "alezost"))
("50F3 3E2E 5B0C 3D90 0424 ABE8 9BDC F497 A4BB CC7F"
(name "ambrevar"))
("AD17 A21E F8AE D8F1 CC02 DBD9 F7D5 C9BF 765C 61E3"
(name "andreas"))
("27D5 86A4 F890 0854 329F F09F 1260 E464 82E6 3562"
(name "apteryx"))
("7F73 0343 F2F0 9F3C 77BF 79D3 2E25 EE8B 6180 2BB3"
@@ -18,6 +17,9 @@
(;; primary: "34FF 38BC D151 25A6 E340 A0B5 3453 2F9F AFCA 8B8E"
"A3A4 B419 0074 087C A7DE 5698 BC45 CA67 E2F8 D007"
(name "bavier"))
(;; primary: "8929 BBC5 73CD 9206 3DDD 979D 3D36 CAA0 116F 0F99"
"1C9B F005 1A1A 6A44 5257 599A A949 03A1 66A1 8FAE"
(name "bricewge"))
(;; primary: "0401 7A2A 6D9A 0CCD C81D 8EC2 96AB 007F 1A7E D999"
"09CD D25B 5244 A376 78F6 EEA8 0CC5 2153 1979 91A5"
(name "carl"))
@@ -30,16 +32,15 @@
(;; primary: "295A F991 6F46 F8A1 34B0 29DA 8086 3842 F0FE D83B"
"76CE C6B1 7274 B465 C02D B3D9 E71A 3554 2C30 BAA5"
(name "dannym"))
("8CCB A7F5 52B9 CBEA E1FB 2915 8328 C747 0FF1 D807"
(name "dthompson"))
("B3C0 DB4D AD73 BA5D 285E 19AE 5143 0234 CEFD 87C3"
(name "davexunit"))
("8CCB A7F5 52B9 CBEA E1FB 2915 8328 C747 0FF1 D807" ;FIXME: to be confirmed!
(name "davexunit (2nd)"))
("A28B F40C 3E55 1372 662D 14F7 41AA E7DC CA3D 8351"
(name "efraim"))
(;; primary: "2453 02B1 BAB1 F867 FDCA 96BC 8F3F 861F 82EB 7A9A"
"CBC5 9C66 EC27 B971 7940 6B3E 6BE8 208A DF21 FE3F"
(name "glv"))
(;; primary: "220F 98D9 5E86 204C 0036 DA7B 6DEC 4360 408B 4185"
"F4C2 D1DF 3FDE EA63 D1D3 0776 ACC6 6D09 CA52 8292"
(name "hako"))
("2219 43F4 9E9F 276F 9499 3382 BF28 6CB6 593E 5FFD"
(name "hoebjo"))
("B943 509D 633E 80DD 27FC 4EED 634A 8DFF D3F6 31DF"
@@ -49,22 +50,22 @@
(name "iyzsong"))
("1A85 8392 E331 EAFD B8C2 7FFB F3C1 A0D9 C1D6 5273"
(name "janneke"))
("3B1D 7F19 E36B B60C 0F5B 2CA9 A52A A2B4 77B6 DD35"
(name "jgart"))
(;; primary: "1BA4 08C5 8BF2 0EA7 3179 635A 865D C0A3 DED9 B5D0"
"E31D 9DDE EBA5 4A14 8A20 4550 DA45 97F9 47B4 1025"
(name "jlicht"))
("8141 6036 E81A 5CF7 8F80 1071 ECFC 8398 8B4E 4B9F"
(name "jonsger"))
("3924 8CD8 41C6 3CC3 36DC AF2F 505E 40B9 1617 1A8A"
(name "jpoiret"))
("017D 74E2 7F58 5696 3801 781D F663 943E 08D8 092A"
(name "lbraun"))
("CA4F 8CF4 37D7 478F DA05 5FD4 4213 7701 1A37 8446"
(name "lbraun (professional)"))
("ACC2 3BA0 59F7 CCF4 08F0 43AD 442A 84B8 C70E 2F87"
(name "lilyp"))
(;; primary: "4F71 6F9A 8FA2 C80E F1B5 E1BA 5E35 F231 DE1A C5E0"
"B051 5948 F1E7 D3C1 B980 38A0 2646 FA30 BACA 7F08"
(name "lfam"))
("CBF5 9755 CBE7 E7EF EF18 3FB1 DD40 9A15 D822 469D"
(name "marusich"))
("BBB0 2DDF 2CEA F6A8 0D1D E643 A2A0 6DF2 A33A 54FA"
(name "mbakke"))
("D919 0965 CE03 199E AF28 B3BE 7CEF 2984 7562 C516"
@@ -76,6 +77,8 @@
(;; primary: "F5BC 5534 C36F 0087 B39D 36EF 1C9D C4FE B9DB 7C4B"
"F5DA 2032 4B87 3D0B 7A38 7672 0DB0 FF88 4F55 6D79"
(name "nckx"))
("E576 BFB2 CF6E B13D F571 33B9 E315 A758 4613 1564"
(name "niedzejkob"))
("ED0E F1C8 E126 BA83 1B48 5FE9 DA00 B4F0 48E9 2F2D"
(name "ngz"))
("CEF4 CB91 4856 BA38 0A20 A7E2 3008 88CB 39C6 3817"
@@ -83,9 +86,9 @@
(;; primary: "41CA 12EA DE0C F33F 6885 A58F 5719 6E37 E00B 77FD"
"72D5 3D81 8CB6 F4A1 7258 374C A8FC 9E44 7F4F 7D54"
(name "planglois"))
(;; primary: "7E9F 5BF6 1680 4367 127B 7A87 F9E6 9FB8 5A75 54F1"
"A420 7B56 C255 109F 2CB3 157E 4990 97AE 5EA8 15D9"
(name "podiki"))
(;; primary: "B68B DF22 73F9 DA0E 63C1 8A32 515B F416 9242 D600"
"C699 ED09 E51B CE89 FD1D A078 AAC7 E891 896B 568A"
(name "pgarlick"))
("CD2D 5EAA A98C CB37 DA91 D6B0 5F58 1664 7F8B E551"
(name "raghavgururajan"))
("BCA6 89B6 3655 3801 C3C6 2150 197A 5888 235F ACAC"
@@ -107,6 +110,4 @@
(name "vagrantc"))
(;; primary: "C955 CC5D C048 7FB1 7966 40A9 199A F6A3 67E9 4ABB"
"7238 7123 8EAC EB63 4548 5857 167F 8EA5 001A FA9C"
(name "wigust"))
("705A 29B7 01EE 410E B6F9 236E 92F1 D22C 608E E7E5"
(name "zimoun"))))
(name "wigust"))))
-1
View File
@@ -39,7 +39,6 @@ Joshua Grant <tadni@riseup.net> <gzg@riseup.net>
Joshua Grant <tadni@riseup.net> <jgrant@parenthetical.io>
Joshua Grant <tadni@riseup.net> <tadnimi@gmail.com>
Joshua Grant <tadni@riseup.net> <youlysses@riseup.net>
Juliana Sims <juli@incana.org> <jtsims@protonmail.com>
Kei Kebreau <kkebreau@posteo.net>
Leo Famulari <leo@famulari.name> <lfamular@gmail.com>
Liliana Marie Prikler <liliana.prikler@gmail.com>
-3
View File
@@ -1,3 +0,0 @@
((debbugs-host . "debbugs.gnu.org")
(patch-email-address . "guix-patches@gnu.org")
(mumi-host . "issues.guix.gnu.org"))
-10
View File
@@ -1,10 +0,0 @@
# This config file allows for Patchwork integration with
# https://patches.guix-patches.cbaines.net/.
[settings]
project: guix-patches
patchwork_url: https://patches.guix-patches.cbaines.net
add_signoff: False
# TODO: enable check_patch
check_patch: False
ignore_bad_tags: True
+59 -183
View File
@@ -1,5 +1,5 @@
# GNU Guix --- Functional package management for GNU
# Copyright © 2012-2023 Ludovic Courtès <ludo@gnu.org>
# Copyright © 2012-2022 Ludovic Courtès <ludo@gnu.org>
# Copyright © 2013 Andreas Enge <andreas@enge.fr>
# Copyright © 2015, 2017 Alex Kost <alezost@gmail.com>
# Copyright © 2016, 2018 Mathieu Lirzin <mthl@gnu.org>
@@ -7,14 +7,13 @@
# Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
# Copyright © 2017 Leo Famulari <leo@famulari.name>
# Copyright © 2017 Ricardo Wurmus <rekado@elephly.net>
# Copyright © 2017, 2020, 2023 Janneke Nieuwenhuizen <janneke@gnu.org>
# Copyright © 2017, 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
# Copyright © 2017 Arun Isaac <arunisaac@systemreboot.net>
# Copyright © 2018 Nikita <nikita@n0.is>
# Copyright © 2018 Julien Lepiller <julien@lepiller.eu>
# Copyright © 2018 Oleg Pykhalov <go.wigust@gmail.com>
# Copyright © 2018 Alex Vong <alexvong1995@gmail.com>
# Copyright © 2019 Efraim Flashner <efraim@flashner.co.il>
# Copyright © 2020, 2021, 2023 Maxim Cournoyer <maxim.cournoyer@gmail.com>
# Copyright © 2021 Chris Marusich <cmmarusich@gmail.com>
# Copyright © 2021 Andrew Tropin <andrew@trop.in>
#
@@ -98,6 +97,7 @@ MODULES = \
guix/discovery.scm \
guix/android-repo-download.scm \
guix/bzr-download.scm \
guix/extracting-download.scm \
guix/git-download.scm \
guix/hg-download.scm \
guix/hash.scm \
@@ -112,7 +112,6 @@ MODULES = \
guix/derivations.scm \
guix/grafts.scm \
guix/repl.scm \
guix/rpm.scm \
guix/transformations.scm \
guix/inferior.scm \
guix/describe.scm \
@@ -131,27 +130,16 @@ MODULES = \
guix/cache.scm \
guix/cve.scm \
guix/workers.scm \
guix/least-authority.scm \
guix/read-print.scm \
guix/ipfs.scm \
guix/platform.scm \
guix/platforms/arm.scm \
guix/platforms/mips.scm \
guix/platforms/powerpc.scm \
guix/platforms/riscv.scm \
guix/platforms/x86.scm \
guix/build-system.scm \
guix/build-system/agda.scm \
guix/build-system/android-ndk.scm \
guix/build-system/ant.scm \
guix/build-system/cargo.scm \
guix/build-system/channel.scm \
guix/build-system/chicken.scm \
guix/build-system/clojure.scm \
guix/build-system/cmake.scm \
guix/build-system/dub.scm \
guix/build-system/dune.scm \
guix/build-system/elm.scm \
guix/build-system/emacs.scm \
guix/build-system/font.scm \
guix/build-system/go.scm \
@@ -170,7 +158,6 @@ MODULES = \
guix/build-system/maven.scm \
guix/build-system/node.scm \
guix/build-system/perl.scm \
guix/build-system/pyproject.scm \
guix/build-system/python.scm \
guix/build-system/renpy.scm \
guix/build-system/ocaml.scm \
@@ -178,11 +165,9 @@ MODULES = \
guix/build-system/waf.scm \
guix/build-system/r.scm \
guix/build-system/rakudo.scm \
guix/build-system/rebar.scm \
guix/build-system/ruby.scm \
guix/build-system/scons.scm \
guix/build-system/texlive.scm \
guix/build-system/tree-sitter.scm \
guix/build-system/trivial.scm \
guix/ftp-client.scm \
guix/http-client.scm \
@@ -197,7 +182,6 @@ MODULES = \
guix/diagnostics.scm \
guix/ui.scm \
guix/status.scm \
guix/build/agda-build-system.scm \
guix/build/android-ndk-build-system.scm \
guix/build/ant-build-system.scm \
guix/build/download.scm \
@@ -208,7 +192,6 @@ MODULES = \
guix/build/cmake-build-system.scm \
guix/build/dub-build-system.scm \
guix/build/dune-build-system.scm \
guix/build/elm-build-system.scm \
guix/build/emacs-build-system.scm \
guix/build/meson-build-system.scm \
guix/build/minify-build-system.scm \
@@ -229,22 +212,18 @@ MODULES = \
guix/build/minetest-build-system.scm \
guix/build/node-build-system.scm \
guix/build/perl-build-system.scm \
guix/build/pyproject-build-system.scm \
guix/build/python-build-system.scm \
guix/build/ocaml-build-system.scm \
guix/build/qt-build-system.scm \
guix/build/r-build-system.scm \
guix/build/renpy-build-system.scm \
guix/build/rakudo-build-system.scm \
guix/build/rebar-build-system.scm \
guix/build/ruby-build-system.scm \
guix/build/scons-build-system.scm \
guix/build/texlive-build-system.scm \
guix/build/tree-sitter-build-system.scm \
guix/build/waf-build-system.scm \
guix/build/haskell-build-system.scm \
guix/build/julia-build-system.scm \
guix/build/kconfig.scm \
guix/build/linux-module-build-system.scm \
guix/build/store-copy.scm \
guix/build/json.scm \
@@ -278,7 +257,6 @@ MODULES = \
guix/import/cran.scm \
guix/import/crate.scm \
guix/import/egg.scm \
guix/import/elm.scm \
guix/import/elpa.scm \
guix/import/gem.scm \
guix/import/git.scm \
@@ -287,7 +265,6 @@ MODULES = \
guix/import/gnu.scm \
guix/import/go.scm \
guix/import/hackage.scm \
guix/import/hexpm.scm \
guix/import/json.scm \
guix/import/kde.scm \
guix/import/launchpad.scm \
@@ -296,7 +273,6 @@ MODULES = \
guix/import/print.scm \
guix/import/pypi.scm \
guix/import/stackage.scm \
guix/import/test.scm \
guix/import/texlive.scm \
guix/import/utils.scm \
guix/scripts.scm \
@@ -306,7 +282,6 @@ MODULES = \
guix/scripts/archive.scm \
guix/scripts/import.scm \
guix/scripts/package.scm \
guix/scripts/locate.scm \
guix/scripts/install.scm \
guix/scripts/remove.scm \
guix/scripts/upgrade.scm \
@@ -324,25 +299,20 @@ MODULES = \
guix/scripts/describe.scm \
guix/scripts/style.scm \
guix/scripts/system.scm \
guix/scripts/system/edit.scm \
guix/scripts/system/reconfigure.scm \
guix/scripts/system/search.scm \
guix/scripts/system/reconfigure.scm \
guix/scripts/home.scm \
guix/scripts/home/edit.scm \
guix/scripts/home/import.scm \
guix/scripts/lint.scm \
guix/scripts/challenge.scm \
guix/scripts/import/crate.scm \
guix/scripts/import/cpan.scm \
guix/scripts/import/cran.scm \
guix/scripts/import/egg.scm \
guix/scripts/import/elm.scm \
guix/scripts/import/elpa.scm \
guix/scripts/import/gem.scm \
guix/scripts/import/gnu.scm \
guix/scripts/import/go.scm \
guix/scripts/import/hackage.scm \
guix/scripts/import/hexpm.scm \
guix/scripts/import/json.scm \
guix/scripts/import/minetest.scm \
guix/scripts/import/opam.scm \
@@ -410,14 +380,10 @@ AUX_FILES = \
gnu/packages/aux-files/chromium/master-preferences.json \
gnu/packages/aux-files/emacs/guix-emacs.el \
gnu/packages/aux-files/guix.vim \
gnu/packages/aux-files/linux-libre/6.4-arm.conf \
gnu/packages/aux-files/linux-libre/6.4-arm64.conf \
gnu/packages/aux-files/linux-libre/6.4-i686.conf \
gnu/packages/aux-files/linux-libre/6.4-x86_64.conf \
gnu/packages/aux-files/linux-libre/6.1-arm.conf \
gnu/packages/aux-files/linux-libre/6.1-arm64.conf \
gnu/packages/aux-files/linux-libre/6.1-i686.conf \
gnu/packages/aux-files/linux-libre/6.1-x86_64.conf \
gnu/packages/aux-files/linux-libre/5.16-arm.conf \
gnu/packages/aux-files/linux-libre/5.16-arm64.conf \
gnu/packages/aux-files/linux-libre/5.16-i686.conf \
gnu/packages/aux-files/linux-libre/5.16-x86_64.conf \
gnu/packages/aux-files/linux-libre/5.15-arm.conf \
gnu/packages/aux-files/linux-libre/5.15-arm64.conf \
gnu/packages/aux-files/linux-libre/5.15-i686.conf \
@@ -437,13 +403,15 @@ AUX_FILES = \
gnu/packages/aux-files/linux-libre/4.14-arm.conf \
gnu/packages/aux-files/linux-libre/4.14-i686.conf \
gnu/packages/aux-files/linux-libre/4.14-x86_64.conf \
gnu/packages/aux-files/linux-libre/4.9-i686.conf \
gnu/packages/aux-files/linux-libre/4.9-x86_64.conf \
gnu/packages/aux-files/linux-libre/4.4-i686.conf \
gnu/packages/aux-files/linux-libre/4.4-x86_64.conf \
gnu/packages/aux-files/pack-audit.c \
gnu/packages/aux-files/python/sanity-check.py \
gnu/packages/aux-files/python/sitecustomize.py \
gnu/packages/aux-files/renpy/renpy.in \
gnu/packages/aux-files/run-in-namespace.c \
gnu/packages/aux-files/xml/patch-catalog-xml.xsl \
gnu/packages/aux-files/xml/docbook-xml/catalog-4.1.2.xml
gnu/packages/aux-files/run-in-namespace.c
# Templates, examples.
EXAMPLES = \
@@ -454,9 +422,6 @@ EXAMPLES = \
gnu/system/examples/desktop.tmpl \
gnu/system/examples/lightweight-desktop.tmpl \
gnu/system/examples/docker-image.tmpl \
gnu/system/examples/plasma.tmpl \
gnu/system/examples/raspberry-pi-64.tmpl \
gnu/system/examples/raspberry-pi-64-nfs-root.tmpl \
gnu/system/examples/vm-image.tmpl
GOBJECTS = $(MODULES:%.scm=%.go) guix/config.go $(dist_noinst_DATA:%.scm=%.go)
@@ -494,7 +459,6 @@ SCM_TESTS = \
tests/boot-parameters.scm \
tests/bournish.scm \
tests/builders.scm \
tests/build-emacs-utils.scm \
tests/build-utils.scm \
tests/cache.scm \
tests/challenge.scm \
@@ -510,7 +474,6 @@ SCM_TESTS = \
tests/derivations.scm \
tests/discovery.scm \
tests/egg.scm \
tests/elm.scm \
tests/elpa.scm \
tests/file-systems.scm \
tests/gem.scm \
@@ -524,7 +487,6 @@ SCM_TESTS = \
tests/gremlin.scm \
tests/hackage.scm \
tests/home-import.scm \
tests/home-services.scm \
tests/http-client.scm \
tests/import-git.scm \
tests/import-github.scm \
@@ -546,19 +508,14 @@ SCM_TESTS = \
tests/profiles.scm \
tests/publish.scm \
tests/pypi.scm \
tests/read-print.scm \
tests/records.scm \
tests/rpm.scm \
tests/scripts.scm \
tests/search-paths.scm \
tests/services.scm \
tests/services/file-sharing.scm \
tests/services/configuration.scm \
tests/services/lightdm.scm \
tests/services/linux.scm \
tests/services/pam-mount.scm \
tests/services/telephony.scm \
tests/services/vpn.scm \
tests/sets.scm \
tests/size.scm \
tests/status.scm \
@@ -599,24 +556,19 @@ SH_TESTS = \
tests/guix-gc.sh \
tests/guix-git-authenticate.sh \
tests/guix-hash.sh \
tests/guix-locate.sh \
tests/guix-pack.sh \
tests/guix-pack-localstatedir.sh \
tests/guix-pack-relocatable.sh \
tests/guix-package.sh \
tests/guix-package-aliases.sh \
tests/guix-package-net.sh \
tests/guix-style.sh \
tests/guix-system.sh \
tests/guix-home.sh \
tests/guix-archive.sh \
tests/guix-authenticate.sh \
tests/guix-environment.sh \
tests/guix-environment-container.sh \
tests/guix-refresh.sh \
tests/guix-shell.sh \
tests/guix-shell-export-manifest.sh \
tests/guix-time-machine.sh \
tests/guix-graph.sh \
tests/guix-describe.sh \
tests/guix-repl.sh \
@@ -684,50 +636,48 @@ dist_fishcompletion_DATA = etc/completion/fish/guix.fish
nodist_selinux_policy_DATA = etc/guix-daemon.cil
EXTRA_DIST += \
.dir-locals.el \
.guix-authorizations \
.guix-channel \
CODE-OF-CONDUCT \
HACKING \
ROADMAP \
TODO \
bootstrap \
build-aux/build-self.scm \
build-aux/check-channel-news.scm \
build-aux/check-final-inputs-self-contained.scm \
build-aux/compile-all.scm \
build-aux/compile-as-derivation.scm \
build-aux/config.rpath \
build-aux/convert-xref.scm \
build-aux/generate-authors.scm \
build-aux/test-driver.scm \
build-aux/update-NEWS.scm \
build-aux/update-guix-package.scm \
doc/build.scm \
CODE-OF-CONDUCT \
.dir-locals.el \
.guix-authorizations \
.guix-channel \
scripts/guix.in \
etc/disarchive-manifest.scm \
etc/guix-install.sh \
etc/historical-authorizations \
etc/news.scm \
etc/hurd-manifest.scm \
etc/kernels-manifest.scm \
etc/release-manifest.scm \
etc/source-manifest.scm \
etc/system-tests.scm \
etc/time-travel-manifest.scm \
scripts/guix.in \
etc/historical-authorizations \
build-aux/build-self.scm \
build-aux/compile-all.scm \
build-aux/cuirass/hurd-manifest.scm \
build-aux/check-final-inputs-self-contained.scm \
build-aux/check-channel-news.scm \
build-aux/compile-as-derivation.scm \
build-aux/convert-xref.scm \
build-aux/generate-authors.scm \
build-aux/test-driver.scm \
build-aux/update-guix-package.scm \
build-aux/update-NEWS.scm \
tests/test.drv \
tests/cve-sample.json \
tests/keys/signing-key.pub \
tests/keys/signing-key.sec \
tests/keys/civodul.pub \
tests/keys/rsa.pub \
tests/keys/dsa.pub \
tests/keys/ed25519.pub \
tests/keys/ed25519.sec \
tests/keys/ed25519-2.pub \
tests/keys/ed25519-2.sec \
tests/keys/ed25519-3.pub \
tests/keys/ed25519-3.sec \
tests/keys/ed25519.pub \
tests/keys/ed25519.sec \
tests/keys/rsa.pub \
tests/keys/signing-key.pub \
tests/keys/signing-key.sec \
tests/test.drv \
build-aux/config.rpath \
bootstrap \
doc/build.scm \
$(TESTS)
if !BUILD_DAEMON_OFFLOAD
@@ -776,70 +726,20 @@ endef
# in <https://issues.guix.gnu.org/48963>. Each 'eval' call below creates a
# 'make-*-go' phony target that builds the corresponding subset.
first_fifth := \
gnu/packages/a% gnu/packages/b% gnu/packages/c%
second_fifth := \
gnu/packages/d% gnu/packages/e% gnu/packages/f%
third_fifth := \
gnu/packages/g% gnu/packages/h% gnu/packages/i%
fourth_fifth := \
gnu/packages/j% gnu/packages/k% gnu/packages/l% gnu/packages/m% \
gnu/packages/n% gnu/packages/o%
MODULES_CORE := guix.scm $(filter-out guix/scripts/%,$(filter guix/%,$(MODULES)))
MODULES_PACKAGES1 := $(filter $(first_fifth),$(MODULES))
MODULES_PACKAGES2 := $(filter $(second_fifth),$(MODULES))
MODULES_PACKAGES3 := $(filter $(third_fifth),$(MODULES))
MODULES_PACKAGES4 := $(filter $(fourth_fifth),$(MODULES))
MODULES_PACKAGES5 := $(filter-out $(first_fifth) $(second_fifth) \
$(third_fifth) $(fourth_fifth), \
$(filter gnu/packages/%,$(MODULES)))
MODULES_PACKAGES := $(MODULES_PACKAGES1) $(MODULES_PACKAGES2) \
$(MODULES_PACKAGES3) $(MODULES_PACKAGES4) \
$(MODULES_PACKAGES5)
MODULES_SYSTEM := gnu.scm $(filter-out gnu/packages/%,$(filter gnu/%,$(MODULES)))
MODULES_CLI := $(filter guix/scripts/%,$(MODULES))
MODULES_PO := guix/build/po.scm
MODULES_CORE = guix.scm $(filter-out guix/scripts/%,$(filter guix/%,$(MODULES)))
MODULES_PACKAGES = $(filter gnu/packages/%,$(MODULES))
MODULES_SYSTEM = gnu.scm $(filter-out gnu/packages/%,$(filter gnu/%,$(MODULES)))
MODULES_CLI = $(filter guix/scripts/%,$(MODULES))
MODULES_PO = guix/build/po.scm
$(eval $(call guile-compilation-rule,make-core-go, \
$(MODULES_CORE) guix/config.scm $(dist_noinst_DATA), \
0))
.PHONY: make-core-go
$(eval $(call guile-compilation-rule,make-packages1-go, \
$(MODULES_PACKAGES1) make-core-go, \
$(eval $(call guile-compilation-rule,make-packages-go, \
$(MODULES_PACKAGES) make-core-go, \
$(words $(MODULES_CORE))))
.PHONY: make-packages1-go
$(eval $(call guile-compilation-rule,make-packages2-go, \
$(MODULES_PACKAGES2) make-core-go make-packages1-go, \
$(words $(MODULES_CORE) $(MODULES_PACKAGES1))))
.PHONY: make-packages2-go
$(eval $(call guile-compilation-rule,make-packages3-go, \
$(MODULES_PACKAGES3) make-core-go make-packages1-go make-packages2-go, \
$(words $(MODULES_CORE) $(MODULES_PACKAGES1) $(MODULES_PACKAGES2))))
.PHONY: make-packages3-go
$(eval $(call guile-compilation-rule,make-packages4-go, \
$(MODULES_PACKAGES4) make-core-go make-packages1-go make-packages2-go \
make-packages3-go, \
$(words $(MODULES_CORE) $(MODULES_PACKAGES1) $(MODULES_PACKAGES2) \
$(MODULES_PACKAGES3))))
.PHONY: make-packages4-go
$(eval $(call guile-compilation-rule,make-packages5-go, \
$(MODULES_PACKAGES5) make-core-go make-packages1-go make-packages2-go \
make-packages3-go make-packages4-go, \
$(words $(MODULES_CORE) $(MODULES_PACKAGES1) $(MODULES_PACKAGES2) \
$(MODULES_PACKAGES3) $(MODULES_PACKAGES4))))
.PHONY: make-packages5-go
make-packages-go: make-packages1-go make-packages2-go \
make-packages3-go make-packages4-go make-packages5-go
.PHONY: make-packages-go
$(eval $(call guile-compilation-rule,make-system-go, \
@@ -1055,21 +955,25 @@ release: dist-with-updated-version all
mv "guix-binary.$$system.tar.xz" \
"$(releasedir)/guix-binary-$(PACKAGE_VERSION).$$system.tar.xz" ; \
done
# Build 'current-guix' to speed things up for the next step.
$(top_builddir)/pre-inst-env guix build \
-e '((@ (gnu packages package-management) current-guix))' \
# Bump the Guix package version and build it (again).
GUIX_ALLOW_ME_TO_USE_PRIVATE_COMMIT=yes \
$(top_builddir)/pre-inst-env "$(GUILE)" \
$(top_srcdir)/build-aux/update-guix-package.scm \
"`git rev-parse HEAD`"
git add $(top_srcdir)/gnu/packages/package-management.scm
git commit -m "gnu: guix: Update to `git rev-parse HEAD | cut -c1-7`."
$(top_builddir)/pre-inst-env guix build guix \
$(call system_flags,$(GUIX_SYSTEM_SUPPORTED_SYSTEMS)) \
-v1 --no-grafts --fallback
# Generate the ISO installation images.
for system in $(GUIX_SYSTEM_SUPPORTED_SYSTEMS) ; do \
GUIX_DISPLAYED_VERSION="`git describe --match=v* | sed -'es/^v//'`" ; \
image=`$(top_builddir)/pre-inst-env \
guix system image -t iso9660 \
guix system image -t iso9660 \
--label="GUIX_$${system}_$(VERSION)" \
--system=$$system --fallback \
gnu/system/install.scm` ; \
if [ ! -f "$$image" ] ; then \
echo "failed to produce Guix installation image for $$system" >&2 ; \
echo "failed to produce Guix installation image for $$system" >&2 ; \
exit 1 ; \
fi ; \
cp "$$image" "$(releasedir)/$(GUIX_SYSTEM_IMAGE_BASE).$$system.iso.tmp" ; \
@@ -1078,7 +982,6 @@ release: dist-with-updated-version all
done
# Generate the VM images.
for system in $(GUIX_SYSTEM_VM_SYSTEMS) ; do \
GUIX_DISPLAYED_VERSION="`git describe --match=v* | sed -'es/^v//'`" ; \
image=`$(top_builddir)/pre-inst-env \
guix system image -t qcow2 $(GUIX_SYSTEM_VM_IMAGE_FLAGS) \
--save-provenance \
@@ -1156,19 +1059,6 @@ cuirass-jobs: $(GOBJECTS)
.PHONY: clean-go make-go as-derivation authenticate
.PHONY: update-guix-package update-NEWS cuirass-jobs release
# Git auto-configuration.
.git/hooks/pre-push: etc/git/pre-push
$(AM_V_at)if test -d .git; then \
cp etc/git/pre-push .git/hooks/pre-push; \
fi
.git/config: etc/git/gitconfig
$(AM_V_at)if command -v git >/dev/null && test -d .git; then \
git config --add include.path ../etc/git/gitconfig; \
fi
nodist_noinst_DATA = .git/hooks/pre-push .git/config
# Downloading up-to-date PO files.
WEBLATE_REPO = https://framagit.org/tyreunom/guix-translations
@@ -1179,35 +1069,21 @@ WEBLATE_REPO = https://framagit.org/tyreunom/guix-translations
# form.
download-po:
dir=$$(mktemp -d); \
git clone --depth 1 "$(WEBLATE_REPO)" "$$dir/translations" && \
git clone --depth 1 "$(WEBLATE_REPO)" "$$dir/translations"; \
for domain in po/doc po/guix po/packages; do \
for po in "$$dir/translations/$$domain"/*.po; do \
translated=$$(LANG=en_US.UTF-8 msgfmt --statistics "$$po" 2>&1 | cut -f1 -d' '); \
untranslated=$$(LANG=en_US.UTF-8 msgfmt --statistics "$$po" 2>&1 | rev | cut -f3 -d' ' | rev); \
untranslated=$${untranslated:-0}; \
total=$$(($$translated+$$untranslated)); \
target=$$(basename "$$po"); \
target="$$domain/$$target"; \
msgfmt -c "$$po"; \
if msgfmt -c "$$po" && [ "$$translated" != "0" ] && ([ "$$domain" != "po/doc" ] || [ "$$translated" -gt $$(($$total/10)) ] || [ -f $$target ]); then \
if msgfmt -c "$$po" && [ "$$translated" != "0" ]; then \
msgfilter --no-wrap -i "$$po" cat > "$$po".tmp; \
mv "$$po".tmp "$$target"; \
echo "copied $$target."; \
else \
echo "WARN: $$target ($$translated translated messages ($$((translated/total*100))%)) was not added/updated."; \
echo "WARN: $$target ($$translated translated messages) was not added/updated."; \
fi; \
done; \
done; \
for po in po/doc/*.po; do \
translated=$$(LANG=en_US.UTF-8 msgfmt --statistics "$$po" 2>&1 | cut -f1 -d' '); \
untranslated=$$(LANG=en_US.UTF-8 msgfmt --statistics "$$po" 2>&1 | rev | cut -f3 -d' ' | rev); \
untranslated=$${untranslated:-0}; \
total=$$(($$translated + $$untranslated)); \
if [ "$$translated" -lt "$$(($$total/20))" ]; then \
echo "WARN: $$po was removed because it is below the 5% threshold: $$((translated/total*100))%"; \
rm $$po; \
fi; \
done; \
rm -rf "$$dir"
.PHONY: download-po
+2 -140
View File
@@ -2,10 +2,9 @@
#+TITLE: Guix NEWS history of user-visible changes
#+STARTUP: content hidestars
Copyright © 2013-2022 Ludovic Courtès <ludo@gnu.org>
Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo@gnu.org>
Copyright © 2016, 2017, 2018 Ricardo Wurmus <rekado@elephly.net>
Copyright © 2021, 2022 Maxim Cournoyer <maxim.cournoyer@gmail.com>
Copyright © 2022 Mathieu Othacehe <othacehe@gnu.org>
Copyright © 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com>
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
@@ -13,127 +12,26 @@ Copyright © 2022 Mathieu Othacehe <othacehe@gnu.org>
Please send Guix bug reports to bug-guix@gnu.org.
* Changes in 1.5.0 (since 1.4.0)
** Package management
*** New rpm format for the guix pack command
* Changes in 1.4.0 (since 1.3.0)
** Package management
*** New guix home command, for home environment management
*** New guix shell command, the successor to guix environment
*** New guix system edit command, to edit services
*** New deb format for the guix pack command
*** New guix import minetest command, to import Minetest extensions
*** New guix import elm command, to import Elm packages
*** New guix import egg command, to import CHICKEN egg packages
*** New guix import hexpm command, to import Erlang and Elixir packages
*** New 'guix style' command, to auto-format package definitions
*** guix import texlive rewritten to use the TLPDB as its source
*** guix import elpa now supports the non-GNU ELPA repository
*** guix import pypi can now import a specific version
*** guix import cran can now import a specific version
*** New updater (see guix refresh): generic-git
*** guix graph has a new --max-depth option
*** guix deploy has a new --execute option
*** guix shell has a new --emulate-fhs option
*** guix shell has a new --symlink option
*** --with-commit option now accepts strings returned by git describe
*** --with-source option now applied recursively
*** Align tabular data output by commands like guix package --list-available
*** Improved guix import go importer via a new PEG parser
*** Improved Software Heritage downloader
*** New 'web.archive.org download fall-back
*** Various performance enhancements
*** New --tune package transformation option
*** guix refresh -L option is repurposed to load-path modification
*** guix system image supersedes the docker-image sub-command
** Distribution
*** The installation script can now enable local substitute servers discovery
*** The installation script can now customize the Bash prompt for Guix
*** More control over boot-time file system checks and repairs
*** XFS file systems can be created by the installer and mounted by label/UUID
*** New interface for declaring swap space
*** GNOME is now at version 42
*** TeX Live is now at version 2021
*** Multiple TeX Live trees can now be used via GUIX_TEXMF
*** Python modules are searched in GUIX_PYTHONPATH instead of PYTHONPATH
*** Python is now faster thanks to being built with optimizations
*** The Rust bootstrap now starts from 1.54 instead of 1.19
*** Most Python 2 packages have been removed
*** Guix now makes use of parallel xz compression
*** Faster shared libraries discovery via a per-package dynamic linker cache
*** Package inputs can now be plain package lists
*** A package origin can now be a single file rather than an archive
*** New sanity-check phase to detect Python packaging problems at build time
*** Fetching sources can now fall-back to use Disarchive
*** Improved CI and infrastructure
*** Multiple cross-compilation tooling addition and fixes
*** Many Qt 6 modules are now packaged
*** Configuring setuid programs is now more flexible
*** Add support for the XFS file system
*** Add partial support for LUKS2 headers when using GRUB
*** GDM now supports Wayland
*** Guix System static networking support is improved
*** The installer final configuration is prettified
*** The installer external command handling is improved
*** The installer now has a crash dump upload mechanism
*** Emacs now supports native compilation
*** GRUB bootloader now supports chain-loading
*** The GNU Shepherd was upgraded to 0.9.3
*** The init RAM disk honors more arguments—e.g. root and rootflags
*** guix system image can now generate WSL images
*** The mcron task scheduler logs now contain the jobs exit statuses
*** Chromium extensions are now built in a deterministic fashion
*** The rsync service lets you specify individual “modules”
*** New services
anonip, bitmask, fail2ban, gitile, greetd, jami, lightdm, log-cleanup,
nar-herder, opendht, rasdaemon, samba, seatd, strongswan, wsdd
*** 5311 new packages
*** 6573 package updates
Noteworthy updates:
bash 5.1.8, binutils 2.37, clojure 1.11.1, cups 2.3.3op2, emacs 28.2,
enlightenment 0.25.4, gcc-toolchain 12.2.0, gdb 12.1, ghc 8.10.7,
gimp 2.10.32, glibc 2.33, gnome 42.4, gnupg 2.2.32, go 1.19.1, guile 3.0.8,
icecat 102.5.0-guix0-preview1, icedtea 3.19.0, inkscape 1.2.1, julia 1.6.7,
libreoffice 7.4.3.2, linux-libre 6.0.10, ocaml 4.14.0, octave 7.2.0,
openjdk 18, perl 5.34.0, python2 2.7.18, python 3.9.9, racket 8.7,
rust 1.60.0, r 4.2.2, sbcl 2.2.10, shepherd 0.9.3, xorg-server 21.1.4
** Programming interfaces
*** Package input fields can now be plain package lists
*** G-expressions can now be used in build phases
*** New modify-inputs macro to ease customizing a list of package inputs
*** New this-package-input and this-package-native-input macros
*** Build phases are no longer required to return a boolean
*** (guix records) now supports “field sanitizers”
*** Various improvements to the helpers in (gnu service configuration)
*** texlive-union is now deprecated in favor of texlive-updmap.cfg
*** New (guix cpu) module
*** New (guix least-authority) module
*** New (guix platform) module
*** New (guix read-print) module
It provides a comment-preserving reader and a comment-preserving
pretty-printer smarter than (ice-9 pretty-print).
*** New channel-build-system
This build system lets you build Guix instances from channel specifications,
similar to how 'guix time-machine' would do it, as regular packages.
*** New pyproject-build-system
This is an extension of python-build-system with support for PEP-517 and
pyproject.toml files. It may eventually get merged back into
python-build-system.
*** New elm-build-system
*** New rebar-build-system
** Noteworthy bug fixes
*** Fall back to Software Heritage when cloning a channel
(<https://issues.guix.gnu.org/44187>)
@@ -145,42 +43,6 @@ This is an extension of python-build-system with support for PEP-517 and
(<https://issues.guix.gnu.org/24937>)
*** File system flags are validated before system instantiation
(<https://issues.guix.gnu.org/51425>)
*** Fonts can now be discovered in any profile via XDG_DATA_DIRS
(<https://issues.guix.gnu.org/31403>)
*** Various Python reproducibility fixes
*** The installer now supports MSDOS disk labels on UEFI systems
(<https://issues.guix.gnu.org/47889>)
*** The installer can now properly mount FAT16 partitions
(<https://issues.guix.gnu.org/48419>)
*** The installer no longer crashes when deleting a free space partition
*** Emacs handles major upgrades better without a re-login
(<https://issues.guix.gnu.org/47458>)
*** The bootloader configuration now accepts multiple targets
(<https://issues.guix.gnu.org/40997>)
*** File system mount point is always created when create? is true
(<https://issues.guix.gnu.org/40158>)
*** Build the man database only if man-db is in the profile
*** gdk-pixbuf now discovers pixbuf loaders via a search path
(<https://issues.guix.gnu.org/50957>)
*** Gitolite home directory permissions are fixed
(https://issues.guix.gnu.org/56444)
*** The man-db database is indexed via man pages names
(https://issues.guix.gnu.org/38838)
*** chfn can now change the user's full name
(https://issues.guix.gnu.org/52539)
*** GNOME Settings Bluetooth panel is now working
(https://issues.guix.gnu.org/32166)
*** Inferiors are now caching store connections
(https://issues.guix.gnu.org/48007)
*** Retry downloads when a substitute has become unavailable
(https://issues.guix.gnu.org/57978)
*** The installer doesn't segfault when removing an extended partition
*** The installer doesn't ship an older Guix revision
(https://issues.guix.gnu.org/53210)
*** The installer cannot proceed without any non-root user accounts
(https://issues.guix.gnu.org/54666)
*** <operating-system> compiler truly honors the 'system' argument
(https://issues.guix.gnu.org/55951)
* Changes in 1.3.0 (since 1.2.0)
** Package management
+23 -30
View File
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2016-2018, 2020, 2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2016, 2017, 2018, 2020 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2017 Jan Nieuwenhuizen <janneke@gnu.org>
;;; Copyright © 2021 Mathieu Othacehe <othacehe@gnu.org>
;;;
@@ -78,35 +78,28 @@
;; up the evaluation speed as the evaluations can be performed
;; concurrently. It also decreases the amount of memory needed per
;; evaluation process.
;;
;; Fork inferior processes upfront before we have created any
;; threads.
(let ((inferiors (map (lambda _
(open-inferior (derivation->output-path derivation)))
%cuirass-supported-systems)))
(n-par-for-each
(min (length %cuirass-supported-systems)
(current-processor-count))
(lambda (system inferior)
(with-store store
(let ((channels (map channel-instance->sexp instances)))
(inferior-eval '(use-modules (gnu ci)) inferior)
(let ((jobs
(inferior-eval-with-store
inferior store
`(lambda (store)
(cuirass-jobs store
'((subset . all)
(systems . ,(list system))
(channels . ,channels))))))
(file
(string-append directory "/jobs-" system ".scm")))
(close-inferior inferior)
(call-with-output-file file
(lambda (port)
(write jobs port)))))))
%cuirass-supported-systems
inferiors)))))))
(n-par-for-each
(/ (current-processor-count) 2)
(lambda (system)
(with-store store
(let ((inferior
(open-inferior (derivation->output-path derivation)))
(channels (map channel-instance->sexp instances)))
(inferior-eval '(use-modules (gnu ci)) inferior)
(let ((jobs
(inferior-eval-with-store
inferior store
`(lambda (store)
(cuirass-jobs store
'((subset . all)
(systems . ,(list system))
(channels . ,channels))))))
(file
(string-append directory "/jobs-" system ".scm")))
(call-with-output-file file
(lambda (port)
(write jobs port)))))))
%cuirass-supported-systems))))))
(x
(format (current-error-port) "Wrong command: ~a~%." x)
(exit 1)))
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2020, 2023 Janneke Nieuwenhuizen <janneke@gnu.org>
;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -31,7 +31,7 @@
(srfi srfi-1))
(use-package-modules
base bootloaders commencement compression file gawk gdb gettext guile
base commencement compression file gawk gdb gettext guile
hurd less m4 package-management python ssh version-control)
(define (input->package input)
@@ -64,14 +64,11 @@
;; development packages
gcc-toolchain gdb-minimal git-minimal gnu-make
gettext-minimal python-minimal
;; ourselves!
(package-without-tests guix)
;; system
grub-minimal grub
;; guix environment guix --without-tests=python-minimal --without-tests=gettext-minimal
(package-without-tests gettext-minimal)
(package-without-tests python-minimal)
(append
guix-dependencies
%base-packages/hurd)))
(delete guile-3.0 %base-packages/hurd))))
-1
View File
@@ -274,7 +274,6 @@ AC_CONFIG_FILES([Makefile
guix/config.scm])
AC_CONFIG_FILES([etc/committer.scm], [chmod +x etc/committer.scm])
AC_CONFIG_FILES([etc/teams.scm], [chmod +x etc/teams.scm])
AC_CONFIG_FILES([test-env:build-aux/test-env.in], [chmod +x test-env])
AC_CONFIG_FILES([pre-inst-env:build-aux/pre-inst-env.in],
[chmod +x pre-inst-env])
+35 -50
View File
@@ -1,7 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2019-2023 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2019-2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2020 Björn Höfling <bjoern.hoefling@bjoernhoefling.de>
;;; Copyright © 2022 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -31,7 +30,6 @@
(guix gexp)
(guix git)
(guix git-download)
(guix profiles)
(guix utils)
(git)
(gnu packages base)
@@ -64,19 +62,11 @@
(or (getenv "GUIX_MANUAL")
"guix"))
(define %manual-languages
;; Available translations for the 'guix-manual' text domain.
'("de" "en" "es" "fr" "pt_BR" "ru" "zh_CN"))
(define %cookbook-languages
;; Available translations for the 'guix-cookbook' text domain.
'("de" "en" "fr" "sk"))
(define %languages
;; Available translations for the document being built.
;; The cookbook is not translated in the same languages as the manual
(if (string=? %manual "guix-cookbook")
%cookbook-languages
%manual-languages))
'("de" "en" "fr" "sk")
'("de" "en" "es" "fr" "ru" "zh_CN")))
(define (texinfo-manual-images source)
"Return a directory containing all the images used by the user manual, taken
@@ -284,9 +274,6 @@ actual file name."
(loop rest))
((('strong _ ...) _ ...)
#t)
((('span ('@ ('class "category")) ;raw Texinfo 6.8
(? string-or-entity?) ...) rest ...)
#t)
((('span ('@ ('class "symbol-definition-category"))
(? string-or-entity?) ...) rest ...)
#t)
@@ -314,9 +301,8 @@ actual file name."
(define (html-files directory)
;; Return the list of HTML files under DIRECTORY.
(map (cut string-append directory "/" <>)
(or (scandir #$manual (lambda (file)
(string-suffix? ".html" file)))
'())))
(scandir #$manual (lambda (file)
(string-suffix? ".html" file)))))
(define anchors
(sort (concatenate
@@ -510,16 +496,10 @@ its <pre class=\"lisp\"> blocks (as produced by 'makeinfo --html')."
;; Replace the ugly <strong> used for @deffn etc., which
;; translate to <dt>, with more stylable markup.
(('dt ('@ ('id id)) ;raw Texinfo 6.8
('span ('@ ('class "category")) category ...)
('span ('strong thing)
anchor))
(('dt (@ ('id id)) category ... ('strong thing))
(highlight-definition id category thing '()))
(('dt (@ ('id id))
('span ('@ ('class "category")) category ...)
('span ('strong thing)
(? space?) ('em args ...)
anchor))
(('dt (@ ('id id)) category ... ('strong thing)
(? space?) ('em args ...))
(highlight-definition id category thing args))
((tag ('@ attributes ...) body ...)
@@ -901,19 +881,14 @@ makeinfo OPTIONS."
#:languages languages
#:date date))
(define texinfo-profile
(profile
(content (packages->manifest
;; texi2dvi requires various command line tools.
(list coreutils
diffutils
gawk
grep
sed
tar
texinfo
(texlive-updmap.cfg
(list texlive-epsf texlive-texinfo)))))))
;; FIXME: This union works, except for the table of contents of non-English
;; manuals, which contains escape sequences like "^^ca^^fe" instead of
;; accented letters.
;;
;; (define texlive
;; (texlive-updmap.cfg (list texlive-tex-texinfo
;; texlive-generic-epsf
;; texlive-fonts-ec)))
(define build
(with-imported-modules '((guix build utils))
@@ -930,12 +905,21 @@ makeinfo OPTIONS."
(string-downcase language)))
;; Install a UTF-8 locale so that 'makeinfo' is at ease.
(setenv "GUIX_LOCPATH" #+(file-append glibc-utf8-locales
"/lib/locale"))
(setenv "GUIX_LOCPATH"
#+(file-append glibc-utf8-locales "/lib/locale"))
(setenv "LC_ALL" "en_US.utf8")
(setenv "PATH" #+(file-append texinfo-profile "/bin"))
(setenv "GUIX_TEXMF" #+(file-append texinfo-profile
"/share/texmf-dist"))
(setenv "PATH"
(string-append #+(file-append texlive "/bin") ":"
#+(file-append texinfo "/bin") ":"
;; Below are command-line tools needed by
;; 'texi2dvi' and friends.
#+(file-append sed "/bin") ":"
#+(file-append grep "/bin") ":"
#+(file-append coreutils "/bin") ":"
#+(file-append gawk "/bin") ":"
#+(file-append tar "/bin") ":"
#+(file-append diffutils "/bin")))
(setvbuf (current-output-port) 'line)
(setvbuf (current-error-port) 'line)
@@ -985,8 +969,7 @@ PDF for language '~a'!~%~%"
(computed-file (string-append manual "-pdf-manual") build
#:local-build? #f))
(define* (guix-manual-text-domain source
#:optional (languages %manual-languages))
(define (guix-manual-text-domain source languages)
"Return the PO files for LANGUAGES of the 'guix-manual' text domain taken
from SOURCE."
(define po-directory
@@ -1059,7 +1042,9 @@ must be the Guix top-level source directory, from which PO files are taken."
(define exp
`(begin
(bindtextdomain "guix-manual"
#+(guix-manual-text-domain source))
#+(guix-manual-text-domain
source
languages))
(bindtextdomain "iso_639-3" ;language names
#+(file-append iso-codes
"/share/locale"))
+172 -596
View File
@@ -26,10 +26,9 @@ choice.
* Packaging Guidelines:: Growing the distribution.
* Coding Style:: Hygiene of the contributor.
* Submitting Patches:: Share your work.
* Tracking Bugs and Changes:: Keeping it all organized.
* Tracking Bugs and Patches:: Keeping it all organized.
* Commit Access:: Pushing to the official repository.
* Updating the Guix Package:: Updating the Guix package definition.
* Writing Documentation:: Improving documentation in GNU Guix.
* Translating Guix:: Make Guix speak your native language.
@end menu
@@ -130,16 +129,14 @@ more information.
Then, run:
@example
./configure --localstatedir=/var --sysconfdir=/etc
./configure --localstatedir=/var
@end example
@noindent
... where @file{/var} is the normal @code{localstatedir} value
(@pxref{The Store}, for information about this) and @file{/etc} is the
normal @code{sysconfdir} value. Note that you will probably not run
@command{make install} at the end (you don't have to) but it's still
important to pass the right @code{localstatedir} and @code{sysconfdir}
values, which get recorded in the @code{(guix config)} Guile module.
(@pxref{The Store}, for information about this). Note that you will
probably not run @command{make install} at the end (you don't have to)
but it's still important to pass the right @code{localstatedir}.
Finally, you can build Guix and, if you feel so inclined, run the tests
(@pxref{Running the Test Suite}):
@@ -227,7 +224,8 @@ $ ./pre-inst-env guile -c '(use-modules (guix utils)) (pk (%current-system))'
@noindent
@cindex REPL
@cindex read-eval-print loop
@dots{} and for a REPL (@pxref{Using Guix Interactively}):
@dots{} and for a REPL (@pxref{Using Guile Interactively,,, guile, Guile
Reference Manual}):
@example
$ ./pre-inst-env guile
@@ -280,8 +278,8 @@ prepared Guile object (@file{.go}) files.
You can run @command{make} automatically as you work using
@command{watchexec} from the @code{watchexec} package. For example,
to build again each time you update a package file, run
@samp{watchexec -w gnu/packages -- make -j4}.
to build again each time you update a package file, you can run
@samp{watchexec -w gnu/packages make -j4}.
@node The Perfect Setup
@section The Perfect Setup
@@ -293,17 +291,22 @@ Manual}). First, you need more than an editor, you need
wonderful @url{https://nongnu.org/geiser/, Geiser}. To set that up, run:
@example
guix install emacs guile emacs-geiser emacs-geiser-guile
guix package -i emacs guile emacs-geiser emacs-geiser-guile
@end example
Geiser allows for interactive and incremental development from within
Emacs: code compilation and evaluation from within buffers, access to
on-line documentation (docstrings), context-sensitive completion,
@kbd{M-.} to jump to an object definition, a REPL to try out your code,
and more (@pxref{Introduction,,, geiser, Geiser User Manual}). If you
allow Emacs to load the @file{.dir-locals.el} file at the root of the
project checkout, it will cause Geiser to automatically add the local
Guix sources to the Guile load path.
and more (@pxref{Introduction,,, geiser, Geiser User Manual}). For
convenient Guix development, make sure to augment Guiles load path so
that it finds source files from your checkout:
@lisp
;; @r{Assuming the Guix checkout is in ~/src/guix.}
(with-eval-after-load 'geiser-guile
(add-to-list 'geiser-guile-load-path "~/src/guix"))
@end lisp
To actually edit the code, Emacs already has a neat Scheme mode. But in
addition to that, you must not miss
@@ -317,25 +320,15 @@ s-expression, etc.
@cindex reducing boilerplate
We also provide templates for common git commit messages and package
definitions in the @file{etc/snippets} directory. These templates can
be used to expand short trigger strings to interactive text snippets. If
you use @url{https://joaotavora.github.io/yasnippet/, YASnippet}, you
may want to add the @file{etc/snippets/yas} snippets directory to the
@var{yas-snippet-dirs} variable. If you use
@url{https://github.com/minad/tempel/, Tempel}, you may want to add the
@file{etc/snippets/tempel/*} path to the @var{tempel-path} variable in
be used with @url{https://joaotavora.github.io/yasnippet/, YASnippet} to
expand short trigger strings to interactive text snippets. You may want
to add the snippets directory to the @var{yas-snippet-dirs} variable in
Emacs.
@lisp
;; @r{Assuming the Guix checkout is in ~/src/guix.}
;; @r{Yasnippet configuration}
(with-eval-after-load 'yasnippet
(add-to-list 'yas-snippet-dirs "~/src/guix/etc/snippets/yas"))
;; @r{Tempel configuration}
(with-eval-after-load 'tempel
;; Ensure tempel-path is a list -- it may also be a string.
(unless (listp 'tempel-path)
(setq tempel-path (list tempel-path)))
(add-to-list 'tempel-path "~/src/guix/etc/snippets/tempel/*"))
(add-to-list 'yas-snippet-dirs "~/src/guix/etc/snippets"))
@end lisp
The commit message snippets depend on @url{https://magit.vc/, Magit} to
@@ -454,7 +447,6 @@ needed is to review and apply the patch.
* Perl Modules:: Little pearls.
* Java Packages:: Coffee break.
* Rust Crates:: Beware of oxidation.
* Elm Packages:: Trees of browser code
* Fonts:: Fond of fonts.
@end menu
@@ -612,7 +604,7 @@ A typical package definition may look like this:
)))
@end lisp
@deffn {Procedure} git-version @var{VERSION} @var{REVISION} @var{COMMIT}
@deffn {Scheme Procedure} git-version @var{VERSION} @var{REVISION} @var{COMMIT}
Return the version string for packages using @code{git-fetch}.
@lisp
@@ -621,7 +613,7 @@ Return the version string for packages using @code{git-fetch}.
@end lisp
@end deffn
@deffn {Procedure} hg-version @var{VERSION} @var{REVISION} @var{CHANGESET}
@deffn {Scheme Procedure} hg-version @var{VERSION} @var{REVISION} @var{CHANGESET}
Return the version string for packages using @code{hg-fetch}. It works
in the same way as @code{git-version}.
@end deffn
@@ -671,7 +663,7 @@ hyperlinks (@pxref{Overview,,, texinfo, GNU Texinfo}). However you
should be careful when using some characters for example @samp{@@} and
curly braces which are the basic special characters in Texinfo
(@pxref{Special Characters,,, texinfo, GNU Texinfo}). User interfaces
such as @command{guix show} take care of rendering it
such as @command{guix package --show} take care of rendering it
appropriately.
Synopses and descriptions are translated by volunteers
@@ -773,8 +765,9 @@ the word @code{python}.
Some modules are compatible with only one version of Python, others with
both. If the package Foo is compiled with Python 3, we name it
@code{python-foo}. If it is compiled with Python 2, we name it
@code{python2-foo}. Python 2 packages are being removed from the
distribution; please do no not submit any new Python 2 packages.
@code{python2-foo}. Packages should be added when they are necessary;
we don't add Python 2 variants of the package unless we are going to use
them.
If a project already contains the word @code{python}, we drop this;
for instance, the module python-dateutil is packaged under the names
@@ -782,29 +775,12 @@ for instance, the module python-dateutil is packaged under the names
starts with @code{py} (e.g.@: @code{pytz}), we keep it and prefix it as
described above.
@quotation Note
Currently there are two different build systems for Python packages in Guix:
@var{python-build-system} and @var{pyproject-build-system}. For the
longest time, Python packages were built from an informally specified
@file{setup.py} file. That worked amazingly well, considering Python's
success, but was difficult to build tooling around. As a result, a host
of alternative build systems emerged and the community eventually settled on a
@url{https://peps.python.org/pep-0517/, formal standard} for specifying build
requirements. @var{pyproject-build-system} is Guix's implementation of this
standard. It is considered ``experimental'' in that it does not yet support
all the various PEP-517 @emph{build backends}, but you are encouraged to try
it for new Python packages and report any problems. It will eventually be
deprecated and merged into @var{python-build-system}.
@end quotation
@subsubsection Specifying Dependencies
@cindex inputs, for Python packages
Dependency information for Python packages is usually available in the
package source tree, with varying degrees of accuracy: in the
@file{pyproject.toml} file, the @file{setup.py} file, in
@file{requirements.txt}, or in @file{tox.ini} (the latter mostly for
test dependencies).
@file{setup.py} file, in @file{requirements.txt}, or in @file{tox.ini}.
Your mission, when writing a recipe for a Python package, is to map
these dependencies to the appropriate type of ``input'' (@pxref{package
@@ -815,12 +791,10 @@ following check list to determine which dependency goes where.
@itemize
@item
We currently package Python with @code{setuptools} and @code{pip}
installed per default. This is about to change, and users are encouraged
to use @code{python-toolchain} if they want a build environment for Python.
@command{guix lint} will warn if @code{setuptools} or @code{pip} are
added as native-inputs because they are generally not necessary.
We currently package Python 2 with @code{setuptools} and @code{pip}
installed like Python 3.4 has per default. Thus you don't need to
specify either of these as an input. @command{guix lint} will warn you
if you do.
@item
Python dependencies required at run time go into
@@ -829,10 +803,9 @@ Python dependencies required at run time go into
@file{requirements.txt} file.
@item
Python packages required only at build time---e.g., those listed under
@code{build-system.requires} in @file{pyproject.toml} or with the
@code{setup_requires} keyword in @file{setup.py}---or dependencies only
for testing---e.g., those in @code{tests_require} or @file{tox.ini}---go into
Python packages required only at build time---e.g., those listed with
the @code{setup_requires} keyword in @file{setup.py}---or only for
testing---e.g., those in @code{tests_require}---go into
@code{native-inputs}. The rationale is that (1) they do not need to be
propagated because they are not needed at run time, and (2) in a
cross-compilation context, it's the ``native'' input that we'd want.
@@ -925,87 +898,6 @@ developed for a different Operating System, depend on features from the Nightly
Rust compiler, or the test suite may have atrophied since it was released.
@node Elm Packages
@subsection Elm Packages
@cindex Elm
Elm applications can be named like other software: their names need not
mention Elm.
Packages in the Elm sense (see @code{elm-build-system} under @ref{Build
Systems}) are required use names of the format
@var{author}@code{/}@var{project}, where both the @var{author} and the
@var{project} may contain hyphens internally, and the @var{author} sometimes
contains uppercase letters.
To form the Guix package name from the upstream name, we follow a convention
similar to Python packages (@pxref{Python Modules}), adding an @code{elm-}
prefix unless the name would already begin with @code{elm-}.
In many cases we can reconstruct an Elm package's upstream name heuristically,
but, since conversion to a Guix-style name involves a loss of information,
this is not always possible. Care should be taken to add the
@code{'upstream-name} property when necessary so that @samp{guix import elm}
will work correctly (@pxref{Invoking guix import}). The most notable scenarios
when explicitly specifying the upstream name is necessary are:
@enumerate
@item
When the @var{author} is @code{elm} and the @var{project} contains one or more
hyphens, as with @code{elm/virtual-dom}; and
@item
When the @var{author} contains hyphens or uppercase letters, as with
@code{Elm-Canvas/raster-shapes}---unless the @var{author} is
@code{elm-explorations}, which is handled as a special case, so packages like
@code{elm-explorations/markdown} do @emph{not} need to use the
@code{'upstream-name} property.
@end enumerate
The module @code{(guix build-system elm)} provides the following utilities for
working with names and related conventions:
@deffn {Procedure} elm-package-origin @var{elm-name} @var{version} @
@var{hash}
Returns a Git origin using the repository naming and tagging regime required
for a published Elm package with the upstream name @var{elm-name} at version
@var{version} with sha256 checksum @var{hash}.
For example:
@lisp
(package
(name "elm-html")
(version "1.0.0")
(source
(elm-package-origin
"elm/html"
version
(base32 "15k1679ja57vvlpinpv06znmrxy09lbhzfkzdc89i01qa8c4gb4a")))
...)
@end lisp
@end deffn
@deffn {Procedure} elm->package-name @var{elm-name}
Returns the Guix-style package name for an Elm package with upstream name
@var{elm-name}.
Note that there is more than one possible @var{elm-name} for which
@code{elm->package-name} will produce a given result.
@end deffn
@deffn {Procedure} guix-package->elm-name @var{package}
Given an Elm @var{package}, returns the possibly-inferred upstream name, or
@code{#f} the upstream name is not specified via the @code{'upstream-name}
property and can not be inferred by @code{infer-elm-package-name}.
@end deffn
@deffn {Procedure} infer-elm-package-name @var{guix-name}
Given the @var{guix-name} of an Elm package, returns the inferred upstream
name, or @code{#f} if the upstream name can't be inferred. If the result is
not @code{#f}, supplying it to @code{elm->package-name} would produce
@var{guix-name}.
@end deffn
@node Fonts
@subsection Fonts
@@ -1085,16 +977,11 @@ and then to browse them ``by hand'' using @code{car}, @code{cdr},
notably the fact that it is hard to read, error-prone, and a hindrance
to proper type error reports.
@findex define-record-type*
@findex match-record
@cindex pattern matching
Guix code should define appropriate data types (for instance, using
@code{define-record-type*}) rather than abuse lists. In addition, it
should use pattern matching, via Guiles @code{(ice-9 match)} module,
especially when matching lists (@pxref{Pattern Matching,,, guile, GNU
Guile Reference Manual}); pattern matching for records is better done
using @code{match-record} from @code{(guix records)}, which, unlike
@code{match}, verifies field names at macro-expansion time.
Guile Reference Manual}).
@node Formatting Code
@subsection Formatting Code
@@ -1149,37 +1036,36 @@ Development is done using the Git distributed version control system.
Thus, access to the repository is not strictly necessary. We welcome
contributions in the form of patches as produced by @code{git
format-patch} sent to the @email{guix-patches@@gnu.org} mailing list
(@pxref{Submitting patches to a project,,, git, Git User Manual}).
Contributors are encouraged to take a moment to set some Git repository
options (@pxref{Configuring Git}) first, which can improve the
readability of patches. Seasoned Guix developers may also want to look
at the section on commit access (@pxref{Commit Access}).
(@pxref{submitting patches,, Submitting patches to a project, git, Git
User Manual}). Contributors are encouraged to take a moment to set some
Git repository options (@pxref{Configuring Git}) first, which can
improve the readability of patches. Seasoned Guix developers may also
want to look at the section on commit access (@pxref{Commit Access}).
This mailing list is backed by a Debbugs instance, which allows us to
keep track of submissions (@pxref{Tracking Bugs and Changes}).
Each message sent to that mailing list gets a new tracking number
assigned; people can then follow up on the submission by sending email
to @code{@var{ISSUE_NUMBER}@@debbugs.gnu.org}, where @var{ISSUE_NUMBER}
is the tracking number (@pxref{Sending a Patch Series}).
keep track of submissions (@pxref{Tracking Bugs and Patches}). Each
message sent to that mailing list gets a new tracking number assigned;
people can then follow up on the submission by sending email to
@code{@var{NNN}@@debbugs.gnu.org}, where @var{NNN} is the tracking
number (@pxref{Sending a Patch Series}).
Please write commit logs in the ChangeLog format (@pxref{Change Logs,,,
standards, GNU Coding Standards}); you can check the commit history for
examples.
You can help make the review process more efficient, and increase the
chance that your patch will be reviewed quickly, by describing the
context of your patch and the impact you expect it to have. For
example, if your patch is fixing something that is broken, describe the
problem and how your patch fixes it. Tell us how you have tested your
patch. Will users of the code changed by your patch have to adjust
their workflow at all? If so, tell us how. In general, try to imagine
what questions a reviewer will ask, and answer those questions in
advance.
Before submitting a patch that adds or modifies a package definition,
please run through this check list:
@enumerate
@cindex @code{git format-patch}
@cindex @code{git-format-patch}
@item
When generating your patches with @code{git format-patch} or @code{git
send-email}, we recommend using the option @code{--base=}, perhaps with
the value @code{auto}. This option adds a note to the patch stating
which commit the patch is based on. This helps reviewers understand how
to apply and review your patches.
@item
If the authors of the packaged software provide a cryptographic
signature for the release tarball, make an effort to verify the
@@ -1247,14 +1133,53 @@ Take a look at the profile reported by @command{guix size}
(@pxref{Invoking guix size}). This will allow you to notice references
to other packages unwillingly retained. It may also help determine
whether to split the package (@pxref{Packages with Multiple Outputs}),
and which optional dependencies should be used. In particular, avoid
adding @code{texlive} as a dependency: because of its extreme size, use
@code{texlive-updmap.cfg} procedure instead.
and which optional dependencies should be used. In particular, avoid adding
@code{texlive} as a dependency: because of its extreme size, use
the @code{texlive-tiny} package or @code{texlive-union} procedure instead.
@item
Check that dependent packages (if applicable) are not affected by the
change; @code{guix refresh --list-dependent @var{package}} will help you
do that (@pxref{Invoking guix refresh}).
For important changes, check that dependent packages (if applicable) are
not affected by the change; @code{guix refresh --list-dependent
@var{package}} will help you do that (@pxref{Invoking guix refresh}).
@c See <https://lists.gnu.org/archive/html/guix-devel/2016-10/msg00933.html>.
@cindex branching strategy
@cindex rebuild scheduling strategy
Depending on the number of dependent packages and thus the amount of
rebuilding induced, commits go to different branches, along these lines:
@table @asis
@item 300 dependent packages or less
@code{master} branch (non-disruptive changes).
@item between 300 and 1,800 dependent packages
@code{staging} branch (non-disruptive changes). This branch is intended
to be merged in @code{master} every 6 weeks or so. Topical changes
(e.g., an update of the GNOME stack) can instead go to a specific branch
(say, @code{gnome-updates}). This branch is not expected to be
buildable or usable until late in its development process.
@item more than 1,800 dependent packages
@code{core-updates} branch (may include major and potentially disruptive
changes). This branch is intended to be merged in @code{master} every
6 months or so. This branch is not expected to be buildable or usable
until late in its development process.
@end table
All these branches are @uref{https://@value{SUBSTITUTE-SERVER-1},
tracked by our build farm} and merged into @code{master} once
everything has been successfully built. This allows us to fix issues
before they hit users, and to reduce the window during which pre-built
binaries are not available.
When we decide to start building the @code{staging} or
@code{core-updates} branches, they will be forked and renamed with the
suffix @code{-frozen}, at which time only bug fixes may be pushed to the
frozen branches. The @code{core-updates} and @code{staging} branches
will remain open to accept patches for the next cycle. Please ask on
the mailing list or IRC if unsure where to place a patch.
@c TODO: It would be good with badges on the website that tracks these
@c branches. Or maybe even a status page.
@item
@cindex determinism, of build processes
@@ -1324,13 +1249,12 @@ guix pull --url=/path/to/your/checkout --profile=/tmp/guix.master
When posting a patch to the mailing list, use @samp{[PATCH] @dots{}} as
a subject, if your patch is to be applied on a branch other than
@code{master}, say @code{core-updates}, specify it in the subject like
@samp{[PATCH core-updates] @dots{}}.
You may use your email client or the @command{git send-email} command
(@pxref{Sending a Patch Series}). We prefer to get patches in plain
text messages, either inline or as MIME attachments. You are advised to
pay attention if your email client changes anything like line breaks or
indentation which could potentially break the patches.
@samp{[PATCH core-updates] @dots{}}. You may use your email client or
the @command{git send-email} command (@pxref{Sending a Patch Series}).
We prefer to get patches in plain text messages, either inline or as
MIME attachments. You are advised to pay attention if your email client
changes anything like line breaks or indentation which could potentially
break the patches.
Expect some delay when you submit your very first patch to
@email{guix-patches@@gnu.org}. You have to wait until you get an
@@ -1338,13 +1262,7 @@ acknowledgement with the assigned tracking number. Future acknowledgements
should not be delayed.
When a bug is resolved, please close the thread by sending an email to
@email{@var{ISSUE_NUMBER}-done@@debbugs.gnu.org}.
@menu
* Configuring Git::
* Sending a Patch Series::
* Teams::
@end menu
@email{@var{NNN}-done@@debbugs.gnu.org}.
@node Configuring Git
@subsection Configuring Git
@@ -1359,192 +1277,51 @@ different name or email just for commits in this repository, you can
use @command{git config --local}, or edit @file{.git/config} in the
repository instead of @file{~/.gitconfig}.
Other important Git configuration will automatically be configured when
building the project (@pxref{Building from Git}).
We provide some default settings in @file{etc/git/gitconfig} which
modify how patches are generated, making them easier to read and apply.
These settings can be applied by manually copying them to
@file{.git/config} in your checkout, or by telling Git to include the
whole file:
@node Sending a Patch Series
@subsection Sending a Patch Series
@example
git config --local include.path ../etc/git/gitconfig
@end example
From then on, any changes to @file{etc/git/gitconfig} would
automatically take effect.
Since the first patch in a series must be sent separately
(@pxref{Sending a Patch Series}), it can also be helpful to tell
@command{git format-patch} to handle the e-mail threading instead of
@command{git send-email}:
@example
git config --local format.thread shallow
git config --local sendemail.thread no
@end example
@unnumberedsubsec Sending a Patch Series
@anchor{Sending a Patch Series}
@cindex patch series
@cindex @code{git send-email}
@cindex @code{git format-patch}
@unnumberedsubsubsec Single Patches
@anchor{Single Patches}
The @command{git send-email} command is the best way to send both single
patches and patch series (@pxref{Multiple Patches}) to the Guix mailing
list. Sending patches as email attachments may make them difficult to
review in some mail clients, and @command{git diff} does not store commit
metadata.
When sending a patch series (e.g., using @code{git send-email}), please
first send one message to @email{guix-patches@@gnu.org}, and then send
subsequent patches to @email{@var{NNN}@@debbugs.gnu.org} to make sure
they are kept together. See
@uref{https://debbugs.gnu.org/Advanced.html, the Debbugs documentation}
for more information. You can install @command{git send-email} with
@command{guix install git:send-email}.
@c Debbugs bug: https://debbugs.gnu.org/db/15/15361.html
@quotation Note
The @command{git send-email} command is provided by the @code{send-email}
output of the @code{git} package, i.e. @code{git:send-email}.
@end quotation
@node Tracking Bugs and Patches
@section Tracking Bugs and Patches
The following command will create a patch email from the latest commit,
open it in your @var{EDITOR} or @var{VISUAL} for editing, and send it to
the Guix mailing list to be reviewed and merged. Assuming you have
already configured Git according to @xref{Configuring Git}, you can
simply use:
@example
$ git send-email --annotate -1
@end example
@quotation Tip
To add a prefix to the subject of your patch, you may use the
@option{--subject-prefix} option. The Guix project uses this to
specify that the patch is intended for a branch or repository
other than the @code{master} branch of
@url{https://git.savannah.gnu.org/cgit/guix.git}.
@example
git send-email --annotate --subject-prefix='PATCH core-updates' -1
@end example
@end quotation
The patch email contains a three-dash separator line after the commit
message. You may ``annotate'' the patch with explanatory text by adding
it under this line. If you do not wish to annotate the email, you may
drop the @option{--annotate} option.
If you need to send a revised patch, don't resend it like this or send
a ``fix'' patch to be applied on top of the last one; instead, use
@command{git commit --amend} or @url{https://git-rebase.io,
@command{git rebase}} to modify the commit, and use the
@email{@var{ISSUE_NUMBER}@@debbugs.gnu.org} address and the @option{-v}
flag with @command{git send-email}.
@example
$ git commit --amend
$ git send-email --annotate -v@var{REVISION} \
--to=@var{ISSUE_NUMBER}@@debbugs.gnu.org -1
@end example
@quotation Note
Due to an apparent bug in @command{git send-email},
@option{-v @var{REVISION}} (with the space) will not work; you
@emph{must} use @option{-v@var{REVISION}}.
@end quotation
You can find out @var{ISSUE_NUMBER} either by searching on the mumi
interface at @url{https://issues.guix.gnu.org} for the name of your patch or
reading the acknowledgement email sent automatically by Debbugs in
reply to incoming bugs and patches, which contains the bug number.
@unnumberedsubsubsec Notifying Teams
@anchor{Notifying Teams}
@cindex teams
If your git checkout has been correctly configured (@pxref{Configuring
Git}), the @command{git send-email} command will automatically notify
the appropriate team members, based on the scope of your changes. This
relies on the @file{etc/teams.scm} script, which can also be invoked
manually if you do not use the preferred @command{git send-email}
command to submit patches. To list the available actions of the script,
you can invoke it via the @command{etc/teams.scm help} command. For
more information regarding teams, see @xref{Teams}.
@unnumberedsubsubsec Multiple Patches
@anchor{Multiple Patches}
@cindex cover letter
While @command{git send-email} alone will suffice for a single
patch, an unfortunate flaw in Debbugs means you need to be more
careful when sending multiple patches: if you send them all to the
@email{guix-patches@@gnu.org} address, a new issue will be created
for each patch!
When sending a series of patches, it's best to send a Git ``cover
letter'' first, to give reviewers an overview of the patch series.
We can create a directory called @file{outgoing} containing both
our patch series and a cover letter called @file{0000-cover-letter.patch}
with @command{git format-patch}.
@example
$ git format-patch -@var{NUMBER_COMMITS} -o outgoing \
--cover-letter --base=auto
@end example
We can now send @emph{just} the cover letter to the
@email{guix-patches@@gnu.org} address, which will create an issue
that we can send the rest of the patches to.
@example
$ git send-email outgoing/0000-cover-letter.patch --annotate
$ rm outgoing/0000-cover-letter.patch # we don't want to resend it!
@end example
Ensure you edit the email to add an appropriate subject line and
blurb before sending it. Note the automatically generated shortlog
and diffstat below the blurb.
Once the Debbugs mailer has replied to your cover letter email, you
can send the actual patches to the newly-created issue address.
@example
$ git send-email outgoing/*.patch --to=@var{ISSUE_NUMBER}@@debbugs.gnu.org
$ rm -rf outgoing # we don't need these anymore
@end example
Thankfully, this @command{git format-patch} dance is not necessary
to send an amended patch series, since an issue already exists for
the patchset.
@example
$ git send-email -@var{NUMBER_COMMITS} -v@var{REVISION} \
--to=@var{ISSUE_NUMBER}@@debbugs.gnu.org
@end example
If need be, you may use @option{--cover-letter --annotate} to send
another cover letter, e.g. for explaining what's changed since the last
revision, and these changes are necessary.
@node Teams
@subsection Teams
@cindex teams
There are several teams mentoring different parts of the Guix source
code. To list all those teams, you can run from a Guix checkout:
@example
$ ./etc/teams.scm list-teams
id: mentors
name: Mentors
description: A group of mentors who chaperone contributions by newcomers.
members:
+ Christopher Baines <mail@@cbaines.net>
+ Ricardo Wurmus <rekado@@elephly.net>
+ Mathieu Othacehe <othacehe@@gnu.org>
+ jgart <jgart@@dismail.de>
+ Ludovic Courtès <ludo@@gnu.org>
@dots{}
@end example
You can run the following command to have the @code{Mentors} team put in
CC of a patch series:
@example
$ git send-email --to=@var{ISSUE_NUMBER}@@debbugs.gnu.org \
--header-cmd='etc/teams.scm cc-mentors-header-cmd' *.patch
@end example
The appropriate team or teams can also be inferred from the modified
files. For instance, if you want to send the two latest commits of the
current Git repository to review, you can run:
@example
$ guix shell -D guix
[env]$ git send-email --to=@var{ISSUE_NUMBER}@@debbugs.gnu.org -2
@end example
@node Tracking Bugs and Changes
@section Tracking Bugs and Changes
This section describes how the Guix project tracks its bug reports,
patch submissions and topic branches.
This section describes how the Guix project tracks its bug reports and
patch submissions.
@menu
* The Issue Tracker:: The official bug and patch tracker.
* Managing Patches and Branches:: How changes to Guix are managed.
* Debbugs User Interfaces:: Ways to interact with Debbugs.
* Debbugs Usertags:: Tag reports with custom labels.
@end menu
@@ -1563,71 +1340,9 @@ email to @email{bug-guix@@gnu.org}, while patch submissions are filed
against the @code{guix-patches} package by sending email to
@email{guix-patches@@gnu.org} (@pxref{Submitting Patches}).
@node Managing Patches and Branches
@subsection Managing Patches and Branches
@cindex branching strategy
@cindex rebuild scheduling strategy
Changes should be posted to @email{guix-patches@@gnu.org}. This mailing
list fills the patch-tracking database (@pxref{The Issue Tracker}). It
also allows patches to be picked up and tested by the quality assurance
tooling; the result of that testing eventually shows up on the dashboard
at @indicateurl{https://qa.guix.gnu.org/issue/@var{ISSUE_NUMBER}}, where
@var{ISSUE_NUMBER} is the number assigned by the issue tracker. Leave
time for a review, without committing anything.
As an exception, some changes considered ``trivial'' or ``obvious'' may
be pushed directly to the @code{master} branch. This includes changes
to fix typos and reverting commits that caused immediate problems. This
is subject to being adjusted, allowing individuals to commit directly on
non-controversial changes on parts theyre familiar with.
Changes which affect more than 300 dependent packages (@pxref{Invoking
guix refresh}) should first be pushed to a topic branch other than
@code{master}; the set of changes should be consistent---e.g., ``GNOME
update'', ``NumPy update'', etc. This allows for testing: the branch
will automatically show up at
@indicateurl{https://qa.guix.gnu.org/branch/@var{branch}}, with an
indication of its build status on various platforms.
@cindex feature branches, coordination
To help coordinate the merging of branches, you must create a new
guix-patches issue each time you wish to merge a branch (@pxref{The
Issue Tracker}). The title of the issue requesting to merge a branch
should have the following format:
@cindex merge requests, template
@example
Request for merging "@var{name}" branch
@end example
The @url{https://qa.guix.gnu.org/, QA infrastructure} recognizes such
issues and lists the merge requests on its main page. Normally branches
will be merged in a ``first come, first merged'' manner, tracked through
the guix-patches issues.
If you agree on a different order with those involved, you can track
this by updating which issues block@footnote{You can mark an issue as
blocked by another by emailing @email{control@@debbugs.gnu.org} with the
following line in the body of the email: @code{block XXXXX by YYYYY}.
Where @code{XXXXX} is the number for the blocked issue, and @code{YYYYY}
is the number for the issue blocking it.} which other issues.
Therefore, to know which branch is at the front of the queue, look for
the oldest issue, or the issue that isn't @dfn{blocked} by any other
branch merges. An ordered list of branches with the open issues is
available at @url{https://qa.guix.gnu.org}.
Once a branch is at the front of the queue, wait until sufficient time
has passed for the build farms to have processed the changes, and for
the necessary testing to have happened. For example, you can check
@indicateurl{https://qa.guix.gnu.org/branch/@var{branch}} to see
information on some builds and substitute availability.
@node Debbugs User Interfaces
@subsection Debbugs User Interfaces
@subsubsection Web interface
A web interface (actually @emph{two} web interfaces!) are available to
browse issues:
@@ -1649,88 +1364,6 @@ To view discussions related to issue number @var{n}, go to
@indicateurl{https://issues.guix.gnu.org/@var{n}} or
@indicateurl{https://bugs.gnu.org/@var{n}}.
@subsubsection Command-line interface
Mumi also comes with a command-line interface that can be used to search
existing issues, open new issues and send patches. You do not need to
use Emacs to use the mumi command-line client. You interact with it
only on the command-line.
To use the mumi command-line interface, navigate to a local clone of the
Guix git repository, and drop into a shell with mumi, git and
git:send-email installed.
@example
$ cd guix
~/guix$ guix shell mumi git git:send-email
@end example
To search for issues, say all open issues about "zig", run
@example
~/guix [env]$ mumi search zig is:open
#60889 Add zig-build-system
opened on 17 Jan 17:37 Z by Ekaitz Zarraga
#61036 [PATCH 0/3] Update zig to 0.10.1
opened on 24 Jan 09:42 Z by Efraim Flashner
#39136 [PATCH] gnu: services: Add endlessh.
opened on 14 Jan 2020 21:21 by Nicol? Balzarotti
#60424 [PATCH] gnu: Add python-online-judge-tools
opened on 30 Dec 2022 07:03 by gemmaro
#45601 [PATCH 0/6] vlang 0.2 update
opened on 1 Jan 2021 19:23 by Ryan Prior
@end example
Pick an issue and make it the "current" issue.
@example
~/guix [env]$ mumi current 61036
#61036 [PATCH 0/3] Update zig to 0.10.1
opened on 24 Jan 09:42 Z by Efraim Flashner
@end example
Once an issue is the current issue, you can easily create and send
patches to it using
@example
~/guix [env]$ git format-patch origin/master
~/guix [env]$ mumi send-email foo.patch bar.patch
@end example
Note that you do not have to pass in @samp{--to} or @samp{--cc}
arguments to @command{git format-patch}. @command{mumi send-email} will
put them in correctly when sending the patches.
To open a new issue, run
@example
~/guix [env]$ mumi new
@end example
and send patches
@example
~/guix [env]$ mumi send-email foo.patch bar.patch
@end example
@command{mumi send-email} is really a wrapper around @command{git
send-email} that automates away all the nitty-gritty of sending patches.
It uses the current issue state to automatically figure out the correct
@samp{To} address to send to, other participants to @samp{Cc}, headers
to add, etc.
Also note that, unlike @command{git send-email}, @command{mumi
send-email} works perfectly well with single and multiple patches alike.
It automates away the debbugs dance of sending the first patch, waiting
for a response from debbugs and sending the remaining patches. It does
so by sending the first patch, polling the server for a response, and
then sending the remaining patches. This polling can unfortunately take
a few minutes. So, please be patient.
@subsubsection Emacs interface
If you use Emacs, you may find it more convenient to interact with
issues using @file{debbugs.el}, which you can install with:
@@ -1809,12 +1442,7 @@ project for at least 6 months. This ensures enough interactions with
the contributor, which is essential for mentoring and assessing whether
they are ready to become a committer. Commit access should not be
thought of as a ``badge of honor'' but rather as a responsibility a
contributor is willing to take to help the project. It is expected from
all contributors, and even more so from committers, to help build
consensus and make decisions based on consensus. To learn what
consensus decision making means and understand its finer details, you
are encouraged to read
@url{https://www.seedsforchange.org.uk/consensus}.
contributor is willing to take to help the project.
The following sections explain how to get commit access, how to be ready
to push commits, and the policies and community expectations for commits
@@ -1907,30 +1535,33 @@ git config commit.gpgsign true
git config user.signingkey CABBA6EA1DC0FF33
@end example
To check that commits are signed with correct key, use:
You can prevent yourself from accidentally pushing unsigned commits to
Savannah by using the pre-push Git hook located at
@file{etc/git/pre-push}:
@example
make authenticate
cp etc/git/pre-push .git/hooks/pre-push
@end example
To avoid accidentally pushing unsigned or signed with the wrong key
commits to Savannah, make sure to configure Git according to
@xref{Configuring Git}.
@subsection Commit Policy
If you get commit access, please make sure to follow the policy below
(discussions of the policy can take place on
If you get commit access, please make sure to follow
the policy below (discussions of the policy can take place on
@email{guix-devel@@gnu.org}).
Ensure you're aware of how the changes should be handled
(@pxref{Managing Patches and Branches}) prior to being pushed to the
repository, especially for the @code{master} branch.
Non-trivial patches should always be posted to
@email{guix-patches@@gnu.org} (trivial patches include fixing typos,
etc.). This mailing list fills the patch-tracking database
(@pxref{Tracking Bugs and Patches}).
If you're committing and pushing your own changes, try and wait at least
one week (two weeks for more significant changes) after you send them
for review. After this, if no one else is available to review them and
if you're confident about the changes, it's OK to commit.
For patches that just add a new package, and a simple one, it's OK to
commit, if you're confident (which means you successfully built it in a
chroot setup, and have done a reasonable copyright and license
auditing). Likewise for package upgrades, except upgrades that trigger
a lot of rebuilds (for example, upgrading GnuTLS or GLib). We have a
mailing list for commit notifications (@email{guix-commits@@gnu.org}),
so people can notice. Before pushing your changes, make sure to run
@code{git pull --rebase}.
When pushing a commit on behalf of somebody else, please add a
@code{Signed-off-by} line at the end of the commit log message---e.g.,
@@ -1945,6 +1576,14 @@ right before pushing:
make check-channel-news
@end example
For anything else, please post to @email{guix-patches@@gnu.org} and
leave time for a review, without committing anything (@pxref{Submitting
Patches}). If you didnt receive any reply after two weeks, and if
you're confident, it's OK to commit.
That last part is subject to being adjusted, allowing individuals to commit
directly on non-controversial changes on parts theyre familiar with.
@subsection Addressing Issues
Peer review (@pxref{Submitting Patches}) and tools such as
@@ -2058,47 +1697,6 @@ This check can be disabled, @emph{at your own peril}, by setting the
this variable is set, the updated package source is also added to the
store. This is used as part of the release process of Guix.
@cindex documentation
@node Writing Documentation
@section Writing Documentation
Guix is documented using the Texinfo system. If you are not yet
familiar with it, we accept contributions for documentation in most
formats. That includes plain text, Markdown, Org, etc.
Documentation contributions can be sent to
@email{guix-patches@@gnu.org}. Prepend @samp{[DOCUMENTATION]} to the
subject.
When you need to make more than a simple addition to the documentation,
we prefer that you send a proper patch as opposed to sending an email
as described above. @xref{Submitting Patches} for more information on
how to send your patches.
To modify the documentation, you need to edit @file{doc/guix.texi} and
@file{doc/contributing.texi} (which contains this documentation
section), or @file{doc/guix-cookbook.texi} for the cookbook. If
you compiled the Guix repository before, you will have
many more @file{.texi} files that are translations of these
documents. Do not modify them, the translation is managed through
@uref{https://translate.fedoraproject.org/projects/guix, Weblate}.
@xref{Translating Guix} for more information.
To render documentation, you must first make sure that you ran
@command{./configure} in your source tree (@pxref{Running Guix Before
It Is Installed}). After that you can run one of the following
commands:
@itemize
@item @samp{make doc/guix.info} to compile the Info manual.
You can check it with @command{info doc/guix.info}.
@item @samp{make doc/guix.html} to compile the HTML version.
You can point your browser to the relevant file in the
@file{doc/guix.html} directory.
@item @samp{make doc/guix-cookbook.info} for the cookbook Info manual.
@item @samp{make doc/guix-cookbook.html} for the cookbook HTML version.
@end itemize
@cindex translation
@cindex l10n
@cindex i18n
@@ -2313,28 +1911,6 @@ Currently, some parts of Guix cannot be translated on Weblate, help wanted!
translated.
@end itemize
@subsubheading Conditions for Inclusion
There are no conditions for adding new translations of the @code{guix} and
@code{guix-packages} components, other than they need at least one translated
string. New languages will be added to Guix as soon as possible. The
files may be removed if they fall out of sync and have no more translated
strings.
Given that the web site is dedicated to new users, we want its translation
to be as complete as possible before we include it in the language menu.
For a new language to be included, it needs to reach at least 80% completion.
When a language is included, it may be removed in the future if it stays
out of sync and falls below 60% completion.
The manual and cookbook are automatically added in the default compilation
target. Every time we synchronize translations, developers need to
recompile all the translated manuals and cookbooks. This is useless for what
is essentially the English manual or cookbook. Therefore, we will only
include a new language when it reaches 10% completion in the component.
When a language is included, it may be removed in the future if it stays
out of sync and falls below 5% completion.
@subsubheading Translation Infrastructure
Weblate is backed by a git repository from which it discovers new strings to
+1 -1
View File
@@ -9,4 +9,4 @@
(package
(inherit gdb)
(native-inputs (modify-inputs (package-native-inputs gdb)
(prepend autoconf-2.69 automake texinfo))))
(prepend autoconf-2.64 automake texinfo))))
+94 -1734
View File
File diff suppressed because it is too large Load Diff
+2322 -9034
View File
File diff suppressed because it is too large Load Diff
+5 -6
View File
@@ -13,13 +13,12 @@
(service home-bash-service-type
(home-bash-configuration
(guix-defaults? #t)
(bash-profile (list (plain-file "bash-profile" "\
export HISTFILE=$XDG_CACHE_HOME/.bash_history")))))
(bash-profile '("\
export HISTFILE=$XDG_CACHE_HOME/.bash_history"))))
(simple-service 'test-config
home-xdg-configuration-files-service-type
(list `("test.conf"
home-files-service-type
(list `("config/test.conf"
,(plain-file "tmp-file.txt"
"the content of
~/.config/test.conf")))))))
"the content of ~/.config/test.conf")))))))
+8 -13
View File
@@ -1,9 +1,9 @@
# htmlxref.cnf - reference file for free Texinfo manuals on the web.
# Modified by Ludovic Courtès <ludo@gnu.org> for the GNU Guix manual.
htmlxrefversion=2022-12-18.15; # UTC
htmlxrefversion=2021-09-24.23; # UTC
# Copyright 2010-2020, 2022 Free Software Foundation, Inc.
# Copyright 2010-2020 Free Software Foundation, Inc.
#
# Copying and distribution of this file, with or without modification,
# are permitted in any medium without royalty provided the copyright
@@ -291,6 +291,8 @@ gdbm chapter ${GDBM}/html_chapter/
gdbm section ${GDBM}/html_section/
gdbm node ${GDBM}/html_node/
# XXX: These are actually pages created by texi2html, so no quite following
# the expected naming scheme.
geiser chapter http://geiser.nongnu.org/
gettext mono ${GS}/gettext/manual/gettext.html
@@ -409,21 +411,16 @@ GUILE_GNOME = ${GS}/guile-gnome/docs
guile-gtk node ${GS}/guile-gtk/docs/guile-gtk/
guile-netlink mono https://git.lepiller.eu/guile-netlink/manual/manual.html
guile-rpc mono ${GS}/guile-rpc/manual/guile-rpc.html
guile-rpc node ${GS}/guile-rpc/manual/html_node/
GUIX_ROOT = https://guix.gnu.org
GUIX = ${GUIX_ROOT}/manual
GUIX = ${GS}/guix/manual
guix.de mono ${GUIX}/de/guix.de.html
guix.de node ${GUIX}/de/html_node/
guix.es mono ${GUIX}/es/guix.es.html
guix.es node ${GUIX}/es/html_node/
guix.fr mono ${GUIX}/fr/guix.fr.html
guix.fr node ${GUIX}/fr/html_node/
guix.pt_BR mono ${GUIX}/pt-br/guix.pt_BR.html
guix.pt_BR node ${GUIX}/pt-br/html_node/
guix.ru mono ${GUIX}/ru/guix.ru.html
guix.ru node ${GUIX}/ru/html_node/
guix.zh_CN mono ${GUIX}/zh-cn/guix.zh_CN.html
@@ -431,13 +428,11 @@ GUIX = ${GUIX_ROOT}/manual
guix mono ${GUIX}/en/guix.html
guix node ${GUIX}/en/html_node/
GUIX_COOKBOOK = ${GUIX_ROOT}/cookbook
guix-cookbook.de mono ${GUIX_COOKBOOK}/de/guix-cookbook.de.html
GUIX_COOKBOOK = ${GS}/guix/cookbook
guix-cookbook.de mono ${GUIX_COOKBOOK}/de/guix-cookbook.html
guix-cookbook.de node ${GUIX_COOKBOOK}/de/html_node/
guix-cookbook.fr mono ${GUIX_COOKBOOK}/fr/guix-cookbook.fr.html
guix-cookbook.fr mono ${GUIX_COOKBOOK}/fr/guix-cookbook.html
guix-cookbook.fr node ${GUIX_COOKBOOK}/fr/html_node/
guix-cookbook.sk mono ${GUIX_COOKBOOK}/sk/guix-cookbook.sk.html
guix-cookbook.sk node ${GUIX_COOKBOOK}/sk/html_node/
guix-cookbook mono ${GUIX_COOKBOOK}/en/guix-cookbook.html
guix-cookbook node ${GUIX_COOKBOOK}/en/html_node/
+17 -17
View File
@@ -22,8 +22,8 @@
# along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
# If adding a language, update the following variables, and info_TEXINFOS.
MANUAL_LANGUAGES = de es fr pt_BR ru zh_CN
COOKBOOK_LANGUAGES = de fr ko sk
MANUAL_LANGUAGES = de es fa fi fr it ko pt_BR ru sk zh_CN
COOKBOOK_LANGUAGES = de es fa fi fr ko pt_BR ru sk uk zh_Hans
# Arg1: A list of languages codes.
# Arg2: The file name stem.
@@ -34,15 +34,27 @@ lang_to_texinfo = $(foreach lang,$(1),%D%/$(2).$(lang).texi)
info_TEXINFOS = %D%/guix.texi \
%D%/guix.de.texi \
%D%/guix.es.texi \
%D%/guix.fa.texi \
%D%/guix.fi.texi \
%D%/guix.fr.texi \
%D%/guix.it.texi \
%D%/guix.ko.texi \
%D%/guix.pt_BR.texi \
%D%/guix.ru.texi \
%D%/guix.sk.texi \
%D%/guix.zh_CN.texi \
%D%/guix-cookbook.texi \
%D%/guix-cookbook.de.texi \
%D%/guix-cookbook.es.texi \
%D%/guix-cookbook.fa.texi \
%D%/guix-cookbook.fi.texi \
%D%/guix-cookbook.fr.texi \
%D%/guix-cookbook.ko.texi \
%D%/guix-cookbook.sk.texi
%D%/guix-cookbook.pt_BR.texi \
%D%/guix-cookbook.ru.texi \
%D%/guix-cookbook.sk.texi \
%D%/guix-cookbook.uk.texi \
%D%/guix-cookbook.zh_Hans.texi
%C%_guix_TEXINFOS = \
%D%/contributing.texi \
@@ -179,31 +191,19 @@ sub_commands_mans = \
$(srcdir)/%D%/guix-archive.1 \
$(srcdir)/%D%/guix-build.1 \
$(srcdir)/%D%/guix-challenge.1 \
$(srcdir)/%D%/guix-container.1 \
$(srcdir)/%D%/guix-copy.1 \
$(srcdir)/%D%/guix-deploy.1 \
$(srcdir)/%D%/guix-describe.1 \
$(srcdir)/%D%/guix-download.1 \
$(srcdir)/%D%/guix-edit.1 \
$(srcdir)/%D%/guix-environment.1 \
$(srcdir)/%D%/guix-gc.1 \
$(srcdir)/%D%/guix-git.1 \
$(srcdir)/%D%/guix-graph.1 \
$(srcdir)/%D%/guix-hash.1 \
$(srcdir)/%D%/guix-home.1 \
$(srcdir)/%D%/guix-import.1 \
$(srcdir)/%D%/guix-lint.1 \
$(srcdir)/%D%/guix-offload.1 \
$(srcdir)/%D%/guix-pack.1 \
$(srcdir)/%D%/guix-package.1 \
$(srcdir)/%D%/guix-processes.1 \
$(srcdir)/%D%/guix-publish.1 \
$(srcdir)/%D%/guix-pull.1 \
$(srcdir)/%D%/guix-refresh.1 \
$(srcdir)/%D%/guix-repl.1 \
$(srcdir)/%D%/guix-shell.1 \
$(srcdir)/%D%/guix-size.1 \
$(srcdir)/%D%/guix-style.1 \
$(srcdir)/%D%/guix-system.1 \
$(srcdir)/%D%/guix-time-machine.1 \
$(srcdir)/%D%/guix-weather.1
@@ -229,8 +229,8 @@ $(srcdir)/%D%/guix.1: scripts/guix.in $(sub_commands_mans)
# The 'case' ensures the man pages are only generated if the corresponding
# source script (the first prerequisite) has been changed. The $(GOBJECTS)
# prerequisite is solely meant to force these docs to be made only after all
# Guile modules have been compiled. We also need the guix script to exist.
$(srcdir)/%D%/guix-%.1: guix/scripts/%.scm $(GOBJECTS) scripts/guix
# Guile modules have been compiled.
$(srcdir)/%D%/guix-%.1: guix/scripts/%.scm $(GOBJECTS)
-@case '$?' in \
*$<*) $(AM_V_P) && set -x || echo " HELP2MAN $@"; \
$(gen_man) --output="$@" "guix $*";; \
+90 -109
View File
@@ -6,7 +6,6 @@
;;; Copyright © 2020, 2021 Ricardo Wurmus <rekado@elephly.net>
;;; Copyright © 2021 Sarah Morgensen <iskarian@mgsn.dev>
;;; Copyright © 2021 Xinglu Chen <public@yoctocell.xyz>
;;; Copyright © 2022 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -29,19 +28,19 @@
;;; Code:
(use-modules ((sxml xpath) #:prefix xpath:)
(srfi srfi-1)
(srfi srfi-2)
(srfi srfi-9)
(srfi srfi-11)
(srfi srfi-26)
(ice-9 format)
(ice-9 popen)
(ice-9 match)
(ice-9 rdelim)
(ice-9 regex)
(ice-9 textual-ports)
(guix gexp))
(import (sxml xpath)
(srfi srfi-1)
(srfi srfi-2)
(srfi srfi-9)
(srfi srfi-11)
(srfi srfi-26)
(ice-9 format)
(ice-9 popen)
(ice-9 match)
(ice-9 rdelim)
(ice-9 regex)
(ice-9 textual-ports)
(guix gexp))
(define* (break-string str #:optional (max-line-length 70))
"Break the string STR into lines that are no longer than MAX-LINE-LENGTH.
@@ -101,16 +100,12 @@ LINE-NO in PORT."
(read-line port)
(loop (1- i) last-top-level-sexp))))))
;;; Whether the hunk contains a newly added package (definition), a removed
;;; package (removal) or something else (#false).
(define hunk-types '(addition removal #false))
(define-record-type <hunk>
(make-hunk file-name
old-line-number
new-line-number
diff-lines
type)
definition?)
hunk?
(file-name hunk-file-name)
;; Line number before the change
@@ -119,8 +114,8 @@ LINE-NO in PORT."
(new-line-number hunk-new-line-number)
;; The full diff to be used with "git apply --cached"
(diff-lines hunk-diff-lines)
;; Does this hunk add or remove a package?
(type hunk-type)) ;one of 'hunk-types'
;; Does this hunk add a definition?
(definition? hunk-definition?))
(define* (hunk->patch hunk #:optional (port (current-output-port)))
(let ((file-name (hunk-file-name hunk)))
@@ -138,30 +133,25 @@ LINE-NO in PORT."
;; new definitions with changes to existing
;; definitions.
"--unified=1"
"--" "gnu")))
"gnu")))
(define (extract-line-number line-tag)
(abs (string->number
(car (string-split line-tag #\,)))))
(define (read-hunk)
(let loop ((lines '())
(type #false))
(definition? #false))
(let ((line (read-line port 'concat)))
(cond
((eof-object? line)
(values (reverse lines) type))
(values (reverse lines) definition?))
((or (string-prefix? "@@ " line)
(string-prefix? "diff --git" line))
(unget-string port line)
(values (reverse lines) type))
(values (reverse lines) definition?))
(else
(loop (cons line lines)
(or type
(cond
((string-prefix? "+(define" line)
'addition)
((string-prefix? "-(define" line)
'removal)
(else #false)))))))))
(or definition?
(string-prefix? "+(define" line))))))))
(define info
(let loop ((acc '())
(file-name #f))
@@ -176,13 +166,13 @@ LINE-NO in PORT."
(match (string-split line #\space)
((_ old-start new-start . _)
(let-values
(((diff-lines type) (read-hunk)))
(((diff-lines definition?) (read-hunk)))
(loop (cons (make-hunk file-name
(extract-line-number old-start)
(extract-line-number new-start)
(cons (string-append line "\n")
diff-lines)
type) acc)
definition?) acc)
file-name)))))
(else (loop acc file-name))))))
(close-pipe port)
@@ -224,10 +214,10 @@ corresponding to the top-level definition containing the staged changes."
(define* (change-commit-message file-name old new #:optional (port (current-output-port)))
"Print ChangeLog commit message for changes between OLD and NEW."
(define (get-values expr field)
(match ((xpath:sxpath `(// ,field quasiquote *)) expr)
(match ((sxpath `(// ,field quasiquote *)) expr)
(()
;; New-style plain lists
(match ((xpath:sxpath `(// ,field list *)) expr)
(match ((sxpath `(// ,field list *)) expr)
((inner) inner)
(_ '())))
;; Old-style labelled inputs
@@ -244,7 +234,7 @@ corresponding to the top-level definition containing the staged changes."
(define variable-name
(second old))
(define version
(and=> ((xpath:sxpath '(// version *any*)) new)
(and=> ((sxpath '(// version *any*)) new)
first))
(format port
"gnu: ~a: Update to ~a.~%~%* ~a (~a): Update to ~a.~%"
@@ -272,18 +262,10 @@ corresponding to the top-level definition containing the staged changes."
(listify added))))))))))
'(inputs propagated-inputs native-inputs)))
(define* (add-commit-message file-name variable-name
#:optional (port (current-output-port)))
"Print ChangeLog commit message for a change to FILE-NAME adding a
definition."
(format port "gnu: Add ~a.~%~%* ~a (~a): New variable.~%"
variable-name file-name variable-name))
(define* (remove-commit-message file-name variable-name
#:optional (port (current-output-port)))
"Print ChangeLog commit message for a change to FILE-NAME removing a
definition."
(format port "gnu: Remove ~a.~%~%* ~a (~a): Delete variable.~%"
(define* (add-commit-message file-name variable-name #:optional (port (current-output-port)))
"Print ChangeLog commit message for a change to FILE-NAME adding a definition."
(format port
"gnu: Add ~a.~%~%* ~a (~a): New variable.~%"
variable-name file-name variable-name))
(define* (custom-commit-message file-name variable-name message changelog
@@ -362,67 +344,66 @@ modifying."
(()
(display "Nothing to be done.\n" (current-error-port)))
(hunks
(let-values (((definitions changes) (partition hunk-type hunks)))
;; Additions/removals.
(for-each
(lambda (hunk)
(and-let* ((define-line (find (cut string-match "(\\+|-)\\(define" <>)
(hunk-diff-lines hunk)))
(variable-name (and=> (string-tokenize define-line)
second))
(commit-message-proc (match (hunk-type hunk)
('addition add-commit-message)
('removal remove-commit-message))))
(commit-message-proc (hunk-file-name hunk) variable-name)
(let ((port (open-pipe* OPEN_WRITE
"git" "apply"
"--cached"
"--unidiff-zero")))
(hunk->patch hunk port)
(unless (eqv? 0 (status:exit-val (close-pipe port)))
(error "Cannot apply")))
(let-values
(((definitions changes)
(partition hunk-definition? hunks)))
(let ((port (open-pipe* OPEN_WRITE "git" "commit" "-F" "-")))
(commit-message-proc (hunk-file-name hunk) variable-name port)
(usleep %delay)
(unless (eqv? 0 (status:exit-val (close-pipe port)))
(error "Cannot commit"))))
(usleep %delay))
definitions))
;; Changes.
(for-each
(match-lambda
((new old . hunks)
(for-each (lambda (hunk)
(let ((port (open-pipe* OPEN_WRITE
"git" "apply"
"--cached"
"--unidiff-zero")))
(hunk->patch hunk port)
(unless (eqv? 0 (status:exit-val (close-pipe port)))
;; Additions.
(for-each (lambda (hunk)
(and-let*
((define-line (find (cut string-prefix? "+(define" <>)
(hunk-diff-lines hunk)))
(variable-name (and=> (string-tokenize define-line) second)))
(add-commit-message (hunk-file-name hunk) variable-name)
(let ((port (open-pipe* OPEN_WRITE
"git" "apply"
"--cached"
"--unidiff-zero")))
(hunk->patch hunk port)
(unless (eqv? 0 (status:exit-val (close-pipe port)))
(error "Cannot apply")))
(usleep %delay))
hunks)
(define copyright-line
(any (lambda (line) (and=> (string-prefix? "+;;; Copyright ©" line)
(const line)))
(hunk-diff-lines (first hunks))))
(cond
(copyright-line
(add-copyright-line copyright-line))
(else
(let ((port (open-pipe* OPEN_WRITE "git" "commit" "-F" "-")))
(change-commit-message* (hunk-file-name (first hunks))
old new)
(change-commit-message* (hunk-file-name (first hunks))
old new
port)
(usleep %delay)
(unless (eqv? 0 (status:exit-val (close-pipe port)))
(error "Cannot commit")))))))
;; XXX: we recompute the hunks here because previous
;; insertions lead to offsets.
(new+old+hunks (diff-info))))))
(let ((port (open-pipe* OPEN_WRITE "git" "commit" "-F" "-")))
(add-commit-message (hunk-file-name hunk)
variable-name port)
(usleep %delay)
(unless (eqv? 0 (status:exit-val (close-pipe port)))
(error "Cannot commit"))))
(usleep %delay))
definitions)
;; Changes.
(for-each (match-lambda
((new old . hunks)
(for-each (lambda (hunk)
(let ((port (open-pipe* OPEN_WRITE
"git" "apply"
"--cached"
"--unidiff-zero")))
(hunk->patch hunk port)
(unless (eqv? 0 (status:exit-val (close-pipe port)))
(error "Cannot apply")))
(usleep %delay))
hunks)
(define copyright-line
(any (lambda (line) (and=> (string-prefix? "+;;; Copyright ©" line)
(const line)))
(hunk-diff-lines (first hunks))))
(cond
(copyright-line
(add-copyright-line copyright-line))
(else
(let ((port (open-pipe* OPEN_WRITE "git" "commit" "-F" "-")))
(change-commit-message* (hunk-file-name (first hunks))
old new)
(change-commit-message* (hunk-file-name (first hunks))
old new
port)
(usleep %delay)
(unless (eqv? 0 (status:exit-val (close-pipe port)))
(error "Cannot commit")))))))
;; XXX: we recompute the hunks here because previous
;; insertions lead to offsets.
(new+old+hunks (diff-info)))))))
(apply main (cdr (command-line)))
+30 -31
View File
@@ -117,59 +117,58 @@ _guix_is_removing ()
$result
}
_guix_is_short_option ()
{
case "${COMP_WORDS[$COMP_CWORD - 1]}" in
--*) false;;
-*$1) true ;;
*) false ;;
esac
}
_guix_is_long_option ()
{
# Don't handle (non-GNU?) --long-option VALUE, as Guix doesn't either.
case "${COMP_WORDS[$COMP_CWORD]}" in
--$1=*) true ;;
*) false ;;
esac
}
_guix_is_dash_f ()
{
_guix_is_short_option f ||
_guix_is_long_option file ||
_guix_is_long_option install-from-file
[ "${COMP_WORDS[$COMP_CWORD - 1]}" = "-f" ] \
|| { case "${COMP_WORDS[$COMP_CWORD]}" in
--file=*|--install-from-file=*) true;;
*) false;;
esac }
}
_guix_is_dash_l ()
{
_guix_is_short_option l ||
_guix_is_long_option load
[ "${COMP_WORDS[$COMP_CWORD - 1]}" = "-l" ] \
|| { case "${COMP_WORDS[$COMP_CWORD]}" in
--load=*) true;;
*) false;;
esac }
}
_guix_is_dash_L ()
{
_guix_is_short_option L ||
_guix_is_long_option load-path
[ "${COMP_WORDS[$COMP_CWORD - 1]}" = "-L" ] \
|| { case "${COMP_WORDS[$COMP_CWORD]}" in
--load-path=*) true;;
*) false;;
esac }
}
_guix_is_dash_m ()
{
_guix_is_short_option m ||
_guix_is_long_option manifest
[ "${COMP_WORDS[$COMP_CWORD - 1]}" = "-m" ] \
|| { case "${COMP_WORDS[$COMP_CWORD]}" in
--manifest=*) true;;
*) false;;
esac }
}
_guix_is_dash_C ()
{
_guix_is_short_option C ||
_guix_is_long_option channels
[ "${COMP_WORDS[$COMP_CWORD - 1]}" = "-C" ] \
|| { case "${COMP_WORDS[$COMP_CWORD]}" in
--channels=*) true;;
*) false;;
esac }
}
_guix_is_dash_p ()
{
_guix_is_short_option p ||
_guix_is_long_option profile
[ "${COMP_WORDS[$COMP_CWORD - 1]}" = "-p" ] \
|| { case "${COMP_WORDS[$COMP_CWORD]}" in
--profile=*) true;;
*) false;;
esac }
}
_guix_complete_file ()
+3 -18
View File
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2021-2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2021 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -30,12 +30,11 @@
(match (origin-actual-file-name origin)
(#f #f)
((? string? file)
;; As of version 0.4.0, Disarchive can only deal with raw tarballs,
;; gzip-compressed tarballs, and xz-compressed tarballs.
;; As of version 0.2.1, Disarchive can only deal with raw tarballs and
;; gzip-compressed tarballs.
(and (origin-hash origin)
(or (string-suffix? ".tar.gz" file)
(string-suffix? ".tgz" file)
(string-suffix? ".tar.xz" file)
(string-suffix? ".tar" file))))))
(define (origin->disarchive origin)
@@ -99,20 +98,6 @@ an empty directory if ORIGIN could not be disassembled."
(directory-union "disarchive-collection"
(filter-map (lambda (origin)
(and (tarball-origin? origin)
;; Dismiss origins with (sha256 #f) such
;; as that of IceCat.
(and=> (origin-hash origin)
content-hash-value)
;; FIXME: Exclude the Chromium tarball
;; because it's huge and "disarchive
;; disassemble" exceeds the max-silent
;; timeout.
(not (string-prefix?
"chromium-"
(origin-actual-file-name origin)))
(origin->disarchive origin)))
origins)
#:copy? #t))
-13
View File
@@ -3,16 +3,3 @@
[diff "texinfo"]
xfuncname = "^@node[[:space:]]+([^,]+).*$"
[format]
forceinbodyfrom = true # help preserve commit authorship
thread = shallow
useAutoBase = true
[pull]
rebase = true
[sendemail]
to = guix-patches@gnu.org
headerCmd = etc/teams.scm cc-members-header-cmd
thread = no
+3 -26
View File
@@ -1,6 +1,6 @@
; -*- lisp -*-
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2018, 2022 Ricardo Wurmus <rekado@elephly.net>
;;; Copyright © 2018 Ricardo Wurmus <rekado@elephly.net>
;;; Copyright © 2020 Daniel Brooks <db48x@db48x.net>
;;; Copyright © 2020 Marius Bakke <marius@gnu.org>
;;;
@@ -37,13 +37,11 @@
(block guix_daemon
;; Require existing types
(typeattributeset cil_gen_require domain)
(typeattributeset cil_gen_require init_t)
(typeattributeset cil_gen_require init_var_run_t)
(typeattributeset cil_gen_require nscd_var_run_t)
(typeattributeset cil_gen_require system_dbusd_var_run_t)
(typeattributeset cil_gen_require tmp_t)
(typeattributeset cil_gen_require nscd_var_run_t)
(typeattributeset cil_gen_require var_log_t)
(typeattributeset cil_gen_require domain)
;; Declare own types
(type guix_daemon_t)
@@ -94,9 +92,6 @@
(allow init_t
guix_store_content_t
(file (open read execute)))
(allow init_t
guix_profiles_t
(dir (setattr)))
;; guix-daemon needs to know the names of users
(allow guix_daemon_t
@@ -176,11 +171,6 @@
execute_no_trans read write open entrypoint map
getattr link unlink)))
;; Remounting /gnu/store read-write.
(allow guix_daemon_t
fs_t
(filesystem (remount)))
;; TODO: unknown
(allow guix_daemon_t
root_t
@@ -228,9 +218,6 @@
(allow guix_daemon_t
tmpfs_t
(file (create open read unlink write)))
(allow guix_daemon_t ;same as above, but with tmp_t
tmp_t
(file (create open read unlink write)))
(allow guix_daemon_t
tmpfs_t
(dir (getattr add_name remove_name write)))
@@ -297,14 +284,6 @@
guix_store_content_t
(sock_file (create getattr setattr unlink write)))
;; Access to run state directories
(allow guix_daemon_t
system_dbusd_var_run_t
(dir (search)))
(allow guix_daemon_t
init_var_run_t
(dir (search)))
;; Access to configuration files and directories
(allow guix_daemon_t
guix_daemon_conf_t
@@ -468,8 +447,6 @@
any (unconfined_u object_r guix_store_content_t (low low)))
(filecon "@prefix@/bin/guix-daemon"
file (system_u object_r guix_daemon_exec_t (low low)))
(filecon "@guix_localstatedir@/guix/profiles/per-user/[^/]+/current-guix/bin/guix-daemon"
file (system_u object_r guix_daemon_exec_t (low low)))
(filecon "@storedir@/.+-(guix-.+|profile)/bin/guix-daemon"
file (system_u object_r guix_daemon_exec_t (low low)))
(filecon "@storedir@/[a-z0-9]+-guix-daemon"
+1 -7
View File
@@ -9,16 +9,10 @@ Description=Build daemon for GNU Guix
ExecStart=@localstatedir@/guix/profiles/per-user/root/current-guix/bin/guix-daemon \
--build-users-group=guixbuild --discover=no
Environment='GUIX_LOCPATH=@localstatedir@/guix/profiles/per-user/root/guix-profile/lib/locale' LC_ALL=en_US.utf8
RemainAfterExit=yes
StandardOutput=syslog
StandardError=syslog
# Work around a nasty systemd feature that kills the entire process tree
# (including the daemon!) if any child, such as cc1plus, runs out of memory.
OOMPolicy=continue
# Despite the name, this is rate-limited: a broken daemon will eventually fail.
Restart=always
# See <https://lists.gnu.org/archive/html/guix-devel/2016-04/msg00608.html>.
# Some package builds (for example, go@1.8.1) may require even more than
# 1024 tasks.
+86 -176
View File
@@ -3,15 +3,13 @@
# Copyright © 2017 sharlatan <sharlatanus@gmail.com>
# Copyright © 2018 Ricardo Wurmus <rekado@elephly.net>
# Copyright © 2018 Efraim Flashner <efraim@flashner.co.il>
# Copyright © 20192020, 2022 Tobias Geerinckx-Rice <me@tobias.gr>
# Copyright © 2019, 2020 Tobias Geerinckx-Rice <me@tobias.gr>
# Copyright © 2020 Morgan Smith <Morgan.J.Smith@outlook.com>
# Copyright © 2020 Simon Tournier <zimon.toutoune@gmail.com>
# Copyright © 2020 Daniel Brooks <db48x@db48x.net>
# Copyright © 2021 Jakub Kądziołka <kuba@kadziolka.net>
# Copyright © 2021 Chris Marusich <cmmarusich@gmail.com>
# Copyright © 2021, 2022, 2023 Maxim Cournoyer <maxim.cournoyer@gmail.com>
# Copyright © 2022 Prafulla Giri <prafulla.giri@protonmail.com>
# Copyright © 2023 Andrew Tropin <andrew@trop.in>
# Copyright © 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com>
#
# This file is part of GNU Guix.
#
@@ -30,28 +28,12 @@
# We require Bash but for portability we'd rather not use /bin/bash or
# /usr/bin/env in the shebang, hence this hack.
# Environment variables
#
# GUIX_BINARY_FILE_NAME
#
# Can be used to override the automatic download mechanism and point
# to a local Guix binary archive filename like
# "/tmp/guix-binary-1.4.0rc2.armhf-linux.tar.xz"
#
# GUIX_ALLOW_OVERWRITE
#
# Instead of aborting to avoid overwriting a previous installations,
# allow copying over /var/guix or /gnu. This can be useful when the
# installation required the user to extract Guix packs under /gnu to
# satisfy its dependencies.
if [ "x$BASH_VERSION" = "x" ]
then
exec bash "$0" "$@"
fi
set -eo pipefail
set -e
[ "$UID" -eq 0 ] || { echo "This script must be run as root."; exit 1; }
@@ -70,7 +52,6 @@ REQUIRE=(
"chmod"
"uname"
"groupadd"
"useradd"
"tail"
"tr"
"xz"
@@ -111,20 +92,17 @@ _debug()
fi
}
die()
{
_err "${ERR}$*"
exit 1
}
# Return true if user answered yes, false otherwise. The prompt is
# yes-biased, that is, when the user simply enter newline, it is equivalent to
# answering "yes".
# Return true if user answered yes, false otherwise.
# $1: The prompt question.
prompt_yes_no() {
local -l yn
read -rp "$1 [Y/n]" yn
[[ ! $yn || $yn = y || $yn = yes ]] || return 1
while true; do
read -rp "$1 " yn
case $yn in
[Yy]*) return 0;;
[Nn]*) return 1;;
*) _msg "Please answer yes or no."
esac
done
}
chk_require()
@@ -138,8 +116,10 @@ chk_require()
command -v "$c" &>/dev/null || warn+=("$c")
done
[ "${#warn}" -ne 0 ] && die "Missing commands: ${warn[*]}."
[ "${#warn}" -ne 0 ] &&
{ _err "${ERR}Missing commands: ${warn[*]}.";
return 1; }
_msg "${PAS}verification of required commands completed"
}
@@ -154,27 +134,21 @@ chk_gpg_keyring()
gpg_key_id=${GPG_SIGNING_KEYS[$user_id]}
# Without --dry-run this command will create a ~/.gnupg owned by root on
# systems where gpg has never been used, causing errors and confusion.
if gpg --dry-run --list-keys "$gpg_key_id" >/dev/null 2>&1; then
continue
fi
if prompt_yes_no "${INF}The following OpenPGP public key is \
if ! gpg --dry-run --list-keys "$gpg_key_id" >/dev/null 2>&1; then
if prompt_yes_no "${INF}The following OpenPGP public key is \
required to verify the Guix binary signature: $gpg_key_id.
Would you like me to fetch it for you?"; then
# Use a reasonable time-out here so users don't report silent
# freezes when Savannah goes out to lunch, as has happened.
if wget "https://sv.gnu.org/people/viewgpg.php?user_id=$user_id" \
--timeout=30 --no-verbose -O- | gpg --import -; then
continue
fi
fi
# If we reach this point, the key is (still) missing. Report further
# missing keys, if any, but then abort the installation.
_err "${ERR}Missing OpenPGP public key ($gpg_key_id).
Would you like me to fetch it for you? (yes/no)"; then
wget "https://sv.gnu.org/people/viewgpg.php?user_id=$user_id" \
--no-verbose -O- | gpg --import -
else
_err "${ERR}Missing OpenPGP public key ($gpg_key_id).
Fetch it with this command:
wget \"https://sv.gnu.org/people/viewgpg.php?user_id=$user_id\" -O - | \
sudo -i gpg --import -"
exit_flag=yes
exit_flag=yes
fi
fi
done
if [ "$exit_flag" = yes ]; then
exit 1
@@ -246,7 +220,8 @@ chk_sys_arch()
local arch=powerpc64le
;;
*)
die "Unsupported CPU type: ${arch}"
_err "${ERR}Unsupported CPU type: ${arch}"
exit 1
esac
case "$os" in
@@ -254,7 +229,8 @@ chk_sys_arch()
local os=linux
;;
*)
die "Your operation system (${os}) is not supported."
_err "${ERR}Your operation system (${os}) is not supported."
exit 1
esac
ARCH_OS="${arch}-${os}"
@@ -278,7 +254,7 @@ chk_sys_nscd()
configure_substitute_discovery() {
if grep -q -- '--discover=no' "$1" && \
prompt_yes_no "Would you like the Guix daemon to automatically \
discover substitute servers on the local network?"; then
discover substitute servers on the local network? (yes/no)"; then
sed -i 's/--discover=no/--discover=yes/' "$1"
fi
}
@@ -309,7 +285,8 @@ guix_get_bin_list()
if [[ "${#bin_ver_ls}" -ne "0" ]]; then
_msg "${PAS}Release for your system: ${default_ver}"
else
die "Could not obtain list of Guix releases."
_err "${ERR}Could not obtain list of Guix releases."
exit 1
fi
# Use default to download according to the list and local ARCH_OS.
@@ -334,7 +311,8 @@ guix_get_bin()
"${url}/${bin_ver}.tar.xz" "${url}/${bin_ver}.tar.xz.sig"; then
_msg "${PAS}download completed."
else
die "could not download ${url}/${bin_ver}.tar.xz."
_err "${ERR}could not download ${url}/${bin_ver}.tar.xz."
exit 1
fi
pushd "${dl_path}" >/dev/null
@@ -342,7 +320,8 @@ guix_get_bin()
_msg "${PAS}Signature is valid."
popd >/dev/null
else
die "could not verify the signature."
_err "${ERR}could not verify the signature."
exit 1
fi
}
@@ -353,18 +332,17 @@ sys_create_store()
_debug "--- [ ${FUNCNAME[0]} ] ---"
if [[ -e /var/guix && -e /gnu ]]; then
if [ -n "$GUIX_ALLOW_OVERWRITE" ]; then
_msg "${WAR}Overwriting existing installation!"
else
die "A previous Guix installation was found. Refusing to overwrite."
fi
if [[ -e "/var/guix" || -e "/gnu" ]]; then
_err "${ERR}A previous Guix installation was found. Refusing to overwrite."
exit 1
fi
cd "$tmp_path"
tar --extract --file "$pkg" && _msg "${PAS}unpacked archive"
_msg "${INF}Installing /var/guix and /gnu..."
# Strip (skip) the leading . component, which fails on read-only /.
tar --extract --strip-components=1 --file "$pkg" -C /
mv "${tmp_path}/var/guix" /var/
mv "${tmp_path}/gnu" /
_msg "${INF}Linking the root user's profile"
mkdir -p ~root/.config/guix
@@ -434,27 +412,36 @@ sys_enable_guix_daemon()
_msg "${PAS}enabled Guix daemon via upstart"
;;
systemd)
{ install_unit()
{
local dest="/etc/systemd/system/$1"
rm -f "$dest"
cp ~root/.config/guix/current/lib/systemd/system/"$1" "$dest"
chmod 664 "$dest"
systemctl daemon-reload
systemctl enable "$1"
}
{ # systemd .mount units must be named after the target directory.
# Here we assume a hard-coded name of /gnu/store.
# XXX Work around <https://issues.guix.gnu.org/41356> until next release.
if [ -f ~root/.config/guix/current/lib/systemd/system/gnu-store.mount ]; then
cp ~root/.config/guix/current/lib/systemd/system/gnu-store.mount \
/etc/systemd/system/;
chmod 664 /etc/systemd/system/gnu-store.mount;
systemctl daemon-reload &&
systemctl enable gnu-store.mount;
fi
install_unit guix-daemon.service
cp ~root/.config/guix/current/lib/systemd/system/guix-daemon.service \
/etc/systemd/system/;
chmod 664 /etc/systemd/system/guix-daemon.service;
# Work around <https://bugs.gnu.org/36074>, present in 1.0.1.
sed -i /etc/systemd/system/guix-daemon.service \
-e "s/GUIX_LOCPATH='/'GUIX_LOCPATH=/";
# Work around <https://bugs.gnu.org/35671>, present in 1.0.1.
if ! grep en_US /etc/systemd/system/guix-daemon.service >/dev/null;
then sed -i /etc/systemd/system/guix-daemon.service \
-e 's/^Environment=\(.*\)$/Environment=\1 LC_ALL=en_US.UTF-8';
fi;
configure_substitute_discovery \
/etc/systemd/system/guix-daemon.service
# Install after guix-daemon.service to avoid a harmless warning.
# systemd .mount units must be named after the target directory.
# Here we assume a hard-coded name of /gnu/store.
install_unit gnu-store.mount
systemctl daemon-reload &&
systemctl enable guix-daemon &&
systemctl start guix-daemon; } &&
_msg "${PAS}enabled Guix daemon via systemd"
;;
@@ -501,22 +488,14 @@ sys_enable_guix_daemon()
}
sys_authorize_build_farms()
{ # authorize the public key(s) of the build farm(s)
local hosts=(
ci.guix.gnu.org
bordeaux.guix.gnu.org
)
{ # authorize the public key of the build farm
if prompt_yes_no "Permit downloading pre-built package binaries from the \
project's build farms?"; then
for host in "${hosts[@]}"; do
local key=~root/.config/guix/current/share/guix/$host.pub
[ -f "$key" ] \
&& guix archive --authorize < "$key" \
&& _msg "${PAS}Authorized public key for $host"
done
else
_msg "${INF}Skipped authorizing build farm public keys"
project's build farm? (yes/no)"; then
guix archive --authorize \
< ~root/.config/guix/current/share/guix/ci.guix.gnu.org.pub \
&& _msg "${PAS}Authorized public key for ci.guix.gnu.org"
else
_msg "${INF}Skipped authorizing build farm public keys"
fi
}
@@ -524,17 +503,7 @@ sys_create_init_profile()
{ # Define for better desktop integration
# This will not take effect until the next shell or desktop session!
[ -d "/etc/profile.d" ] || mkdir /etc/profile.d # Just in case
cat <<"EOF" > /etc/profile.d/zzz-guix.sh
# Explicitly initialize XDG base directory variables to ease compatibility
# with Guix System: see <https://issues.guix.gnu.org/56050#3>.
export XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
export XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}"
export XDG_DATA_DIRS="${XDG_DATA_DIRS:-/usr/local/share/:/usr/share/}"
export XDG_CONFIG_DIRS="${XDG_CONFIG_DIRS:-/etc/xdg}"
export XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}"
# no default for XDG_RUNTIME_DIR (depends on foreign distro for semantics)
cat <<"EOF" > /etc/profile.d/guix.sh
# _GUIX_PROFILE: `guix pull` profile
_GUIX_PROFILE="$HOME/.config/guix/current"
export PATH="$_GUIX_PROFILE/bin${PATH:+:}$PATH"
@@ -544,19 +513,16 @@ export PATH="$_GUIX_PROFILE/bin${PATH:+:}$PATH"
# searches 'Info-default-directory-list'.
export INFOPATH="$_GUIX_PROFILE/share/info:$INFOPATH"
# GUIX_PROFILE: User's default profile and home profile
# GUIX_PROFILE: User's default profile
GUIX_PROFILE="$HOME/.guix-profile"
[ -f "$GUIX_PROFILE/etc/profile" ] && . "$GUIX_PROFILE/etc/profile"
[ -L "$GUIX_PROFILE" ] || \
GUIX_LOCPATH="$GUIX_PROFILE/lib/locale:${GUIX_LOCPATH:+:}$GUIX_LOCPATH"
GUIX_PROFILE="$HOME/.guix-home/profile"
[ -f "$GUIX_PROFILE/etc/profile" ] && . "$GUIX_PROFILE/etc/profile"
[ -L "$GUIX_PROFILE" ] || \
GUIX_LOCPATH="$GUIX_PROFILE/lib/locale:${GUIX_LOCPATH:+:}$GUIX_LOCPATH"
[ -L $GUIX_PROFILE ] || return
GUIX_LOCPATH="$GUIX_PROFILE/lib/locale"
export GUIX_LOCPATH
[ -f "$GUIX_PROFILE/etc/profile" ] && . "$GUIX_PROFILE/etc/profile"
# set XDG_DATA_DIRS to include Guix installations
export XDG_DATA_DIRS="$GUIX_PROFILE/share:${XDG_DATA_DIRS:-/usr/local/share/:/usr/share/}"
EOF
}
@@ -579,53 +545,9 @@ sys_create_shell_completion()
_msg "${PAS}installed shell completion"
}
sys_customize_bashrc()
{
prompt_yes_no "Customize users Bash shell prompt for Guix?" || return 0
for bashrc in /home/*/.bashrc /root/.bashrc; do
test -f "$bashrc" || continue
grep -Fq '$GUIX_ENVIRONMENT' "$bashrc" && continue
cp "${bashrc}" "${bashrc}.bak"
echo '
# Automatically added by the Guix install script.
if [ -n "$GUIX_ENVIRONMENT" ]; then
if [[ $PS1 =~ (.*)"\\$" ]]; then
PS1="${BASH_REMATCH[1]} [env]\\\$ "
fi
fi
' >> "$bashrc"
done
_msg "${PAS}Bash shell prompt successfully customized for Guix"
}
sys_maybe_setup_selinux()
{
if ! [ -f /sys/fs/selinux/policy ]
then
return
fi
local c
for c in semodule restorecon
do
if ! command -v "$c" &>/dev/null
then
return
fi
done
prompt_yes_no "Install SELinux policy that might be required to run guix-daemon?" \
|| return 0
local var_guix=/var/guix/profiles/per-user/root/current-guix
semodule -i "${var_guix}/share/selinux/guix-daemon.cil"
restorecon -R /gnu /var/guix
}
welcome()
{
local char
cat<<"EOF"
░░░ ░░░
░░▒▒░░░░░░░░░ ░░░░░░░░░▒▒░░
@@ -651,18 +573,8 @@ This script installs GNU Guix on your system
https://www.gnu.org/software/guix/
EOF
# Don't use read -p here! It won't display when run non-interactively.
echo -n "Press return to continue..."$'\r'
if ! read -r char; then
echo
die "Can't read standard input. Hint: don't pipe scripts into a shell."
fi
if [ "$char" ]; then
echo
echo "...that ($char) was not a return!"
_msg "${WAR}Use newlines to automate installation, e.g.: yes '' | ${0##*/}"
_msg "${WAR}Any other method is unsupported and likely to break in future."
fi
echo -n "Press return to continue..."
read -r
}
main()
@@ -682,7 +594,7 @@ main()
_msg "${INF}system is ${ARCH_OS}"
umask 0022
tmp_path="$(mktemp -t -d guix.XXXXXX)"
tmp_path="$(mktemp -t -d guix.XXX)"
if [ -z "${GUIX_BINARY_FILE_NAME}" ]; then
guix_get_bin_list "${GNU_URL}"
@@ -698,12 +610,10 @@ main()
sys_create_store "${GUIX_BINARY_FILE_NAME}" "${tmp_path}"
sys_create_build_user
sys_maybe_setup_selinux
sys_enable_guix_daemon
sys_authorize_build_farms
sys_create_init_profile
sys_create_shell_completion
sys_customize_bashrc
_msg "${INF}cleaning up ${tmp_path}"
rm -r "${tmp_path}"
+1 -3
View File
@@ -11,12 +11,10 @@ After=guix-daemon.service
[Service]
ExecStart=@localstatedir@/guix/profiles/per-user/root/current-guix/bin/guix publish --user=nobody --port=8181
Environment='GUIX_LOCPATH=@localstatedir@/guix/profiles/per-user/root/guix-profile/lib/locale' LC_ALL=en_US.utf8
RemainAfterExit=yes
StandardOutput=syslog
StandardError=syslog
# Despite the name, this is rate-limited: a broken daemon will eventually fail.
Restart=always
# See <https://lists.gnu.org/archive/html/guix-devel/2016-04/msg00608.html>.
TasksMax=1024
-35
View File
@@ -1,35 +0,0 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2022 Leo Famulari <leo@famulari.name>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
;;; This file returns a manifest of packages related to linux-libre.
;;; Simplistically, it selects packages whose names begin with "linux-libre".
;;; It is used to assist continuous integration of the kernel packages.
(use-modules (guix packages)
(guix profiles)
(gnu packages))
(manifest
(map package->manifest-entry
(fold-packages
(lambda (package lst)
(if (string-prefix? "linux-libre"
(package-name package))
(cons package lst)
lst))
'())))
+10 -1070
View File
File diff suppressed because it is too large Load Diff
+18 -22
View File
@@ -1,7 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2020-2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2020, 2021 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
;;; Copyright © 2023 Andreas Enge <andreas@enge.fr>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -24,10 +23,9 @@
(use-modules (gnu packages)
(guix packages)
(guix profiles)
((guix platform) #:select (targets))
((gnu ci) #:select (%cross-targets))
((gnu services xorg) #:select (%default-xorg-modules))
(guix utils)
(guix gexp)
(srfi srfi-1)
(srfi srfi-26))
@@ -52,17 +50,18 @@ TARGET."
"openssh" "emacs" "vim" "python" "guile" "guix")))
(define %base-packages/armhf
;; The guix package doesn't build natively on armhf due to Guile memory
;; issues compiling the package modules
(remove (lambda (package)
(string=? (package-name package) "guix"))
%base-packages))
;; XXX: Relax requirements for armhf-linux for lack of enough build power.
(map (lambda (package)
(if (string=? (package-name package) "emacs")
(specification->package "emacs-no-x")
package))
%base-packages))
(define %base-packages/hurd
;; XXX: For now we are less demanding of "i586-gnu".
(map specification->package
'("coreutils" "grep" "findutils" "gawk" "make"
#;"gcc-toolchain" "tar" "xz")))
"gcc-toolchain" "tar" "xz")))
(define %system-packages
;; Key packages proposed by the Guix System installer.
@@ -74,14 +73,16 @@ TARGET."
"connman" "network-manager" "network-manager-applet"
"openssh" "ntp" "tor"
"linux-libre" "grub-hybrid"
"icecat"))
;; FIXME: Add IceCat when Rust is available on i686.
;;"icecat"
))
%default-xorg-modules))
(define %packages-to-cross-build
;; Packages that must be cross-buildable from x86_64-linux.
;; FIXME: Add (@ (gnu packages gcc) gcc) when <https://bugs.gnu.org/40463>
;; is fixed.
(append (list (@ (gnu packages guile) guile-3.0/pinned))
(append (list (@ (gnu packages guile) guile-3.0/fixed))
(map specification->package
'("coreutils" "grep" "sed" "findutils" "diffutils" "patch"
"gawk" "gettext" "gzip" "xz"
@@ -110,6 +111,8 @@ TARGET."
(cond ((string=? system "i586-gnu")
%base-packages/hurd)
((string=? system "armhf-linux")
;; FIXME: Drop special case when ci.guix.gnu.org
;; has more ARMv7 build power.
%base-packages/armhf)
((string=? system "powerpc64le-linux")
;; FIXME: Drop 'bootstrap-tarballs' until
@@ -139,16 +142,9 @@ TARGET."
(if (target-mingw? target)
%packages-to-cross-build-for-mingw
%packages-to-cross-build)))
(fold delete (targets)
'(;; Like in (gnu ci), dismiss cross-compilation to x86:
;; it's pointless.
"x86_64-linux-gnu"
"i686-linux-gnu"
;; XXX: Important bits like libsigsegv and libffi don't
;; support RISCV at the moment, so don't require RISCV
;; support.
"riscv64-linux-gnu")))))
;; XXX: Important bits like libsigsegv and libffi don't support
;; RISCV at the moment, so don't require RISCV support.
(delete "riscv64-linux-gnu" %cross-targets))))
(define %cross-bootstrap-manifest
(manifest
@@ -11,7 +11,6 @@
"ant-build-system"
"asdf-build-system"
"cargo-build-system"
"chicken-build-system"
"clojure-build-system"
"cmake-build-system"
"copy-build-system"
@@ -28,7 +27,6 @@
"linux-module-build-system"
"maven-build-system"
"meson-build-system"
"minetest-build-system"
"minify-build-system"
"node-build-system"
"ocaml-build-system"
@@ -37,8 +35,6 @@
"qt-build-system"
"r-build-system"
"rakudo-build-system"
"rebar-build-system"
"renpy-build-system"
"ruby-build-system"
"scons-build-system"
"texlive-build-system"
-89
View File
@@ -1,89 +0,0 @@
-*- mode: lisp-data -*-
scheme-mode
(package...
"(define-public " (s name)
n> "(package"
n > "(name \"" (s name) "\")"
n > "(version \"" p "\")"
n > "(source origin...)"
n > "(build-system " (p "gnu") "-build-system)"
n > "(home-page \"" p "\")"
n > "(synopsis \"" p "\")"
n > "(description \"" p "\")"
n > "(license license:" (p "unknown") ")))" n)
(origin...
"(origin"
n> "(method " (p "url-fetch" method) ")"
n> "(uri " (cl-case (and method (intern method))
('git-fetch "git-reference...")
('svn-fetch "svn-reference...")
('hg-fetch "hg-reference...")
('cvs-fetch "cvs-reference...")
('bzr-fetch "bzr-reference...")
(t "\"https://...\""))
")"
n>
(cl-case (and method (intern method))
('git-fetch
(insert "(file-name (git-file-name name version))")
(newline)
(indent-according-to-mode))
('hg-fetch
(insert "(file-name (hg-file-name name version))")
(newline)
(indent-according-to-mode))
('svn-fetch
(insert "(file-name (string-append name \"-\" version \"-checkout\"))")
(newline)
(indent-according-to-mode))
('cvs-fetch
(insert "(file-name (string-append name \"-\" version \"-checkout\"))")
(newline)
(indent-according-to-mode))
('bzr-fetch
(insert "(file-name (string-append name \"-\" version \"-checkout\"))")
(newline)
(indent-according-to-mode))
(t ""))
> "(sha256"
n > "(base32 \""
;; hash of an empty directory
(p "0sjjj9z1dhilhpc8pq4154czrb79z9cm044jvn75kxcjv6v5l2m5") "\")))")
(git-reference...
"(git-reference"
n> "(url \"" p "\")"
n> "(commit " (p "commit") "))")
(svn-reference...
"(svn-reference"
n> "(url \"" p "\")"
n> "(revision " (p "revision") "))")
(cvs-reference...
"(cvs-reference"
n> "(root-directory \"" p "\")"
n> "(module \"" p "\")"
n> "(revision \"" p "\"))")
(hg-reference...
"(hg-reference"
n> "(url \"" p "\")"
n> "(changeset " (p "changeset") "))")
(bzr-reference...
"(bzr-reference"
n> "(url \"" p "\")"
n> "(revision " (p "revision") "))")
(:phases\ "#:phases (modify-phases %standard-phases"
n> p ")")
(add-before\ "(add-before '" p " '" p
n > p ")")
(add-after\ "(add-after '" p " '" p
n > p ")")
(replace\ "(replace '" p " " p")")
-158
View File
@@ -1,158 +0,0 @@
-*- mode: lisp-data -*-
text-mode :when (bound-and-true-p git-commit-mode)
(add\ "gnu: Add "
(p (with-temp-buffer
(magit-git-wash #'magit-diff-wash-diffs
"diff" "--staged")
(goto-char (point-min))
(when (re-search-forward "\\+(define-public \\(\\S-+\\)"
nil 'noerror)
(match-string-no-properties 1)))
var)
"." n n
"* " (p (or (car (magit-staged-files)) ""))
" (" (s var ) "): New variable.")
(remove\ "gnu: Remove "
(p (with-temp-buffer
(magit-git-wash #'magit-diff-wash-diffs
"diff" "--staged")
(goto-char (point-min))
(when (re-search-forward "\\-(define-public \\(\\S-+\\)"
nil 'noerror)
(match-string-no-properties 1)))
var)
"." n n
"* " (p (or (car (magit-staged-files)) ""))
" (" (s var) "): Delete variable.")
(rename\ "gnu: "
(p (with-temp-buffer
(magit-git-wash #'magit-diff-wash-diffs
"diff" "--staged")
(beginning-of-buffer)
(when (search-forward "-(define-public " nil 'noerror)
(thing-at-point 'sexp 'no-properties)))
prev-var)
": Rename package to "
(p (with-temp-buffer
(magit-git-wash #'magit-diff-wash-diffs
"diff" "--staged")
(beginning-of-buffer)
(when (search-forward "+(define-public " nil 'noerror)
(thing-at-point 'sexp 'no-properties)))
new-var)
"." n n
"* " (p (or (car (magit-staged-files)) "")) " (" (s prev-var) "): "
"Define in terms of" n
"'deprecated-package'." n
"(" (s new-var) "): New variable, formerly known as \""
(s prev-var) "\".")
(update\ "gnu: "
(p (with-temp-buffer
(magit-git-wash #'magit-diff-wash-diffs
"diff" "--staged")
(goto-char (point-min))
(when (re-search-forward "^[ ]*(define-public \\(\\S-+\\)"
nil 'noerror)
(match-string-no-properties 1)))
var)
": Update to "
(p (with-temp-buffer
(magit-git-wash #'magit-diff-wash-diffs
"diff" "--staged")
(goto-char (point-min))
(search-forward "name" nil 'noerror)
(search-forward "+" nil 'noerror) ; first change
(when (and (search-forward "version " nil 'noerror)
(looking-at-p "\""))
(let ((end (save-excursion (search-forward "\")"
nil 'noerror))))
(when end
(forward-char)
(buffer-substring-no-properties (point) (- end 2))))))
version)
"." n n
"* " (p (or (car (magit-staged-files)) "")) " (" (s var) "): "
"Update to " (s version) "." n
(mapconcat (lambda (file) (concat "* " file))
(cdr (magit-staged-files))
"\n"))
(addcl\ "gnu: Add cl-"
(p (replace-regexp-in-string
"^cl-" "" (with-temp-buffer
(magit-git-wash #'magit-diff-wash-diffs
"diff" "--staged")
(beginning-of-buffer)
(when (search-forward "+(define-public " nil 'noerror)
(replace-regexp-in-string
"^sbcl-" ""
(thing-at-point 'sexp 'no-properties)))))
var)
"." n n
"* " (p (or (car (magit-staged-files)) ""))
" (cl-" (s var)
", ecl-" (s var)
", sbcl-" (s var) "): New variables.")
(https\ "gnu: "
(p (with-temp-buffer
(magit-git-wash #'magit-diff-wash-diffs
"diff" "--staged")
(goto-char (point-min))
(when (re-search-forward "^[ ]*(define-public \\(\\S-+\\)"
nil 'noerror)
(match-string-no-properties 1)))
var)
": Use HTTPS home page." n n
"* " (p (or (car (magit-staged-files)) ""))
" (" (s var) ")[home-page]: Use HTTPS."
n
(mapconcat (lambda (file) (concat "* " file))
(cdr (magit-staged-files))
"\n"))
(move\ "gnu: "
(p (with-temp-buffer
(magit-git-wash #'magit-diff-wash-diffs
"diff" "--staged")
(goto-char (point-min))
(when (re-search-forward "\\-(define-public \\(\\S-+\\)"
nil 'noerror)
(match-string-no-properties 1)))
var)
": Move to ("
(p (with-temp-buffer
(magit-git-wash #'magit-diff-wash-diffs
"diff" "--staged")
(goto-char (point-min))
(when (and
(re-search-forward "\\+(define-public \\(\\S-+\\)"
nil 'noerror)
(re-search-backward "modified[ ]*\\(\\S-+\\)"
nil 'noerror))
(string-replace
"\.scm" ""
(string-replace "/" " "
(match-string-no-properties 1)))))
new-module)
")." n
n
"* " (p (with-temp-buffer
(magit-git-wash #'magit-diff-wash-diffs
"diff" "--staged")
(goto-char (point-min))
(when (and
(re-search-forward "\\-(define-public \\(\\S-+\\)"
nil 'noerror)
(re-search-backward "modified[ ]*\\(\\S-+\\)"
nil 'noerror))
(match-string-no-properties 1)))
source)
" (" (s var) "): Move from here…" n
"* " (concat (string-replace " " "/" new-module) ".scm")
" (" (s var) "): …to here.")
@@ -1,9 +0,0 @@
# -*- mode: snippet -*-
# name: guix-vc-commit-message-add-package
# key: add
# --
gnu: Add ${1:`(when (string-match "\\+(define-public \\(\\S-+\\)" vc-patch-string)
(match-string-no-properties 1 vc-patch-string))`}.
* `(car (log-edit-files))` ($1): New variable.
`(mapconcat (lambda (file) (concat "* " file)) (cdr (log-edit-files)) "\n")`
@@ -1,9 +0,0 @@
# -*- mode: snippet -*-
# name: guix-vc-commit-message-remove-package
# key: remove
# --
gnu: Remove ${1:`(when (string-match "\\-(define-public \\(\\S-+\\)" vc-patch-string)
(match-string-no-properties 1 vc-patch-string))`}.
* `(car (log-edit-files))` ($1): Delete variable.
`(mapconcat (lambda (file) (concat "* " file)) (cdr (log-edit-files)) "\n")`
@@ -1,14 +0,0 @@
# -*- mode: snippet -*-
# name: guix-vc-commit-message-rename-package
# key: rename
# --
gnu: ${1:`(when (string-match "\\-(define-public \\(\\S-+\\)" vc-patch-string)
(match-string-no-properties 1 vc-patch-string))
`}: Rename package to ${2:`
(when (string-match "\\+(define-public \\(\\S-+\\)" vc-patch-string)
(match-string-no-properties 1 vc-patch-string))`}.
* `(car (log-edit-files))` ($1): Define in terms of
'deprecated-package'.
($2): New variable, formerly known as "$1".
`(mapconcat (lambda (file) (concat "* " file)) (cdr (log-edit-files)) "\n")`
@@ -1,12 +0,0 @@
# -*- mode: snippet -*-
# name: guix-vc-commit-message-update-package
# key: update
# --
gnu: ${1:`(when (string-match "^[ ]*(define-public \\(\\S-+\\)" vc-patch-string)
(match-string-no-properties 1 vc-patch-string))`}: Update to ${2:`
(when (string-match "^\\+[ ]*(version \"\\(.*\\)\"" vc-patch-string)
(match-string-no-properties 1 vc-patch-string))`}.
* `(car (log-edit-files))` ($1): Update to $2.$0
`(mapconcat (lambda (file) (concat "* " file)) (cdr (log-edit-files)) "\n")`
@@ -1,9 +0,0 @@
# -*- mode: snippet -*-
# name: guix-vc-commit-message-use-https-home-page
# key: https
# --
gnu: ${1:`(when (string-match "^[ ]*(define-public \\(\\S-+\\)" vc-patch-string)
(match-string-no-properties 1 vc-patch-string))`}: Use HTTPS home page URI.
* `(car (log-edit-files))` ($1)[home-page]: Use HTTPS URI.
`(mapconcat (lambda (file) (concat "* " file)) (cdr (log-edit-files)) "\n")`
@@ -1,9 +0,0 @@
# -*- mode: snippet -*-
# name: guix-news-entry
# key: entry...
# --
(entry (commit "$1")
(title
(en "$2"))
(body
(en "$3")))
@@ -1,13 +0,0 @@
# -*- mode: snippet -*-
# name: guix-commit-message-remove-package
# key: remove
# condition: git-commit-mode
# --
gnu: Remove ${1:`(with-temp-buffer
(magit-git-wash #'magit-diff-wash-diffs
"diff" "--staged")
(goto-char (point-min))
(when (re-search-forward "\\-(define-public \\(\\S-+\\)" nil 'noerror)
(match-string-no-properties 1)))`}.
* `(car (magit-staged-files))` ($1): Delete variable.
+11 -16
View File
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2016, 2018-2020, 2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2016, 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -18,8 +18,7 @@
(use-modules (gnu tests)
(gnu packages package-management)
(guix monads)
(guix store)
((gnu ci) #:select (channel-source->package))
((guix git-download) #:select (git-predicate))
((guix utils) #:select (current-source-directory))
(git)
@@ -49,19 +48,15 @@ instance."
;; of tests to run in the usual way:
;;
;; make check-system TESTS=installed-os
(let ((guix (channel-source->package source #:commit commit)))
(map (lambda (test)
(system-test
(inherit test)
(value (mparameterize %store-monad ((current-guix-package guix))
(system-test-value test)))))
(match (getenv "TESTS")
(#f
(all-system-tests))
((= string-tokenize (tests ...))
(filter (lambda (test)
(member (system-test-name test) tests))
(all-system-tests)))))))
(parameterize ((current-guix-package
(channel-source->package source #:commit commit)))
(match (getenv "TESTS")
(#f
(all-system-tests))
((= string-tokenize (tests ...))
(filter (lambda (test)
(member (system-test-name test) tests))
(all-system-tests))))))
(define (system-test->manifest-entry test)
"Return a manifest entry for TEST, a system test."
-840
View File
@@ -1,840 +0,0 @@
#!@GUILE@ \
--no-auto-compile -s
!#
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2022, 2023 Ricardo Wurmus <rekado@elephly.net>
;;; Copyright © 2022 Mathieu Othacehe <othacehe@gnu.org>
;;; Copyright © 2022, 2023 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;; Copyright © 2022 Simon Tournier <zimon.toutoune@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; This code defines development teams and team members, as well as their
;; scope.
;;; Code:
(use-modules (srfi srfi-1)
(srfi srfi-9)
(srfi srfi-26)
(ice-9 format)
(ice-9 regex)
(ice-9 match)
(ice-9 rdelim)
(guix ui)
(git))
(define-record-type <regexp*>
(%make-regexp* pat flag rx)
regexp*?
(pat regexp*-pattern)
(flag regexp*-flag)
(rx regexp*-rx))
;;; Work around regexp implementation.
;;; This record allows to track the regexp pattern and then display it.
(define* (make-regexp* pat #:optional (flag regexp/extended))
"Alternative to `make-regexp' producing annotated <regexp*> objects."
(%make-regexp* pat flag (make-regexp pat flag)))
(define (regexp*-exec rx* str)
"Execute the RX* regexp, a <regexp*> object."
(regexp-exec (regexp*-rx rx*) str))
(define-record-type <team>
(make-team id name description members scope)
team?
(id team-id)
(name team-name)
(description team-description)
(members team-members set-team-members!)
(scope team-scope))
(define-record-type <person>
(make-person name email)
person?
(name person-name)
(email person-email))
(define* (person name #:optional email)
(make-person name email))
(define* (team id #:key name description (members '())
(scope '()))
(make-team id
(or name (symbol->string id))
description
members
scope))
(define %teams
(make-hash-table))
(define-syntax define-team
(lambda (x)
(syntax-case x ()
((_ id value)
#`(begin
(define-public id value)
(hash-set! %teams 'id id))))))
(define-syntax-rule (define-member person teams ...)
(let ((p person))
(for-each (lambda (team-id)
(let ((team
(hash-ref %teams team-id
(lambda ()
(error (format #false
"Unknown team ~a for ~a~%"
team-id p))))))
(set-team-members!
team (cons p (team-members team)))))
(quote (teams ...)))))
(define-team python
(team 'python
#:name "Python team"
#:description
"Python, Python packages, the \"pypi\" importer, and the python-build-system."
#:scope
(list "gnu/packages/django.scm"
"gnu/packages/jupyter.scm"
;; Match haskell.scm and haskell-*.scm.
(make-regexp* "^gnu/packages/python(-.+|)\\.scm$")
"gnu/packages/sphinx.scm"
"gnu/packages/tryton.scm"
"guix/build/pyproject-build-system.scm"
"guix/build-system/pyproject.scm"
"guix/build/python-build-system.scm"
"guix/build-system/python.scm"
"guix/import/pypi.scm"
"guix/scripts/import/pypi.scm"
"tests/pypi.scm")))
(define-team haskell
(team 'haskell
#:name "Haskell team"
#:description
"GHC, Hugs, Haskell packages, the \"hackage\" and \"stackage\" importers, and
the haskell-build-system."
#:scope
(list "gnu/packages/dhall.scm"
;; Match haskell.scm and haskell-*.scm.
(make-regexp* "^gnu/packages/haskell(-.+|)\\.scm$")
"gnu/packages/purescript.scm"
"guix/build/haskell-build-system.scm"
"guix/build-system/haskell.scm"
"guix/import/cabal.scm"
"guix/import/hackage.scm"
"guix/import/stackage.scm"
"guix/scripts/import/hackage.scm")))
(define-team qt
(team 'qt
#:name "Qt team"
#:description
"The Qt toolkit/library and the qt-build-system,
as well as some packages using Qt."
#:scope (list "gnu/packages/qt.scm"
"guix/build-system/qt.scm"
"guix/build/qt-build-system.scm"
"guix/build/qt-utils.scm")))
(define-team r
(team 'r
#:name "R team"
#:description
"The R language, CRAN and Bioconductor repositories, the \"cran\" importer,
and the r-build-system."
#:scope (list "gnu/packages/bioconductor.scm"
"gnu/packages/cran.scm"
"guix/build/r-build-system.scm"
"guix/build-system/r.scm"
"guix/import/cran.scm"
"guix/scripts/import/cran.scm"
"tests/cran.scm")))
(define-team telephony
(team 'telephony
#:name "Telephony team"
#:description
"Telephony packages and services such as Jami, Linphone, etc."
#:scope (list "gnu/build/jami-service.scm"
"gnu/packages/jami.scm"
"gnu/packages/linphone.scm"
"gnu/packages/telephony.scm"
"gnu/services/telephony.scm"
"gnu/tests/data/jami-dummy-account.dat"
"gnu/tests/telephony.scm"
"tests/services/telephony.scm")))
(define-team tex
(team 'tex
#:name "TeX team"
#:description
"TeX, LaTeX, XeLaTeX, LuaTeX, TeXLive, the texlive-build-system, and
the \"texlive\" importer."
#:scope (list "gnu/packages/tex.scm"
"gnu/packages/texlive.scm"
"guix/build/texlive-build-system.scm"
"guix/build-system/texlive.scm"
"guix/import/texlive.scm"
"guix/scripts/import/texlive.scm"
"tests/texlive.scm")))
(define-team julia
(team 'julia
#:name "Julia team"
#:description
"The Julia language, Julia packages, and the julia-build-system."
#:scope (list (make-regexp* "^gnu/packages/julia(-.+|)\\.scm$")
"guix/build/julia-build-system.scm"
"guix/build-system/julia.scm")))
(define-team ocaml
(team 'ocaml
#:name "OCaml and Dune team"
#:description
"The OCaml language, the Dune build system, OCaml packages, the \"opam\"
importer, and the ocaml-build-system."
#:scope
(list "gnu/packages/ocaml.scm"
"gnu/packages/coq.scm"
"guix/build/ocaml-build-system.scm"
"guix/build/dune-build-system.scm"
"guix/build-system/ocaml.scm"
"guix/build-system/dune.scm"
"guix/import/opam.scm"
"guix/scripts/import/opam.scm"
"tests/opam.scm")))
(define-team java
(team 'java
#:name "Java and Maven team"
#:description
"The JDK and JRE, the Maven build system, Java packages, the ant-build-system,
and the maven-build-system."
#:scope
(list ;; Match java.scm and java-*.scm.
(make-regexp* "^gnu/packages/java(-.+|)\\.scm$")
;; Match maven.scm and maven-*.scm
(make-regexp* "^gnu/packages/maven(-.+|)\\.scm$")
"guix/build/ant-build-system.scm"
"guix/build/java-utils.scm"
"guix/build/maven-build-system.scm"
;; The maven directory
(make-regexp* "^guix/build/maven/")
"guix/build-system/ant.scm"
"guix/build-system/maven.scm")))
(define-team science
(team 'science
#:name "Science team"
#:description "The main science disciplines and fields related
packages (e.g. Astronomy, Chemistry, Math, Physics etc.)"
#:scope (list "gnu/packages/algebra.scm"
"gnu/packages/astronomy.scm"
"gnu/packages/geo.scm"
"gnu/packages/chemistry.scm"
"gnu/packages/maths.scm")))
(define-team emacs
(team 'emacs
#:name "Emacs team"
#:description "The extensible, customizable text editor and its
ecosystem."
#:scope (list "gnu/packages/aux-files/emacs/guix-emacs.el"
(make-regexp* "^gnu/packages/emacs(-.+|)\\.scm$")
"gnu/packages/tree-sitter.scm"
"guix/build/emacs-build-system.scm"
"guix/build/emacs-utils.scm"
"guix/build-system/emacs.scm"
"guix/import/elpa.scm"
"guix/scripts/import/elpa.scm"
"tests/elpa.scm")))
(define-team lisp
(team 'lisp
#:name "Lisp team"
#:description
"Common Lisp and similar languages, Common Lisp packages and the
asdf-build-system."
#:scope (list (make-regexp* "^gnu/packages/lisp(-.+|)\\.scm$")
"guix/build/asdf-build-system.scm"
"guix/build/lisp-utils.scm"
"guix/build-system/asdf.scm")))
(define-team ruby
(team 'ruby
#:name "Ruby team"
#:scope (list "gnu/packages/ruby.scm"
"guix/build/ruby-build-system.scm"
"guix/build-system/ruby.scm"
"guix/import/gem.scm"
"guix/scripts/import/gem.scm"
"tests/gem.scm")))
(define-team go
(team 'go
#:name "Go team"
#:scope (list "gnu/packages/golang.scm"
"guix/build/go-build-system.scm"
"guix/build-system/go.scm"
"guix/import/go.scm"
"guix/scripts/import/go.scm"
"tests/go.scm")))
(define-team bootstrap
(team 'bootstrap
#:name "Bootstrap"
#:scope (list "gnu/packages/mes.scm")))
(define-team embedded
(team 'embedded
#:name "Embedded"
#:scope (list "gnu/packages/bootloaders.scm"
"gnu/packages/firmware.scm")))
(define-team rust
(team 'rust
#:name "Rust"
#:scope (list (make-regexp* "^gnu/packages/(crates|rust)(-.+|)\\.scm$")
"gnu/packages/sequoia.scm"
"guix/build/cargo-build-system.scm"
"guix/build/cargo-utils.scm"
"guix/build-system/cargo.scm"
"guix/import/crate.scm"
"guix/scripts/import/crate.scm"
"tests/crate.scm")))
(define-team kernel
(team 'kernel
#:name "Linux-libre kernel team"
#:scope (list "gnu/build/linux-modules.scm"
"gnu/packages/linux.scm"
"gnu/tests/linux-modules.scm"
"guix/build/linux-module-build-system.scm"
"guix/build-system/linux-module.scm")))
(define-team core
(team 'core
#:name "Core / Tools / Internals"
#:scope
(list "guix/avahi.scm"
"guix/base16.scm"
"guix/base32.scm"
"guix/base64.scm"
"guix/bzr-download.scm"
"guix/cache.scm"
"guix/channels.scm"
"guix/ci.scm"
"guix/colors.scm"
"guix/combinators.scm"
"guix/config.scm"
"guix/cpio.scm"
"guix/cpu.scm"
"guix/cve.scm"
"guix/cvs-download.scm"
"guix/deprecation.scm"
"guix/derivations.scm"
"guix/describe.scm"
"guix/diagnostics.scm"
"guix/discovery.scm"
"guix/docker.scm"
"guix/download.scm"
"guix/elf.scm"
"guix/ftp-client.scm"
"guix/gexp.scm"
"guix/git-authenticate.scm"
"guix/git-download.scm"
"guix/git.scm"
"guix/glob.scm"
"guix/gnu-maintenance.scm"
"guix/gnupg.scm"
"guix/grafts.scm"
"guix/graph.scm"
"guix/hash.scm"
"guix/hg-download.scm"
"guix/http-client.scm"
"guix/i18n.scm"
"guix/inferior.scm"
"guix/ipfs.scm"
"guix/least-authority.scm"
"guix/licenses.scm"
"guix/lint.scm"
"guix/man-db.scm"
"guix/memoization.scm"
"guix/modules.scm"
"guix/monad-repl.scm"
"guix/monads.scm"
"guix/narinfo.scm"
"guix/nar.scm"
"guix/openpgp.scm"
"guix/packages.scm"
"guix/pki.scm"
"guix/platform.scm"
"guix/profiles.scm"
"guix/profiling.scm"
"guix/progress.scm"
"guix/quirks.scm"
"guix/read-print.scm"
"guix/records.scm"
"guix/remote.scm"
"guix/repl.scm"
"guix/search-paths.scm"
"guix/self.scm"
"guix/serialization.scm"
"guix/sets.scm"
"guix/ssh.scm"
"guix/status.scm"
"guix/store.scm"
"guix/substitutes.scm"
"guix/svn-download.scm"
"guix/swh.scm"
"guix/tests.scm"
"guix/transformations.scm"
"guix/ui.scm"
"guix/upstream.scm"
"guix/utils.scm"
"guix/workers.scm"
(make-regexp* "^guix/platforms/")
(make-regexp* "^guix/scripts/")
(make-regexp* "^guix/store/"))))
(define-team games
(team 'games
#:name "Games and Toys"
#:description "Packaging programs for amusement."
#:scope (list "gnu/packages/games.scm"
"gnu/packages/game-development.scm"
"gnu/packages/minetest.scm"
"gnu/packages/esolangs.scm" ; granted, rather niche
"gnu/packages/motti.scm"
"guix/build/minetest-build-system.scm")))
(define-team localization
(team 'localization
#:name "Localization (l10n) team"
#:description
"Localization of your system to specific languages."
#:scope (list "gnu/packages/anthy.scm"
"gnu/packages/fcitx5.scm"
"gnu/packages/fcitx.scm"
"gnu/packages/fonts.scm"
"gnu/packages/ibus.scm")))
(define-team translations
(team 'translations
#:name "Translations"
#:scope (list "etc/news.scm"
(make-regexp* "^po/"))))
(define-team installer
(team 'installer
#:name "Installer script and system installer"
#:scope (list (make-regexp* "^gnu/installer(\\.scm$|/)"))))
(define-team home
(team 'home
#:name "Team for \"Guix Home\""
#:scope (list (make-regexp* "^(gnu|guix/scripts)/home(\\.scm$|/)")
"tests/guix-home.sh"
"tests/home-import.scm"
"tests/home-services.scm")))
(define-team mentors
(team 'mentors
#:name "Mentors"
#:description
"A group of mentors who chaperone contributions by newcomers."))
(define-team mozilla
(team 'mozilla
#:name "Mozilla"
#:description
"Taking care about Icecat and Icedove, built from Mozilla Firefox
and Thunderbird."
#:scope (list "gnu/packages/gnuzilla.scm")))
(define-team racket
(team 'racket
#:name "Racket team"
#:description
"The Racket language and Racket-based languages, Racket packages,
Racket's variant of Chez Scheme, and development of a Racket build system and
importer."
#:scope (list "gnu/packages/chez.scm"
"gnu/packages/racket.scm")))
(define-team reproduciblebuilds
(team 'reproduciblebuilds
#:name "Reproducible Builds team"
#:description
"Reproducible Builds tooling and issues that affect any guix packages."
#:scope (list "gnu/packages/diffoscope.scm")))
(define-team gnome
(team 'gnome
#:name "Gnome team"
#:description
"The Gnome desktop environment, along with core technologies such as
GLib/GIO, GTK, GStreamer and Webkit."
#:scope (list "gnu/packages/glib.scm"
"gnu/packages/gstreamer.scm"
"gnu/packages/gtk.scm"
"gnu/packages/gnome.scm"
"gnu/packages/gnome-xyz.scm"
"gnu/packages/webkit.scm"
"guix/build/glib-or-gtk-build-system.scm"
"guix/build/meson-build-system.scm")))
(define-team xfce
(team 'xfce
#:name "Xfce team"
#:description "Xfce desktop environment."
#:scope (list "gnu/packages/xfce.scm")))
(define-team lxqt
(team 'lxqt
#:name "LXQt team"
#:description "LXQt desktop environment."
#:scope (list "gnu/packages/lxqt.scm"
"gnu/packages/qt.scm")))
(define-member (person "Eric Bavier"
"bavier@posteo.net")
science)
(define-member (person "Lars-Dominik Braun"
"lars@6xq.net")
python haskell)
(define-member (person "Jonathan Brielmaier"
"jonathan.brielmaier@web.de")
mozilla)
(define-member (person "Ludovic Courtès"
"ludo@gnu.org")
core home bootstrap installer mentors)
(define-member (person "Andreas Enge"
"andreas@enge.fr")
lxqt science tex)
(define-member (person "Tobias Geerinckx-Rice"
"me@tobias.gr")
core kernel mentors)
(define-member (person "Björn Höfling"
"bjoern.hoefling@bjoernhoefling.de")
java)
(define-member (person "Leo Famulari"
"leo@famulari.name")
kernel)
(define-member (person "Efraim Flashner"
"efraim@flashner.co.il")
embedded bootstrap julia rust science)
(define-member (person "jgart"
"jgart@dismail.de")
python lisp mentors)
(define-member (person "Guillaume Le Vaillant"
"glv@posteo.net")
lisp)
(define-member (person "Julien Lepiller"
"julien@lepiller.eu")
java ocaml translations)
(define-member (person "Philip McGrath"
"philip@philipmcgrath.com")
racket)
(define-member (person "Mathieu Othacehe"
"othacehe@gnu.org")
core installer mentors)
(define-member (person "Florian Pelz"
"pelzflorian@pelzflorian.de")
translations)
(define-member (person "Liliana Marie Prikler"
"liliana.prikler@gmail.com")
emacs games gnome)
(define-member (person "Ricardo Wurmus"
"rekado@elephly.net")
r core mentors tex)
(define-member (person "Christopher Baines"
"guix@cbaines.net")
core mentors ruby)
(define-member (person "Andrew Tropin"
"andrew@trop.in")
home emacs)
(define-member (person "pukkamustard"
"pukkamustard@posteo.net")
ocaml)
(define-member (person "Josselin Poiret"
"dev@jpoiret.xyz")
core installer)
(define-member (person "("
"paren@disroot.org")
home mentors)
(define-member (person "Simon Tournier"
"zimon.toutoune@gmail.com")
julia core mentors)
(define-member (person "Raghav Gururajan"
"rg@raghavgururajan.name")
gnome mentors)
(define-member (person "宋文武"
"iyzsong@envs.net")
games localization lxqt xfce)
(define-member (person "Vagrant Cascadian"
"vagrant@debian.org")
embedded)
(define-member (person "Vagrant Cascadian"
"vagrant@reproducible-builds.org")
reproduciblebuilds)
(define-member (person "Zhu Zihao"
"all_but_last@163.com")
localization xfce)
(define-member (person "Maxim Cournoyer"
"maxim.cournoyer@gmail.com")
gnome qt telephony)
(define-member (person "Katherine Cox-Buday"
"cox.katherine.e+guix@gmail.com")
emacs go lisp)
(define (find-team name)
(or (hash-ref %teams (string->symbol name))
(error (format #false
"no such team: ~a~%" name))))
(define (find-team-by-scope files)
"Return the team(s) which scope matches at least one of the FILES, as list
of file names as string."
(hash-fold
(lambda (key team acc)
(if (any (lambda (file)
(any (match-lambda
((? string? scope)
(string=? scope file))
((? regexp*? scope)
(regexp*-exec scope file)))
(team-scope team)))
files)
(cons team acc)
acc))
'()
%teams))
(define (cc . teams)
"Return arguments for `git send-email' to notify the members of the given
TEAMS when a patch is received by Debbugs."
(let ((members (append-map team-members teams)))
(unless (null? members)
(format #true "--add-header=\"X-Debbugs-Cc: ~{~a~^, ~}\""
(map person-email (sort-members members))))))
(define (sort-members members)
"Deduplicate and sort MEMBERS alphabetically by their name."
(sort (delete-duplicates members equal?)
(lambda (m1 m2)
(string<? (person-name m1) (person-name m2)))))
(define (member->string member)
"Return the 'email <name>' string representation of MEMBER."
(let* ((name (person-name member))
(quoted-name/maybe (if (string-contains name ",")
(string-append "\"" name "\"")
name)))
(format #false "~a <~a>" quoted-name/maybe (person-email member))))
(define* (list-members team #:key (prefix ""))
"Print the members of the given TEAM."
(for-each (lambda (member)
(format #t "~a~a~%" prefix (member->string member)))
(sort-members (team-members team))))
(define (print-team team)
"Print TEAM, a <team> record object."
(format #t
"\
id: ~a
name: ~a
description: ~a
~amembers:
"
(team-id team)
(team-name team)
(or (and=> (team-description team)
(lambda (text)
(string->recutils
(fill-paragraph text (%text-width)
(string-length "description: ")))))
"<none>")
(match (team-scope team)
(() "")
(scope (format #f "scope:~%~{+ ~a~^~%~}~%"
(sort (map (match-lambda
((? regexp*? rx)
(regexp*-pattern rx))
(item item))
scope)
string<?)))))
(list-members team #:prefix "+ ")
(newline))
(define (sort-teams teams)
"Sort TEAMS, a list of <team> record objects."
(sort teams
(lambda (team1 team2)
(string<? (symbol->string (team-id team1))
(symbol->string (team-id team2))))))
(define* (list-teams #:optional team-names)
"Print all teams, their scope and their members."
(for-each print-team
(sort-teams
(if team-names
(map find-team team-names)
(hash-map->list (lambda (_ value) value) %teams)))))
(define (diff-revisions rev-start rev-end)
"Return the list of added, modified or removed files between REV-START
and REV-END, two git revision strings."
(let* ((repository (repository-open (getcwd)))
(commit1 (commit-lookup repository
(object-id
(revparse-single repository rev-start))))
(commit2 (commit-lookup repository
(object-id
(revparse-single repository rev-end))))
(diff (diff-tree-to-tree repository
(commit-tree commit1)
(commit-tree commit2)))
(files '()))
(diff-foreach
diff
(lambda (delta progress)
(set! files
(cons (diff-file-path (diff-delta-old-file delta)) files))
0)
(const 0)
(const 0)
(const 0))
files))
(define (git-patch->commit-id file)
"Parse the commit ID from the first line of FILE, a patch produced with git."
(call-with-input-file file
(lambda (port)
(let ((m (string-match "^From ([0-9a-f]{40})" (read-line port))))
(unless m
(error "invalid patch file:" file))
(match:substring m 1)))))
(define (git-patch->revisions file)
"Return the start and end revisions of FILE, a patch file produced with git."
(let* ((rev-end (git-patch->commit-id file))
(rev-start (string-append rev-end "^")))
(list rev-start rev-end)))
(define (patch->teams patch-file)
"Return the name of the teams in scope for the changes in PATCH-FILE."
(map (compose symbol->string team-id)
(find-team-by-scope (apply diff-revisions
(git-patch->revisions patch-file)))))
(define (main . args)
(match args
(("cc" . team-names)
(apply cc (map find-team team-names)))
(("cc-members" patch-file)
(unless (file-exists? patch-file)
(error "patch file does not exist:" patch-file))
(apply main "cc-members" (git-patch->revisions patch-file)))
(("cc-members" rev-start rev-end)
(apply cc (find-team-by-scope
(diff-revisions rev-start rev-end))))
(("cc-members-header-cmd" patch-file)
(let* ((teams (map find-team (patch->teams patch-file)))
(members (sort-members (append-map team-members teams))))
(unless (null? members)
(format #true "X-Debbugs-Cc: ~{~a~^, ~}"
(map member->string members)))))
(("cc-mentors-header-cmd" patch-file)
(format #true "X-Debbugs-Cc: ~{~a~^, ~}"
(map member->string
(sort-members (team-members (find-team "mentors"))))))
(("get-maintainer" patch-file)
(apply main "list-members" (patch->teams patch-file)))
(("list-teams" . args)
(list-teams))
(("list-members" . team-names)
(for-each
(lambda (team-name)
(list-members (find-team team-name)))
team-names))
(("show" . team-names)
(list-teams team-names))
(anything
(format (current-error-port)
"Usage: etc/teams.scm <command> [<args>]
Commands:
cc <team-name>
get git send-email flags for cc-ing <team-name>
cc-members <start> <end> | <patch>
cc teams related to files changed between revisions or in a patch file
cc-members-header-cmd <patch>
cc-members variant for use with 'git send-email --header-cmd'
cc-mentors-header-cmd <patch>
command to use with 'git send-email --header-cmd' to notify mentors
list-teams
list teams and their members
list-members <team-name>
list members belonging to <team-name>
get-maintainer <patch>
compatibility mode with Linux get_maintainer.pl
show <team-name>
display <team-name> properties~%"))))
(apply main (cdr (command-line)))
-50
View File
@@ -1,50 +0,0 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2023 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
;;; This file returns a manifest of packages related to linux-libre.
;;; Simplistically, it selects packages whose names begin with "linux-libre".
;;; It is used to assist continuous integration of the kernel packages.
(use-modules (guix packages)
(guix profiles)
(guix utils)
(gnu packages))
(define* (qt-packages-manifest #:key major-version negate-version-test?)
"Return a manifest of Qt packages for MAJOR-VERSION, or any version if left
unspecified. If NEGATE-VERSION-TEST? is true, select all the Qt packages
*not* matching MAJOR-VERSION."
(manifest
(map package->manifest-entry
(fold-packages
(lambda (package lst)
(let ((uri (and=> (package-source package)
(lambda (x)
(and (origin? x)
(origin-uri x))))))
(if (and uri
(string? uri)
(string-prefix? "mirror://qt/" uri)
(if major-version
((if negate-version-test? not identity)
(string=? major-version (version-major
(package-version package))))
#t))
(cons package lst)
lst)))
'()))))
-34
View File
@@ -1,34 +0,0 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2023 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
;;; This file returns a manifest of packages related to linux-libre.
;;; Simplistically, it selects packages whose names begin with "linux-libre".
;;; It is used to assist continuous integration of the kernel packages.
(load "common.scm")
;;; Commentary:
;;;
;;; This manifest can be used to update the latest Qt packages collection, via
;;; e.g.:
;;;
;;; ./pre-inst-env guix refresh -u -m etc/teams/qt/qt-manifest.scm
;;;
;;; Code:
(qt-packages-manifest #:major-version "5" #:negate-version-test? #t)
-34
View File
@@ -1,34 +0,0 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2023 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
;;; This file returns a manifest of packages related to linux-libre.
;;; Simplistically, it selects packages whose names begin with "linux-libre".
;;; It is used to assist continuous integration of the kernel packages.
(load "common.scm")
;;; Commentary:
;;;
;;; This manifest can be used to update the Qt 5 packages collection, via
;;; e.g.:
;;;
;;; ./pre-inst-env guix refresh -u -m etc/teams/qt/qt5-manifest.scm --target-version=5.15.10
;;;
;;; Code:
(qt-packages-manifest #:major-version "5")
-84
View File
@@ -1,84 +0,0 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2022 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
;;; This file returns a manifest containing entries to build past Guix
;;; releases from the current Guix, as per 'guix time-machine'.
(use-modules (srfi srfi-9) (ice-9 match)
(guix channels) (guix gexp)
((guix store) #:select (%store-monad))
((guix monads) #:select (mparameterize return))
((guix git) #:select (%repository-cache-directory))
((guix build utils) #:select (mkdir-p)))
;; Representation of the latest channels. This type exists just so we can
;; refer to such records in a gexp.
(define-record-type <guix-instance>
(guix-instance channels)
guix-instance?
(channels guix-instance-channels))
(define-gexp-compiler (guix-instance-compiler (instance <guix-instance>)
system target)
(match instance
(($ <guix-instance> channels)
;; When this manifest is evaluated by Cuirass, make sure it does not
;; fiddle with the cached checkout that Cuirass is also using since
;; concurrent accesses are unsafe.
(mparameterize %store-monad ((%repository-cache-directory
(string-append (%repository-cache-directory)
"/time-travel/" system)))
(return (mkdir-p (%repository-cache-directory)))
(latest-channel-derivation channels)))))
(define (guix-instance->manifest-entry instance)
"Return a manifest entry for INSTANCE."
(define (shorten commit)
(string-take commit 7))
(manifest-entry
(name "guix")
(version (string-join (map (compose shorten channel-commit)
(guix-instance-channels instance))
"-"))
(item instance)))
(define (commit->guix-instance commit)
"Return a Guix instance for COMMIT."
(guix-instance (list (channel
(inherit %default-guix-channel)
(commit commit)))))
(define %release-commits
;; Release commits: the list of version/commit pairs.
'(("1.3.0" . "a0178d34f582b50e9bdbb0403943129ae5b560ff")
("1.2.0" . "a099685659b4bfa6b3218f84953cbb7ff9e88063")
("1.1.0" . "d62c9b2671be55ae0305bebfda17b595f33797f2")
("1.0.1" . "d68de958b60426798ed62797ff7c96c327a672ac")
("1.0.0" . "6298c3ffd9654d3231a6f25390b056483e8f407c")
("0.16.0" . "4a0b87f0ec5b6c2dcf82b372dd20ca7ea6acdd9c")))
(manifest
(map (match-lambda
((version . commit)
(let ((entry (guix-instance->manifest-entry
(commit->guix-instance commit))))
(manifest-entry
(inherit entry)
(version version)))))
%release-commits))
+2 -2
View File
@@ -29,7 +29,7 @@
;;; Code:
(define %artwork-repository
(let ((commit "4c7f2ce6428a63e202cd2a9474a06f68a946934d"))
(let ((commit "2f2fe74c1078be605a6a93c2193fd6c715cebbb0"))
(origin
(method git-fetch)
(uri (git-reference
@@ -39,6 +39,6 @@
"-checkout"))
(sha256
(base32
"1rl569759q9wm1dxn7nkq3873d2k92giic7aa6jwzwr3n16prc7y")))))
"0c8r0phvm3wgf914n2kw1461cwdjl2zbzqvzq9x7d9pwkgv7xmq7")))))
;;; artwork.scm ends here
+87 -151
View File
@@ -1,11 +1,9 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2017 David Craven <david@craven.ch>
;;; Copyright © 2017, 2020, 2022 Mathieu Othacehe <othacehe@gnu.org>
;;; Copyright © 2017, 2020 Mathieu Othacehe <m.othacehe@gmail.com>
;;; Copyright © 2017 Leo Famulari <leo@famulari.name>
;;; Copyright © 2019, 2021 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
;;; Copyright © 2022 Josselin Poiret <dev@jpoiret.xyz>
;;; Copyright © 2022 Reza Alizadeh Majd <r.majd@pantherx.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -23,8 +21,6 @@
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (gnu bootloader)
#:use-module (gnu system file-systems)
#:use-module (gnu system uuid)
#:use-module (guix discovery)
#:use-module (guix gexp)
#:use-module (guix profiles)
@@ -34,8 +30,6 @@
#:use-module (guix diagnostics)
#:use-module (guix i18n)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-34)
#:use-module (srfi srfi-35)
#:use-module (ice-9 match)
#:export (menu-entry
menu-entry?
@@ -48,7 +42,6 @@
menu-entry-multiboot-kernel
menu-entry-multiboot-arguments
menu-entry-multiboot-modules
menu-entry-chain-loader
menu-entry->sexp
sexp->menu-entry
@@ -76,7 +69,7 @@
bootloader-configuration-terminal-inputs
bootloader-configuration-serial-unit
bootloader-configuration-serial-speed
bootloader-configuration-device-tree-support?
bootloader-configuration-additional-configuration
%bootloaders
lookup-bootloader-by-name
@@ -107,77 +100,34 @@
(multiboot-arguments menu-entry-multiboot-arguments
(default '())) ; list of string-valued gexps
(multiboot-modules menu-entry-multiboot-modules
(default '())) ; list of multiboot commands, where
(default '()))) ; list of multiboot commands, where
; a command is a list of <string>
(chain-loader menu-entry-chain-loader
(default #f))) ; string, path of efi file
(define (report-menu-entry-error menu-entry)
(raise
(condition
(&message
(message
(format #f (G_ "invalid menu-entry: ~a") menu-entry)))
(&fix-hint
(hint
(G_ "Please chose only one of:
@enumerate
@item direct boot by specifying fields @code{linux},
@code{linux-arguments} and @code{linux-modules},
@item multiboot by specifying fields @code{multiboot-kernel},
@code{multiboot-arguments} and @code{multiboot-modules},
@item chain-loader by specifying field @code{chain-loader}.
@end enumerate"))))))
(define (menu-entry->sexp entry)
"Return ENTRY serialized as an sexp."
(define (device->sexp device)
(match device
((? uuid? uuid)
`(uuid ,(uuid-type uuid) ,(uuid->string uuid)))
((? file-system-label? label)
`(label ,(file-system-label->string label)))
(_ device)))
(match entry
(($ <menu-entry> label device mount-point
(? identity linux) linux-arguments (? identity initrd)
#f () () #f)
(($ <menu-entry> label device mount-point linux linux-arguments initrd #f
())
`(menu-entry (version 0)
(label ,label)
(device ,(device->sexp device))
(device ,device)
(device-mount-point ,mount-point)
(linux ,linux)
(linux-arguments ,linux-arguments)
(initrd ,initrd)))
(($ <menu-entry> label device mount-point #f () #f
(? identity multiboot-kernel) multiboot-arguments
multiboot-modules #f)
multiboot-kernel multiboot-arguments multiboot-modules)
`(menu-entry (version 0)
(label ,label)
(device ,(device->sexp device))
(device ,device)
(device-mount-point ,mount-point)
(multiboot-kernel ,multiboot-kernel)
(multiboot-arguments ,multiboot-arguments)
(multiboot-modules ,multiboot-modules)))
(($ <menu-entry> label device mount-point #f () #f #f () ()
(? identity chain-loader))
`(menu-entry (version 0)
(label ,label)
(device ,(device->sexp device))
(device-mount-point ,mount-point)
(chain-loader ,chain-loader)))
(_ (report-menu-entry-error entry))))
(multiboot-modules ,multiboot-modules)))))
(define (sexp->menu-entry sexp)
"Turn SEXP, an sexp as returned by 'menu-entry->sexp', into a <menu-entry>
record."
(define (sexp->device device-sexp)
(match device-sexp
(('uuid type uuid-string)
(uuid uuid-string type))
(('label label)
(file-system-label label))
(_ device-sexp)))
(match sexp
(('menu-entry ('version 0)
('label label) ('device device)
@@ -186,7 +136,7 @@ record."
('initrd initrd) _ ...)
(menu-entry
(label label)
(device (sexp->device device))
(device device)
(device-mount-point mount-point)
(linux linux)
(linux-arguments linux-arguments)
@@ -199,20 +149,11 @@ record."
('multiboot-modules multiboot-modules) _ ...)
(menu-entry
(label label)
(device (sexp->device device))
(device device)
(device-mount-point mount-point)
(multiboot-kernel multiboot-kernel)
(multiboot-arguments multiboot-arguments)
(multiboot-modules multiboot-modules)))
(('menu-entry ('version 0)
('label label) ('device device)
('device-mount-point mount-point)
('chain-loader chain-loader) _ ...)
(menu-entry
(label label)
(device (sexp->device device))
(device-mount-point mount-point)
(chain-loader chain-loader)))))
(multiboot-modules multiboot-modules)))))
;;;
@@ -253,33 +194,29 @@ instead~%")))
(define-record-type* <bootloader-configuration>
bootloader-configuration make-bootloader-configuration
bootloader-configuration?
(bootloader
bootloader-configuration-bootloader) ;<bootloader>
(targets %bootloader-configuration-targets
(default #f)) ;list of strings
(target %bootloader-configuration-target ;deprecated
(default #f)
(sanitize warn-target-field-deprecation))
(menu-entries bootloader-configuration-menu-entries
(default '())) ;list of <menu-entry>
(default-entry bootloader-configuration-default-entry
(default 0)) ;integer
(timeout bootloader-configuration-timeout
(default 5)) ;seconds as integer
(keyboard-layout bootloader-configuration-keyboard-layout
(default #f)) ;<keyboard-layout> | #f
(theme bootloader-configuration-theme
(default #f)) ;bootloader-specific theme
(terminal-outputs bootloader-configuration-terminal-outputs
(default '(gfxterm))) ;list of symbols
(terminal-inputs bootloader-configuration-terminal-inputs
(default '())) ;list of symbols
(serial-unit bootloader-configuration-serial-unit
(default #f)) ;integer | #f
(serial-speed bootloader-configuration-serial-speed
(default #f)) ;integer | #f
(device-tree-support? bootloader-configuration-device-tree-support?
(default #t))) ;boolean
(bootloader bootloader-configuration-bootloader) ;<bootloader>
(targets %bootloader-configuration-targets ;list of strings
(default #f))
(target %bootloader-configuration-target ;deprecated
(default #f) (sanitize warn-target-field-deprecation))
(menu-entries bootloader-configuration-menu-entries ;list of <menu-entry>
(default '()))
(default-entry bootloader-configuration-default-entry ;integer
(default 0))
(timeout bootloader-configuration-timeout ;seconds as integer
(default 5))
(keyboard-layout bootloader-configuration-keyboard-layout ;<keyboard-layout> | #f
(default #f))
(theme bootloader-configuration-theme ;bootloader-specific theme
(default #f))
(terminal-outputs bootloader-configuration-terminal-outputs ;list of symbols
(default '(gfxterm)))
(terminal-inputs bootloader-configuration-terminal-inputs ;list of symbols
(default '()))
(serial-unit bootloader-configuration-serial-unit ;integer | #f
(default #f))
(serial-speed bootloader-configuration-serial-speed ;integer | #f
(default #f)))
(define-deprecated (bootloader-configuration-target config)
bootloader-configuration-targets
@@ -322,22 +259,26 @@ instead~%")))
(force %bootloaders))
(leave (G_ "~a: no such bootloader~%") name)))
(define (efi-bootloader-profile packages files hooks)
"Creates a profile from the lists of PACKAGES and FILES from the store.
This profile is meant to be used by the bootloader-installer.
(define (efi-bootloader-profile files bootloader-package hooks)
"Creates a profile with BOOTLOADER-PACKAGE and a directory collection/ with
links to additional FILES from the store. This collection is meant to be used
by the bootloader installer.
FILES is a list of file or directory names from the store, which will be
symlinked into the profile. If a directory name ends with '/', then the
directory content instead of the directory itself will be symlinked into the
profile.
symlinked into the collection/ directory. If a directory name ends with '/',
then the directory content instead of the directory itself will be symlinked
into the collection/ directory.
FILES may contain file like objects produced by procedures like plain-file,
FILES may contain file like objects produced by functions like plain-file,
local-file, etc., or package contents produced with file-append.
HOOKS lists additional hook functions to modify the profile."
(define (efi-bootloader-profile-hook manifest)
(define (bootloader-collection manifest)
(define build
(with-imported-modules '((guix build utils))
(with-imported-modules '((guix build utils)
(ice-9 ftw)
(srfi srfi-1)
(srfi srfi-26))
#~(begin
(use-modules ((guix build utils)
#:select (mkdir-p strip-store-file-name))
@@ -361,7 +302,8 @@ HOOKS lists additional hook functions to modify the profile."
(define (name-is-store-entry? name)
"Return #t if NAME is a direct store entry and nothing inside."
(not (string-index (strip-store-file-name name) #\/)))
(let* ((files '#$files)
(let* ((collection (string-append #$output "/collection"))
(files '#$files)
(directories (filter name-ends-with-/? files))
(names-from-directories
(append-map (lambda (directory)
@@ -369,11 +311,11 @@ HOOKS lists additional hook functions to modify the profile."
directories))
(names (append names-from-directories
(remove name-ends-with-/? files))))
(mkdir-p #$output)
(mkdir-p collection)
(if (every file-exists? names)
(begin
(for-each (lambda (name)
(symlink-to name #$output
(symlink-to name collection
(if (name-is-store-entry? name)
strip-store-file-name
basename)))
@@ -381,63 +323,57 @@ HOOKS lists additional hook functions to modify the profile."
#t)
#f)))))
(gexp->derivation "efi-bootloader-profile"
(gexp->derivation "bootloader-collection"
build
#:local-build? #t
#:substitutable? #f
#:properties
`((type . profile-hook)
(hook . efi-bootloader-profile-hook))))
(hook . bootloader-collection))))
(profile (content (packages->manifest packages))
(name "efi-bootloader-profile")
(hooks (cons efi-bootloader-profile-hook hooks))
(profile (content (packages->manifest (list bootloader-package)))
(name "bootloader-profile")
(hooks (append (list bootloader-collection) hooks))
(locales? #f)
(allow-collisions? #f)
(relative-symlinks? #f)))
(define* (efi-bootloader-chain final-bootloader
(define* (efi-bootloader-chain files
final-bootloader
#:key
(packages '())
(files '())
(hooks '())
installer
disk-image-installer)
"Define a chain of bootloaders with the FINAL-BOOTLOADER, optional PACKAGES,
and optional directories and files from the store given in the list of FILES.
installer)
"Define a bootloader chain with FINAL-BOOTLOADER as the final bootloader and
certain directories and files from the store given in the list of FILES.
The package of the FINAL-BOOTLOADER and all PACKAGES and FILES will be placed
in an efi-bootloader-profile, which will be passed to the INSTALLER.
FILES may contain file-like objects produced by procedures like plain-file,
local-file, etc., or package contents produced with file-append.
FILES may contain file like objects produced by functions like plain-file,
local-file, etc., or package contents produced with file-append. They will be
collected inside a directory collection/ inside a generated bootloader profile,
which will be passed to the INSTALLER.
If a directory name in FILES ends with '/', then the directory content instead
of the directory itself will be symlinked into the efi-bootloader-profile.
of the directory itself will be symlinked into the collection/ directory.
The procedures in the HOOKS list can be used to further modify the bootloader
profile. It is possible to pass a single function instead of a list.
If the INSTALLER argument is used, then this gexp procedure will be called to
install the efi-bootloader-profile. Otherwise the installer of the
FINAL-BOOTLOADER will be called.
If the DISK-IMAGE-INSTALLER is used, then this gexp procedure will be called
to install the efi-bootloader-profile into a disk image. Otherwise the
disk-image-installer of the FINAL-BOOTLOADER will be called."
(bootloader
(inherit final-bootloader)
(name "efi-bootloader-chain")
(package
(efi-bootloader-profile (cons (bootloader-package final-bootloader)
packages)
files
(if (list? hooks)
hooks
(list hooks))))
(installer
(or installer
(bootloader-installer final-bootloader)))
(disk-image-installer
(or disk-image-installer
(bootloader-disk-image-installer final-bootloader)))))
If the INSTALLER argument is used, then this function will be called to install
the bootloader. Otherwise the installer of the FINAL-BOOTLOADER will be called."
(let* ((final-installer (or installer
(bootloader-installer final-bootloader)))
(profile (efi-bootloader-profile files
(bootloader-package final-bootloader)
(if (list? hooks)
hooks
(list hooks)))))
(bootloader
(inherit final-bootloader)
(package profile)
(installer
#~(lambda (bootloader target mount-point)
(#$final-installer bootloader target mount-point)
(copy-recursively
(string-append bootloader "/collection")
(string-append mount-point target)
#:follow-symlinks? #t
#:log (%make-void-port "w")))))))
+2 -10
View File
@@ -1,7 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2017 David Craven <david@craven.ch>
;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
;;; Copyright © 2022 Reza Alizadeh Majd <r.majd@pantherx.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -39,9 +38,6 @@ corresponding to old generations of the system."
(define all-entries
(append entries (bootloader-configuration-menu-entries config)))
(define with-fdtdir?
(bootloader-configuration-device-tree-support? config))
(define (menu-entry->gexp entry)
(let ((label (menu-entry-label entry))
(kernel (menu-entry-linux entry))
@@ -50,16 +46,12 @@ corresponding to old generations of the system."
#~(format port "LABEL ~a
MENU LABEL ~a
KERNEL ~a
~a
FDTDIR ~a/lib/dtbs
INITRD ~a
APPEND ~a
~%"
#$label #$label
#$kernel
(if #$with-fdtdir?
(string-append "FDTDIR " (dirname #$kernel) "/lib/dtbs")
"")
#$initrd
#$kernel (dirname #$kernel) #$initrd
(string-join (list #$@kernel-arguments)))))
(define builder
+112 -253
View File
@@ -3,12 +3,10 @@
;;; Copyright © 2016 Chris Marusich <cmmarusich@gmail.com>
;;; Copyright © 2017 Leo Famulari <leo@famulari.name>
;;; Copyright © 2017, 2020 Mathieu Othacehe <m.othacehe@gmail.com>
;;; Copyright © 2019, 2020, 2023 Janneke Nieuwenhuizen <janneke@gnu.org>
;;; Copyright © 2019, 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
;;; Copyright © 2019, 2020 Miguel Ángel Arruga Vivas <rosen644835@gmail.com>
;;; Copyright © 2020 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;; Copyright © 2020 Stefan <stefan-guix@vodafonemail.de>
;;; Copyright © 2022 Karl Hallsby <karl@hallsby.com>
;;; Copyright © 2022 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -52,15 +50,11 @@
grub-theme-color-highlight
grub-theme-gfxmode
install-grub-efi-removable
make-grub-efi-netboot-installer
install-grub-efi-netboot
grub-bootloader
grub-efi-bootloader
grub-efi-removable-bootloader
grub-efi32-bootloader
grub-efi-netboot-bootloader
grub-efi-netboot-removable-bootloader
grub-mkrescue-bootloader
grub-minimal-bootloader
@@ -354,7 +348,7 @@ code."
((or #f (? string?))
#~(format #f "search --file --set ~a" #$file)))))
(define* (make-grub-configuration grub config entries
(define* (grub-configuration-file config entries
#:key
(locale #f)
(system (%current-system))
@@ -375,63 +369,44 @@ when booting a root file system on a Btrfs subvolume."
(let ((label (menu-entry-label entry))
(linux (menu-entry-linux entry))
(device (menu-entry-device entry))
(device-mount-point (menu-entry-device-mount-point entry))
(multiboot-kernel (menu-entry-multiboot-kernel entry))
(chain-loader (menu-entry-chain-loader entry)))
(cond
(linux
(let ((arguments (menu-entry-linux-arguments entry))
(linux (normalize-file linux
device-mount-point
store-directory-prefix))
(initrd (normalize-file (menu-entry-initrd entry)
device-mount-point
store-directory-prefix)))
;; Here DEVICE is the store and DEVICE-MOUNT-POINT is its mount point.
;; Use the right file names for LINUX and INITRD in case
;; DEVICE-MOUNT-POINT is not "/", meaning that the store is on a
;; separate partition.
(device-mount-point (menu-entry-device-mount-point entry)))
(if linux
(let ((arguments (menu-entry-linux-arguments entry))
(linux (normalize-file linux
device-mount-point
store-directory-prefix))
(initrd (normalize-file (menu-entry-initrd entry)
device-mount-point
store-directory-prefix)))
;; Here DEVICE is the store and DEVICE-MOUNT-POINT is its mount point.
;; Use the right file names for LINUX and INITRD in case
;; DEVICE-MOUNT-POINT is not "/", meaning that the store is on a
;; separate partition.
;; When STORE-DIRECTORY-PREFIX is defined, prepend it the linux and
;; initrd paths, to allow booting from a Btrfs subvolume.
#~(format port "menuentry ~s {
;; When BTRFS-SUBVOLUME-FILE-NAME is defined, prepend it the linux and
;; initrd paths, to allow booting from a Btrfs subvolume.
#~(format port "menuentry ~s {
~a
linux ~a ~a
initrd ~a
}~%"
#$label
#$(grub-root-search device linux)
#$linux (string-join (list #$@arguments))
#$initrd)))
(multiboot-kernel
(let* ((kernel (menu-entry-multiboot-kernel entry))
(arguments (menu-entry-multiboot-arguments entry))
;; Choose between device names as understood by Mach's built-in
;; IDE driver ("hdX") and those understood by rumpdisk ("wdX"
;; in the "noide" case).
(disk (if (member "noide" arguments) "w" "h"))
(modules (menu-entry-multiboot-modules entry))
(root-index 1)) ; XXX EFI will need root-index 2
#~(format port "
menuentry ~s {
multiboot ~a root=part:~a:device:~ad0~a~a
}~%"
#$label
#$kernel
#$root-index
#$disk
(string-join (list #$@arguments) " " 'prefix)
(string-join (map string-join '#$modules)
"\n module " 'prefix))))
(chain-loader
#$label
#$(grub-root-search device linux)
#$linux (string-join (list #$@arguments))
#$initrd))
(let ((kernel (menu-entry-multiboot-kernel entry))
(arguments (menu-entry-multiboot-arguments entry))
(modules (menu-entry-multiboot-modules entry))
(root-index 1)) ; XXX EFI will need root-index 2
#~(format port "
menuentry ~s {
~a
chainloader ~a
multiboot ~a root=device:hd0s~a~a~a
}~%"
#$label
#$(grub-root-search device chain-loader)
#$chain-loader)))))
#$kernel
#$root-index (string-join (list #$@arguments) " " 'prefix)
(string-join (map string-join '#$modules)
"\n module " 'prefix))))))
(define (crypto-devices)
(define (crypto-device->cryptomount dev)
@@ -460,7 +435,9 @@ menuentry ~s {
(define locale-config
(let* ((entry (first all-entries))
(device (menu-entry-device entry))
(mount-point (menu-entry-device-mount-point entry)))
(mount-point (menu-entry-device-mount-point entry))
(bootloader (bootloader-configuration-bootloader config))
(grub (bootloader-package bootloader)))
#~(let ((locale #$(and locale
(locale-definition-source
(locale-name->definition locale))))
@@ -486,6 +463,8 @@ set lang=~a~%"
(define keyboard-layout-config
(let* ((layout (bootloader-configuration-keyboard-layout config))
(grub (bootloader-package
(bootloader-configuration-bootloader config)))
(keymap* (and layout
(keyboard-layout-file layout #:grub grub)))
(entry (first all-entries))
@@ -536,16 +515,6 @@ fi~%"))))
#:options '(#:local-build? #t
#:substitutable? #f)))
(define (grub-configuration-file config . args)
(let* ((bootloader (bootloader-configuration-bootloader config))
(grub (bootloader-package bootloader)))
(apply make-grub-configuration grub config args)))
(define (grub-efi-configuration-file . args)
(apply make-grub-configuration grub-efi args))
(define grub-cfg "/boot/grub/grub.cfg")
;;;
@@ -639,79 +608,42 @@ fi~%"))))
"--bootloader-id=Guix"
"--efi-directory" target-esp)))))
(define install-grub-efi-removable
#~(lambda (bootloader efi-dir mount-point)
;; NOTE: mount-point is /mnt in guix system init /etc/config.scm /mnt/point
;; NOTE: efi-dir comes from target list of booloader configuration
;; There is nothing useful to do when called in the context of a disk
;; image generation.
(when efi-dir
;; Install GRUB onto the EFI partition mounted at EFI-DIR, for the
;; system whose root is mounted at MOUNT-POINT.
(let ((grub-install (string-append bootloader "/sbin/grub-install"))
(install-dir (string-append mount-point "/boot"))
;; When installing Guix, it's common to mount EFI-DIR below
;; MOUNT-POINT rather than /boot/efi on the live image.
(target-esp (if (file-exists? (string-append mount-point efi-dir))
(string-append mount-point efi-dir)
efi-dir)))
;; Tell 'grub-install' that there might be a LUKS-encrypted /boot or
;; root partition.
(setenv "GRUB_ENABLE_CRYPTODISK" "y")
(invoke/quiet grub-install "--boot-directory" install-dir
"--removable"
;; "--no-nvram"
"--bootloader-id=Guix"
"--efi-directory" target-esp)))))
(define install-grub-efi32
#~(lambda (bootloader efi-dir mount-point)
;; There is nothing useful to do when called in the context of a disk
;; image generation.
(when efi-dir
;; Install GRUB onto the EFI partition mounted at EFI-DIR, for the
;; system whose root is mounted at MOUNT-POINT.
(let ((grub-install (string-append bootloader "/sbin/grub-install"))
(install-dir (string-append mount-point "/boot"))
;; When installing Guix, it's common to mount EFI-DIR below
;; MOUNT-POINT rather than /boot/efi on the live image.
(target-esp (if (file-exists? (string-append mount-point efi-dir))
(string-append mount-point efi-dir)
efi-dir)))
;; Tell 'grub-install' that there might be a LUKS-encrypted /boot or
;; root partition.
(setenv "GRUB_ENABLE_CRYPTODISK" "y")
(invoke/quiet grub-install "--boot-directory" install-dir
"--bootloader-id=Guix"
(cond ((target-x86?) "--target=i386-efi")
((target-arm?) "--target=arm-efi"))
"--efi-directory" target-esp)))))
(define* (make-grub-efi-netboot-installer grub-efi grub-cfg subdir)
"Make a bootloader-installer for a grub-efi-netboot bootloader, which expects
its files in SUBDIR and its configuration file in GRUB-CFG.
As a grub-efi-netboot package is already pre-installed by 'grub-mknetdir', the
installer basically copies all files from the bootloader-package (or profile)
into the bootloader-target directory.
Additionally for network booting over TFTP, two relative symlinks to the store
and to the GRUB-CFG file are necessary. Due to this a TFTP root directory must
not be located on a FAT file-system.
If the bootloader-target does not support symlinks, then it is assumed to be a
kind of EFI System Partition (ESP). In this case an intermediate configuration
file is created with the help of GRUB-EFI to load the GRUB-CFG.
The installer is usable for any efi-bootloader-chain, which prepares the
bootloader-profile in a way ready for copying.
The installer does not manipulate the system's 'UEFI Boot Manager'.
The returned installer accepts the BOOTLOADER, TARGET and MOUNT-POINT
arguments. Its job is to copy the BOOTLOADER, which must be a pre-installed
grub-efi-netboot package with a SUBDIR like efi/boot or efi/Guix, below the
directory TARGET for the system whose root is mounted at MOUNT-POINT.
(define (install-grub-efi-netboot subdir)
"Define a grub-efi-netboot bootloader installer for installation in SUBDIR,
which is usually efi/Guix or efi/boot."
(let* ((system (string-split (nix-system->gnu-triplet
(or (%current-target-system)
(%current-system)))
#\-))
(arch (first system))
(boot-efi-link (match system
;; These are the supportend systems and the names
;; defined by the UEFI standard for removable media.
(("i686" _ ...) "/bootia32.efi")
(("x86_64" _ ...) "/bootx64.efi")
(("arm" _ ...) "/bootarm.efi")
(("aarch64" _ ...) "/bootaa64.efi")
(("riscv" _ ...) "/bootriscv32.efi")
(("riscv64" _ ...) "/bootriscv64.efi")
;; Other systems are not supported, although defined.
;; (("riscv128" _ ...) "/bootriscv128.efi")
;; (("ia64" _ ...) "/bootia64.efi")
((_ ...) #f)))
(core-efi (string-append
;; This is the arch dependent file name of GRUB, e.g.
;; i368-efi/core.efi or arm64-efi/core.efi.
(match arch
("i686" "i386")
("aarch64" "arm64")
("riscv" "riscv32")
(_ arch))
"-efi/core.efi")))
(with-imported-modules
'((guix build union))
#~(lambda (bootloader target mount-point)
"Install the BOOTLOADER, which must be the package grub, as e.g.
bootx64.efi or bootaa64.efi into SUBDIR, which is usually efi/Guix or efi/boot,
below the directory TARGET for the system whose root is mounted at MOUNT-POINT.
MOUNT-POINT is the last argument in 'guix system init /etc/config.scm mnt/point'
or '/' for other 'guix system' commands.
@@ -721,19 +653,17 @@ bootloader-configuration in:
(operating-system
(bootloader (bootloader-configuration
(targets '(\"/boot/efi\"))
(targets '(\"/boot\"))
))
)
TARGET is required to be an absolute directory name, usually mounted via NFS,
and finally needs to be provided by a TFTP server as
the TFTP root directory.
and finally needs to be provided by a TFTP server as the TFTP root directory.
Usually the installer will be used to prepare network booting over TFTP. Then
GRUB will load tftp://server/SUBDIR/grub.cfg and this file will instruct it to
load more files from the store like tftp://server/gnu/store/-linux/Image.
To make this possible two symlinks are created. The first symlink points
To make this possible two symlinks will be created. The first symlink points
relatively form MOUNT-POINT/TARGET/SUBDIR/grub.cfg to
MOUNT-POINT/boot/grub/grub.cfg, and the second symlink points relatively from
MOUNT-POINT/TARGET/%store-prefix to MOUNT-POINT/%store-prefix.
@@ -743,80 +673,34 @@ paths on the TFTP server side are unknown.
It is also important to note that both symlinks will point outside the TFTP root
directory and that the TARGET/%store-prefix symlink makes the whole store
accessible via TFTP. Possibly the TFTP server must be configured to allow
accesses outside its TFTP root directory. This all may need to be considered
for security aspects. It is advised to disable any TFTP write access!
The installer can also be used to prepare booting from local storage, if the
underlying file-system, like FAT on an EFI System Partition (ESP), does not
support symlinks. In this case the MOUNT-POINT/TARGET/SUBDIR/grub.cfg will be
created with the help of GRUB-EFI to load the /boot/grub/grub.cfg file. A
symlink to the store is not needed in this case."
(with-imported-modules '((guix build union))
#~(lambda (bootloader target mount-point)
;; In context of a disk image creation TARGET will be #f and an
;; installer is expected to do necessary installations on MOUNT-POINT,
;; which will become the root file system. If TARGET is #f, this
;; installer has nothing to do, as it only cares about the EFI System
;; Partition (ESP).
(when target
(use-modules ((guix build union) #:select (symlink-relative))
(ice-9 popen)
(ice-9 rdelim))
(let* ((mount-point/target (string-append mount-point target "/"))
;; When installing Guix, it is common to mount TARGET below
;; MOUNT-POINT rather than the root directory.
(bootloader-target (if (file-exists? mount-point/target)
mount-point/target
target))
(store (string-append mount-point (%store-prefix)))
(store-link (string-append bootloader-target (%store-prefix)))
(grub-cfg (string-append mount-point #$grub-cfg))
(grub-cfg-link (string-append bootloader-target
#$subdir "/"
(basename grub-cfg))))
;; Copy the bootloader into the bootloader-target directory.
;; Should we beforehand recursively delete any existing file?
(copy-recursively bootloader bootloader-target
#:follow-symlinks? #t
#:log (%make-void-port "w"))
;; For TFTP we need to install additional relative symlinks.
;; If we install on an EFI System Partition (ESP) or some other FAT
;; file-system, then symlinks cannot be created and are not needed.
;; Therefore we ignore exceptions when trying.
;; Prepare the symlink to the grub.cfg.
(mkdir-p (dirname grub-cfg-link))
(false-if-exception (delete-file grub-cfg-link))
(if (unspecified?
(false-if-exception (symlink-relative grub-cfg grub-cfg-link)))
;; Symlinks are supported.
(begin
;; Prepare the symlink to the store.
(mkdir-p (dirname store-link))
(false-if-exception (delete-file store-link))
(symlink-relative store store-link))
;; Creating symlinks does not seem to be supported. Probably
;; an ESP is used. Add a script to search and load the actual
;; grub.cfg.
(let* ((probe #$(file-append grub-efi "/sbin/grub-probe"))
(port (open-pipe* OPEN_READ probe "--target=fs_uuid"
grub-cfg))
(search-root
(match (read-line port)
((? eof-object?)
;; There is no UUID available. As a fallback search
;; everywhere for the grub.cfg.
(string-append "search --file --set " #$grub-cfg))
(fs-uuid
;; The UUID to load the grub.cfg from is known.
(string-append "search --fs-uuid --set " fs-uuid))))
(load-grub-cfg (string-append "configfile " #$grub-cfg)))
(close-pipe port)
(with-output-to-file grub-cfg-link
(lambda ()
(display (string-join (list search-root
load-grub-cfg)
"\n")))))))))))
accessible via TFTP. Possibly the TFTP server must be configured
to allow accesses outside its TFTP root directory. This may need to be
considered for security aspects."
(use-modules ((guix build union) #:select (symlink-relative)))
(let* ((net-dir (string-append mount-point target "/"))
(sub-dir (string-append net-dir #$subdir "/"))
(store (string-append mount-point (%store-prefix)))
(store-link (string-append net-dir (%store-prefix)))
(grub-cfg (string-append mount-point "/boot/grub/grub.cfg"))
(grub-cfg-link (string-append sub-dir (basename grub-cfg)))
(boot-efi-link (string-append sub-dir #$boot-efi-link)))
;; Prepare the symlink to the store.
(mkdir-p (dirname store-link))
(false-if-exception (delete-file store-link))
(symlink-relative store store-link)
;; Prepare the symlink to the grub.cfg, which points into the store.
(mkdir-p (dirname grub-cfg-link))
(false-if-exception (delete-file grub-cfg-link))
(symlink-relative grub-cfg grub-cfg-link)
;; Install GRUB, which refers to the grub.cfg, with support for
;; encrypted partitions,
(setenv "GRUB_ENABLE_CRYPTODISK" "y")
(invoke/quiet (string-append bootloader "/bin/grub-mknetdir")
(string-append "--net-directory=" net-dir)
(string-append "--subdir=" #$subdir))
;; Prepare the bootloader symlink, which points to core.efi of GRUB.
(false-if-exception (delete-file boot-efi-link))
(symlink #$core-efi boot-efi-link))))))
@@ -834,7 +718,7 @@ symlink to the store is not needed in this case."
(package grub)
(installer install-grub)
(disk-image-installer install-grub-disk-image)
(configuration-file grub-cfg)
(configuration-file "/boot/grub/grub.cfg")
(configuration-file-generator grub-configuration-file)))
(define grub-minimal-bootloader
@@ -844,42 +728,17 @@ symlink to the store is not needed in this case."
(define grub-efi-bootloader
(bootloader
(name 'grub-efi)
(package grub-efi)
(inherit grub-bootloader)
(installer install-grub-efi)
(disk-image-installer #f)
(configuration-file grub-cfg)
(configuration-file-generator grub-configuration-file)))
(define grub-efi-removable-bootloader
(bootloader
(inherit grub-efi-bootloader)
(name 'grub-efi-removable-bootloader)
(installer install-grub-efi-removable)))
(define grub-efi32-bootloader
(bootloader
(inherit grub-efi-bootloader)
(installer install-grub-efi32)
(name 'grub-efi32)
(package grub-efi32)))
(define (make-grub-efi-netboot-bootloader name subdir)
(bootloader
(name name)
(package (make-grub-efi-netboot (symbol->string name) subdir))
(installer (make-grub-efi-netboot-installer grub-efi grub-cfg subdir))
(disk-image-installer #f)
(configuration-file grub-cfg)
(configuration-file-generator grub-efi-configuration-file)))
(name 'grub-efi)
(package grub-efi)))
(define grub-efi-netboot-bootloader
(make-grub-efi-netboot-bootloader 'grub-efi-netboot-bootloader
"efi/Guix"))
(define grub-efi-netboot-removable-bootloader
(make-grub-efi-netboot-bootloader 'grub-efi-netboot-removable-bootloader
"efi/boot"))
(bootloader
(inherit grub-efi-bootloader)
(name 'grub-efi-netboot-bootloader)
(installer (install-grub-efi-netboot "efi/Guix"))))
(define grub-mkrescue-bootloader
(bootloader
-35
View File
@@ -3,8 +3,6 @@
;;; Copyright © 2017, 2019 Mathieu Othacehe <m.othacehe@gmail.com>
;;; Copyright © 2020 Julien Lepiller <julien@lepiller.eu>
;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
;;; Copyright © 2022 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;; Copyright © 2023 Efraim Flashner <efraim@flashner.co.il>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -44,8 +42,6 @@
u-boot-puma-rk3399-bootloader
u-boot-rock64-rk3328-bootloader
u-boot-rockpro64-rk3399-bootloader
u-boot-sifive-unmatched-bootloader
u-boot-ts7970-q-2g-1000mhz-c-bootloader
u-boot-wandboard-bootloader))
(define install-u-boot
@@ -131,21 +127,6 @@
(define install-pinebook-pro-rk3399-u-boot install-rockpro64-rk3399-u-boot)
(define install-u-boot-ts7970-q-2g-1000mhz-c-u-boot
#~(lambda (bootloader device mount-point)
(let ((u-boot.imx (string-append bootloader "/libexec/u-boot.imx"))
(install-dir (string-append mount-point "/boot")))
(install-file u-boot.imx install-dir))))
(define install-sifive-unmatched-u-boot
#~(lambda (bootloader root-index image)
(let ((spl (string-append bootloader "/libexec/spl/u-boot-spl.bin"))
(u-boot (string-append bootloader "/libexec/u-boot.itb")))
(write-file-on-device spl (stat:size (stat spl))
image (* 34 512))
(write-file-on-device u-boot (stat:size (stat u-boot))
image (* 2082 512)))))
;;;
@@ -274,19 +255,3 @@
(inherit u-boot-bootloader)
(package u-boot-pinebook-pro-rk3399)
(disk-image-installer install-pinebook-pro-rk3399-u-boot)))
(define u-boot-ts7970-q-2g-1000mhz-c-bootloader
;; This bootloader doesn't really need to be installed, as it is read from
;; an SPI memory chip, not the SD card. It is copied to /boot/u-boot.imx
;; for convenience and should be manually flashed at the U-Boot prompt.
(bootloader
(inherit u-boot-bootloader)
(package u-boot-ts7970-q-2g-1000mhz-c)
(installer install-u-boot-ts7970-q-2g-1000mhz-c-u-boot)
(disk-image-installer #f)))
(define u-boot-sifive-unmatched-bootloader
(bootloader
(inherit u-boot-bootloader)
(package u-boot-sifive-unmatched)
(disk-image-installer install-sifive-unmatched-u-boot)))
+3 -8
View File
@@ -363,14 +363,9 @@ second element is the name it should appear at, such as:
"Tell the kernel to look for device firmware under DIRECTORY. This
mechanism bypasses udev: it allows Linux to handle firmware loading directly
by itself, without having to resort to a \"user helper\"."
;; If the kernel was built without firmware loading support, this file
;; does not exist. Do nothing in that case.
(let ((firmware-path "/sys/module/firmware_class/parameters/path"))
(when (file-exists? firmware-path)
(call-with-output-file firmware-path
(lambda (port)
(display directory port))))))
(call-with-output-file "/sys/module/firmware_class/parameters/path"
(lambda (port)
(display directory port))))
(define (activate-ptrace-attach)
"Allow users to PTRACE_ATTACH their own processes.
+13 -24
View File
@@ -1,8 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
;;; Copyright © 2019 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2022 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
;;; Copyright © 2022 Timothy Sample <samplet@ngyro.com>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -56,12 +54,8 @@
;;; EFI bootloader.
;;;
(define* (install-efi grub grub-config esp #:key targets)
"Write a self-contained GRUB EFI loader to the mounted ESP using
GRUB-CONFIG.
If TARGETS is set, use its car as the GRUB image format and its cdr as
the output filename. Otherwise, use defaults for the host platform."
(define (install-efi grub grub-config esp)
"Write a self-contained GRUB EFI loader to the mounted ESP using GRUB-CONFIG."
(let* ((system %host-type)
;; Hard code the output location to a well-known path recognized by
;; compliant firmware. See "3.5.1.1 Removable Media Boot Behaviour":
@@ -69,15 +63,14 @@ the output filename. Otherwise, use defaults for the host platform."
(grub-mkstandalone (string-append grub "/bin/grub-mkstandalone"))
(efi-directory (string-append esp "/EFI/BOOT"))
;; Map grub target names to boot file names.
(efi-targets (or targets
(cond ((string-prefix? "x86_64" system)
'("x86_64-efi" . "BOOTX64.EFI"))
((string-prefix? "i686" system)
'("i386-efi" . "BOOTIA32.EFI"))
((string-prefix? "armhf" system)
'("arm-efi" . "BOOTARM.EFI"))
((string-prefix? "aarch64" system)
'("arm64-efi" . "BOOTAA64.EFI"))))))
(efi-targets (cond ((string-prefix? "x86_64" system)
'("x86_64-efi" . "BOOTX64.EFI"))
((string-prefix? "i686" system)
'("i386-efi" . "BOOTIA32.EFI"))
((string-prefix? "armhf" system)
'("arm-efi" . "BOOTARM.EFI"))
((string-prefix? "aarch64" system)
'("arm64-efi" . "BOOTAA64.EFI")))))
;; grub-mkstandalone requires a TMPDIR to prepare the firmware image.
(setenv "TMPDIR" esp)
@@ -88,12 +81,9 @@ the output filename. Otherwise, use defaults for the host platform."
;; Graft the configuration file onto the image.
(string-append "boot/grub/grub.cfg=" grub-config))))
(define* (install-efi-loader grub-efi esp #:key targets)
(define (install-efi-loader grub-efi esp)
"Install in ESP directory the given GRUB-EFI bootloader. Configure it to
load the Grub bootloader located in the 'Guix_image' root partition.
If TARGETS is set, use its car as the GRUB image format and its cdr as
the output filename. Otherwise, use defaults for the host platform."
load the Grub bootloader located in the 'Guix_image' root partition."
(let ((grub-config "grub.cfg"))
(call-with-output-file grub-config
(lambda (port)
@@ -107,6 +97,5 @@ the output filename. Otherwise, use defaults for the host platform."
insmod part_gpt~@
search --set=root --label Guix_image~@
configfile /boot/grub/grub.cfg~%")))
(install-efi grub-efi grub-config esp #:targets targets)
(install-efi grub-efi grub-config esp)
(delete-file grub-config)))
+14 -4
View File
@@ -1,6 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2020, 2021 Marius Bakke <marius@gnu.org>
;;; Copyright © 2022 Nicolas Graves <ngraves@ngraves.fr>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -20,9 +19,10 @@
(define-module (gnu build chromium-extension)
#:use-module (guix gexp)
#:use-module (guix packages)
#:use-module (gnu packages chromium)
#:use-module (gnu packages gnupg)
#:use-module (gnu packages tls)
#:use-module (gnu packages node-xyz)
#:use-module (gnu packages xorg)
#:use-module (guix build-system trivial)
#:export (make-chromium-extension))
@@ -69,14 +69,24 @@ in PACKAGE-OUTPUT of PACKAGE. The extension will be signed with SIGNING-KEY."
(string-append name "-" version ".crx")
(with-imported-modules '((guix build utils))
#~(begin
;; This is not great. We pull Xorg and Chromium just to Zip and
;; sign an extension. This should be implemented with something
;; lighter. (TODO: where is the CRXv3 documentation..?)
(use-modules (guix build utils))
(let ((crx3 #+(file-append node-crx3 "/bin/crx3"))
(let ((chromium #$(file-append ungoogled-chromium "/bin/chromium"))
(xvfb #$(file-append xorg-server "/bin/Xvfb"))
(packdir (string-append (getcwd) "/extension")))
(mkdir packdir)
(copy-recursively (ungexp package package-output) packdir
;; Ensure consistent file modification times.
#:keep-mtime? #t)
(invoke crx3 "--keyPath" #$signing-key packdir)
(system (string-append xvfb " :1 &"))
(setenv "DISPLAY" ":1")
(sleep 2) ;give Xorg some time to initialize...
(invoke chromium
"--user-data-dir=chromium-profile"
(string-append "--pack-extension=" packdir)
(string-append "--pack-extension-key=" #$signing-key))
(copy-file (string-append packdir ".crx") #$output))))
#:local-build? #t))
-213
View File
@@ -1,213 +0,0 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2021, 2022 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;;
;;; This module contains procedures to interact with D-Bus via the 'dbus-send'
;;; command line utility. Before using any public procedure
;;;
;;; Code:
(define-module (gnu build dbus-service)
#:use-module (ice-9 match)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-19)
#:use-module (srfi srfi-26)
#:autoload (d-bus protocol connections) (d-bus-conn?
d-bus-conn-flush
d-bus-connect
d-bus-disconnect
d-bus-session-bus-address
d-bus-system-bus-address)
#:autoload (d-bus protocol messages) (MESSAGE_TYPE_METHOD_CALL
d-bus-headers-ref
d-bus-message-body
d-bus-message-headers
d-bus-read-message
d-bus-write-message
header-PATH
header-DESTINATION
header-INTERFACE
header-MEMBER
header-SIGNATURE
make-d-bus-message)
#:export (%dbus-query-timeout
initialize-dbus-connection!
%current-dbus-connection
send-dbus
call-dbus-method
dbus-available-services
dbus-service-available?
with-retries))
(define %dbus-query-timeout 2) ;in seconds
;;; Use Fibers' sleep to enable cooperative scheduling in Shepherd >= 0.9.0,
;;; which is required at least for the Jami service.
(define sleep*
(lambda () ;delay execution
(if (resolve-module '(fibers) #f #:ensure #f)
(module-ref (resolve-interface '(fibers)) 'sleep)
(begin
(format #t "Fibers not available -- blocking 'sleep' in use~%")
sleep))))
;;;
;;; Utilities.
;;;
(define-syntax-rule (with-retries n delay body ...)
"Retry the code in BODY up to N times until it doesn't raise an exception nor
return #f, else raise an error. A delay of DELAY seconds is inserted before
each retry."
(let loop ((attempts 0))
(catch #t
(lambda ()
(let ((result (begin body ...)))
(if (not result)
(error "failed attempt" attempts)
result)))
(lambda args
(if (< attempts n)
(begin
((sleep*) delay) ;else wait and retry
(loop (+ 1 attempts)))
(error "maximum number of retry attempts reached"
body ... args))))))
;;;
;;; Low level wrappers above AC/D-Bus.
;;;
;; The active D-Bus connection (a parameter) used by the other procedures.
(define %current-dbus-connection (make-parameter #f))
(define* (initialize-dbus-connection!
#:key (address (or (d-bus-session-bus-address)
(d-bus-system-bus-address))))
"Initialize the D-Bus connection. ADDRESS should be the address of the D-Bus
session, e.g. \"unix:path=/var/run/dbus/system_bus_socket\", the default value
if ADDRESS is not provided and DBUS_SESSION_BUS_ADDRESS is not set. Return
the initialized D-Bus connection."
;; Clear current correction if already active.
(when (d-bus-conn? (%current-dbus-connection))
(d-bus-disconnect (%current-dbus-connection)))
(let ((connection (d-bus-connect address)))
(%current-dbus-connection connection) ;update connection parameter
(call-dbus-method "Hello")) ;initial handshake
(%current-dbus-connection))
(define* (send-dbus message #:key
(connection (%current-dbus-connection))
timeout)
"Send a D-Bus MESSAGE to CONNECTION and return the body of its reply. Up to
READ-RETRIES replies are read until a matching reply is found, else an error
is raised. MESSAGE is to be constructed with `make-d-bus-message'. When the
body contains a single element, it is returned directly, else the body
elements are returned as a list. TIMEOUT is a timeout value in seconds."
(let ((serial (d-bus-write-message connection message))
(start-time (current-time time-monotonic))
(timeout* (or timeout %dbus-query-timeout)))
(d-bus-conn-flush connection)
(let retry ()
(when (> (time-second (time-difference (current-time time-monotonic)
start-time))
timeout*)
(error 'dbus "fail to get reply in timeout" timeout*))
(let* ((reply (d-bus-read-message connection))
(reply-headers (d-bus-message-headers reply))
(reply-serial (d-bus-headers-ref reply-headers 'REPLY_SERIAL))
(error-name (d-bus-headers-ref reply-headers 'ERROR_NAME))
(body (d-bus-message-body reply)))
;; Validate the reply matches the message.
(when error-name
(error 'dbus "method failed with error" error-name body))
;; Some replies do not include a serial header, such as the for the
;; org.freedesktop.DBus NameAcquired one.
(if (and reply-serial (= serial reply-serial))
(match body
((x x* ..1) ;contains 2 ore more elements
body)
((x)
x) ;single element; return it directly
(#f #f))
(retry))))))
(define (argument->signature-type argument)
"Infer the D-Bus signature type from ARGUMENT."
;; XXX: avoid ..1 when using vectors due to a bug (?) in (ice-9 match).
(match argument
((? boolean?) "b")
((? string?) "s")
(#((? string?) (? string?) ...) "as")
(#(((? string?) . (? string?))
((? string?) . (? string?)) ...) "a{ss}")
(_ (error 'dbus "no rule to infer type from argument" argument))))
(define* (call-dbus-method method
#:key
(path "/org/freedesktop/DBus")
(destination "org.freedesktop.DBus")
(interface "org.freedesktop.DBus")
(connection (%current-dbus-connection))
arguments
timeout)
"Call the D-Bus method specified by METHOD, PATH, DESTINATION and INTERFACE.
The currently active D-Bus CONNECTION is used unless explicitly provided.
Method arguments may be provided via ARGUMENTS sent as the message body.
TIMEOUT limit the maximum time to allow for the reply. Return the body of the
reply."
(let ((message (make-d-bus-message
MESSAGE_TYPE_METHOD_CALL 0 #f '()
`#(,(header-PATH path)
,(header-DESTINATION destination)
,(header-INTERFACE interface)
,(header-MEMBER method)
,@(if arguments
(list (header-SIGNATURE
(string-join
(map argument->signature-type arguments)
"")))
'()))
arguments)))
(send-dbus message #:connection connection #:timeout timeout)))
;;;
;;; Higher-level, D-Bus procedures.
;;;
(define (dbus-available-services)
"Return the list of available (acquired) D-Bus services."
(let ((names (vector->list (call-dbus-method "ListNames"))))
;; Remove entries such as ":1.7".
(remove (cut string-prefix? ":" <>) names)))
(define (dbus-service-available? service)
"Predicate to check for the D-Bus SERVICE availability."
(member service (dbus-available-services)))
;; Local Variables:
;; eval: (put 'with-retries 'scheme-indent-function 2)
;; End:
+47 -125
View File
@@ -1,12 +1,11 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2014-2018, 2020-2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2014, 2015, 2016, 2017, 2018, 2020, 2021 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2016, 2017 David Craven <david@craven.ch>
;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
;;; Copyright © 2019 Guillaume Le Vaillant <glv@posteo.net>
;;; Copyright © 20192021 Tobias Geerinckx-Rice <me@tobias.gr>
;;; Copyright © 2019 David C. Trudgian <dave@trudgian.net>
;;; Copyright © 2020 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;; Copyright © 2022 Oleg Pykhalov <go.wigust@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -53,11 +52,8 @@
read-partition-uuid
read-luks-partition-uuid
cleanly-unmounted-ext2?
bind-mount
system*/tty
mount-flags->bit-mask
check-file-system
mount-file-system
@@ -71,45 +67,6 @@
;;;
;;; Code:
(define (system*/console program . args)
"Run PROGRAM with ARGS in a tty on top of /dev/console. The return value is
as for 'system*'."
(match (primitive-fork)
(0
(dynamic-wind
(const #t)
(lambda ()
(login-tty (open-fdes "/dev/console" O_RDWR))
(apply execlp program program args))
(lambda ()
(primitive-_exit 127))))
(pid
(cdr (waitpid pid)))))
(define (system*/tty program . args)
"Run PROGRAM with ARGS, creating a tty if its standard input isn't one.
The return value is as for 'system*'.
This is necessary for commands such as 'cryptsetup open' or 'fsck' that may
need to interact with the user but might be invoked from shepherd, where
standard input is /dev/null."
(apply (if (isatty? (current-input-port))
system*
system*/console)
program args))
(define (call-with-input-file file proc)
"Like 'call-with-input-file', but pass O_CLOEXEC."
(let ((port #f))
(dynamic-wind
(lambda ()
(set! port (open file (logior O_RDONLY O_CLOEXEC))))
(lambda ()
(proc port))
(lambda ()
(close-port port)
(set! port #f)))))
(define (bind-mount source target)
"Bind-mount SOURCE at TARGET."
(mount source target "" MS_BIND))
@@ -208,23 +165,6 @@ NUL terminator, return the size of the bytevector."
if DEVICE does not contain an ext2 file system."
(read-superblock device 1024 264 ext2-superblock?))
(define (ext2-superblock-cleanly-unmounted? sblock)
"Return true if SBLOCK denotes a file system that was cleanly unmounted,
false otherwise."
(define EXT2_VALID_FS 1) ;cleanly unmounted
(define EXT2_ERROR_FS 2) ;errors detected
(define EXT3_FEATURE_INCOMPAT_RECOVER #x0004) ;journal needs recovery
(let ((state (bytevector-u16-ref sblock 58 %ext2-endianness)))
(cond ((= state EXT2_VALID_FS)
(let ((incompatible-features
(bytevector-u32-ref sblock 96 %ext2-endianness)))
(zero? (logand incompatible-features
EXT3_FEATURE_INCOMPAT_RECOVER))))
((= state EXT2_ERROR_FS) #f)
(else (error "invalid ext2 superblock state" state)))))
(define (ext2-superblock-uuid sblock)
"Return the UUID of ext2 superblock SBLOCK as a 16-byte bytevector."
(sub-bytevector sblock 104 16))
@@ -240,23 +180,18 @@ true, check the file system even if it's marked as clean. If REPAIR is false,
do not write to the file system to fix errors. If it's #t, fix all
errors. Otherwise, fix only those considered safe to repair automatically."
(match (status:exit-val
(apply system*/tty "e2fsck" "-v" "-C" "0"
`(,@(if force? '("-f") '())
,@(match repair
(#f '("-n"))
(#t '("-y"))
(_ '("-p")))
,device)))
(apply system* `("e2fsck" "-v" "-C" "0"
,@(if force? '("-f") '())
,@(match repair
(#f '("-n"))
(#t '("-y"))
(_ '("-p")))
,device)))
(0 'pass)
(1 'errors-corrected)
(2 'reboot-required)
(_ 'fatal-error)))
(define (cleanly-unmounted-ext2? device) ;convenience procedure
"Return true if DEVICE is an ext2 file system and if it was cleanly
unmounted."
(ext2-superblock-cleanly-unmounted? (read-ext2-superblock device)))
;;;
;;; Linux swap.
@@ -377,14 +312,14 @@ errors. Otherwise, fix only those considered safe to repair automatically."
(status
;; A number, or #f on abnormal termination (e.g., assertion failure).
(status:exit-val
(apply system*/tty "bcachefs" "fsck" "-v"
`(,@(if force? '("-f") '())
,@(match repair
(#f '("-n"))
(#t '("-y"))
(_ '("-p")))
;; Make each multi-device member a separate argument.
,@(string-split device #\:))))))
(apply system* `("bcachefs" "fsck" "-v"
,@(if force? '("-f") '())
,@(match repair
(#f '("-n"))
(#t '("-y"))
(_ '("-p")))
;; Make each multi-device member a separate argument.
,@(string-split device #\:))))))
(match (and=> status (cut logand <> (lognot ignored-bits)))
(0 'pass)
(1 'errors-corrected)
@@ -429,17 +364,17 @@ false, do not write to DEVICE. If it's #t, fix any errors found. Otherwise,
fix only those considered safe to repair automatically."
(if force?
(match (status:exit-val
(apply system*/tty "btrfs" "check" "--progress"
;; Btrfs's --force is not relevant to us here.
`(,@(match repair
;; Upstream considers ALL repairs dangerous
;; and will warn the user at run time.
(#t '("--repair"))
(_ '("--readonly" ; a no-op for clarity
;; A 466G file system with 180G used is
;; enough to kill btrfs with 6G of RAM.
"--mode" "lowmem")))
,device)))
(apply system* `("btrfs" "check" "--progress"
;; Btrfs's --force is not relevant to us here.
,@(match repair
;; Upstream considers ALL repairs dangerous
;; and will warn the user at run time.
(#t '("--repair"))
(_ '("--readonly" ; a no-op for clarity
;; A 466G file system with 180G used is
;; enough to kill btrfs with 6G of RAM.
"--mode" "lowmem")))
,device)))
(0 'pass)
(_ 'fatal-error))
'pass))
@@ -477,11 +412,11 @@ ignored: a full file system scan is always performed. If REPAIR is false, do
not write to the file system to fix errors. Otherwise, automatically fix them
using the least destructive approach."
(match (status:exit-val
(system*/tty "fsck.vfat" "-v"
(match repair
(#f "-n")
(_ "-a")) ;no 'safe/#t distinction
device))
(apply system* `("fsck.vfat" "-v"
,@(match repair
(#f '("-n"))
(_ '("-a"))) ; no 'safe/#t distinction
,device)))
(0 'pass)
(1 'errors-corrected)
(_ 'fatal-error)))
@@ -610,7 +545,7 @@ do not write to the file system to fix errors, and replay the transaction log
only if FORCE? is true. Otherwise, replay the transaction log before checking
and automatically fix found errors."
(match (status:exit-val
(apply system*/tty
(apply system*
`("jfs_fsck" "-v"
;; The LEVEL logic is convoluted. To quote fsck/xchkdsk.c
;; (-p, -a, and -r are aliases in every way):
@@ -686,10 +621,10 @@ REPAIR are true, automatically fix found errors."
"warning: forced check of F2FS ~a implies repairing any errors~%"
device))
(match (status:exit-val
(apply system*/tty "fsck.f2fs"
`(,@(if force? '("-f") '())
,@(if repair '("-p") '("--dry-run"))
,device)))
(apply system* `("fsck.f2fs"
,@(if force? '("-f") '())
,@(if repair '("-p") '("--dry-run"))
,device)))
;; 0 and -1 are the only two possibilities according to the man page.
(0 'pass)
(_ 'fatal-error)))
@@ -774,9 +709,9 @@ ignored: a full check is always performed. Repair is not possible: if REPAIR is
true and the volume has been repaired by an external tool, clear the volume
dirty flag to indicate that it's now safe to mount."
(match (status:exit-val
(system*/tty "ntfsfix"
(if repair "--clear-dirty" "--no-action")
device))
(apply system* `("ntfsfix"
,@(if repair '("--clear-dirty") '("--no-action"))
,device)))
(0 'pass)
(_ 'fatal-error)))
@@ -819,11 +754,11 @@ write to DEVICE. If it's #t, replay the log, check, and fix any errors found.
Otherwise, only replay the log, and check without attempting further repairs."
(define (xfs_repair)
(status:exit-val
(system*/tty "xfs_repair" "-Pv"
(match repair
(#t "-e")
(_ "-n")) ;will miss some errors
device)))
(apply system* `("xfs_repair" "-Pv"
,@(match repair
(#t '("-e"))
(_ '("-n"))) ; will miss some errors
,device))))
(if force?
;; xfs_repair fails with exit status 2 if the log is dirty, which is
;; likely in situations where you're running xfs_repair. Only the kernel
@@ -899,10 +834,6 @@ caught and lead to a warning and #f as the result."
(format (current-error-port)
"warning: failed to read from device '~a'~%" device)
#f)
((= EMEDIUMTYPE errno) ;inaccessible, like DRBD secondaries
(format (current-error-port)
"warning: failed to open device '~a'~%" device)
#f)
(else
(apply throw args))))))))
@@ -1123,12 +1054,11 @@ an exception in such cases but perform the nearest sane action."
"Return the number suitable for the 'flags' argument of 'mount' that
corresponds to the symbols listed in FLAGS."
(let loop ((flags flags))
;; Note: Keep in sync with invalid-file-system-flags.
(match flags
(('read-only rest ...)
(logior MS_RDONLY (loop rest)))
(('bind-mount rest ...)
(logior MS_REC (logior MS_BIND (loop rest))))
(logior MS_BIND (loop rest)))
(('no-suid rest ...)
(logior MS_NOSUID (loop rest)))
(('no-dev rest ...)
@@ -1137,14 +1067,10 @@ corresponds to the symbols listed in FLAGS."
(logior MS_NOEXEC (loop rest)))
(('no-atime rest ...)
(logior MS_NOATIME (loop rest)))
(('no-diratime rest ...)
(logior MS_NODIRATIME (loop rest)))
(('strict-atime rest ...)
(logior MS_STRICTATIME (loop rest)))
(('lazy-time rest ...)
(logior MS_LAZYTIME (loop rest)))
(('shared rest ...)
(loop rest))
(()
0))))
@@ -1202,16 +1128,12 @@ corresponds to the symbols listed in FLAGS."
(not (file-is-directory? source)))
(unless (file-exists? target)
(mkdir-p (dirname target))
(close-fdes
(open-fdes target (logior O_WRONLY O_CREAT O_CLOEXEC))))
(call-with-output-file target (const #t)))
(mkdir-p target))
(cond
((string-prefix? "nfs" type)
(mount-nfs source target type flags options))
((memq 'shared (file-system-flags fs))
(mount source target type flags options)
(mount "none" target #f MS_SHARED))
(else
(mount source target type flags options)))
+28 -63
View File
@@ -1,6 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2020-2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2020, 2023 Janneke Nieuwenhuizen <janneke@gnu.org>
;;; Copyright © 2020, 2021 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -105,7 +105,7 @@ Return the value associated with OPTION, or #f on failure."
;; TODO: Set the 'gnu.translator' extended attribute for passive translator
;; settings?
(mkdir-p (scope "servers/bus/pci")))
)
(define (passive-translator-xattr? file-name)
"Return true if FILE-NAME has an extended @code{gnu.translator} attribute
@@ -127,9 +127,6 @@ set."
(define (translated? file-name)
"Return true if a translator is installed on FILE-NAME."
;; On GNU/Hurd, 'getxattr' in glibc opens the file without O_NOTRANS, and
;; then, for "gnu.translator", it calls 'file_get_translator', resulting in
;; EOPNOTSUPP (conversely, 'showtrans' opens the file with O_NOTRANS).
(if (string-contains %host-type "linux-gnu")
(passive-translator-xattr? file-name)
(passive-translator-installed? file-name)))
@@ -183,8 +180,7 @@ set."
(mkdir-p dir))))
(define servers
'(("servers/bus/pci" ("/hurd/pci-arbiter"))
("servers/crash-dump-core" ("/hurd/crash" "--dump-core"))
'(("servers/crash-dump-core" ("/hurd/crash" "--dump-core"))
("servers/crash-kill" ("/hurd/crash" "--kill"))
("servers/crash-suspend" ("/hurd/crash" "--suspend"))
("servers/password" ("/hurd/password"))
@@ -195,7 +191,7 @@ set."
("proc" ("/hurd/procfs" "--stat-mode=444"))))
(define devices
`(("dev/full" ("/hurd/null" "--full") #o666)
'(("dev/full" ("/hurd/null" "--full") #o666)
("dev/null" ("/hurd/null") #o666)
("dev/random" ("/hurd/random" "--seed-file" "/var/lib/random-seed")
#o644)
@@ -214,58 +210,31 @@ set."
;; 'fd_to_filename' in libc expects it.
("dev/fd" ("/hurd/magic" "--directory" "fd") #o555)
("dev/rumpdisk" ("/hurd/rumpdisk") #o660)
("dev/netdde" ("/hurd/netdde") #o660)
("dev/eth0" ("/hurd/devnode" "--master-device=/dev/net"
"eth0")
#o660)
("dev/eth1" ("/hurd/devnode" "--master-device=/dev/net"
"eth1")
#o660)
("dev/tty1" ("/hurd/term" "/dev/tty1" "hurdio" "/dev/vcs/1/console")
#o666)
("dev/tty2" ("/hurd/term" "/dev/tty2" "hurdio" "/dev/vcs/2/console")
#o666)
("dev/tty3" ("/hurd/term" "/dev/tty3" "hurdio" "/dev/vcs/3/console")
#o666)
;; Create a number of ttys; syslogd writes to tty12 by default.
;; FIXME: Creating /dev/tty12 leads the console client to switch to
;; tty12 when syslogd starts, which is confusing for users. Thus, do
;; not create tty12.
,@(map (lambda (n)
(let ((n (number->string n)))
`(,(string-append "dev/tty" n)
("/hurd/term" ,(string-append "/dev/tty" n)
"hurdio" ,(string-append "/dev/vcs/" n "/console"))
#o666)))
(iota 11 1))
("dev/ptyp0" ("/hurd/term" "/dev/ptyp0" "pty-master" "/dev/ttyp0")
#o666)
("dev/ptyp1" ("/hurd/term" "/dev/ptyp1" "pty-master" "/dev/ttyp1")
#o666)
("dev/ptyp2" ("/hurd/term" "/dev/ptyp2" "pty-master" "/dev/ttyp2")
#o666)
,@(append-map (lambda (n)
(let ((n (number->string n)))
`((,(string-append "dev/ptyp" n)
("/hurd/term" ,(string-append "/dev/ptyp" n)
"pty-master" ,(string-append "/dev/ttyp" n))
#o666)
(,(string-append "dev/ttyp" n)
("/hurd/term" ,(string-append "/dev/ttyp" n)
"pty-slave" ,(string-append "/dev/ptyp" n))
#o666))))
(iota 10 0))
,@(append-map (lambda (n)
(let* ((n (number->string n))
(drive (string-append "dev/wd" n))
(disk (string-append "@/dev/disk:wd" n)))
`((,drive ("/hurd/storeio" ,disk) #o600)
,@(map (lambda (p)
(let ((p (number->string p)))
`(,(string-append drive "s" p)
("/hurd/storeio"
"--store-type=typed"
,(string-append
"part:" p ":device:" disk))
#o660)))
(iota 4 1)))))
(iota 4 0))))
("dev/ttyp0" ("/hurd/term" "/dev/ttyp0" "pty-slave" "/dev/ptyp0")
#o666)
("dev/ttyp1" ("/hurd/term" "/dev/ttyp1" "pty-slave" "/dev/ptyp1")
#o666)
("dev/ttyp2" ("/hurd/term" "/dev/ttyp2" "pty-slave" "/dev/ptyp2")
#o666)))
(for-each scope-set-translator servers)
(mkdir* "dev/vcs/1")
(mkdir* "dev/vcs/2")
(mkdir* "dev/vcs/2")
(rename-file (scope "dev/console") (scope "dev/console-"))
(for-each scope-set-translator devices)
@@ -274,10 +243,6 @@ set."
(false-if-EEXIST (symlink "/dev/fd/1" (scope "dev/stdout")))
(false-if-EEXIST (symlink "/dev/fd/2" (scope "dev/stderr")))
(false-if-EEXIST (symlink "crash-dump-core" (scope "servers/crash")))
(false-if-EEXIST (symlink "/dev/rumpdisk" (scope "dev/disk")))
(false-if-EEXIST (symlink "/dev/netdde" (scope "dev/net")))
(false-if-EEXIST (symlink "/servers/socket/2" (scope "servers/socket/inet")))
(false-if-EEXIST (symlink "/servers/socket/26" (scope "servers/socket/inet6")))
;; Make sure /etc/mtab is a symlink to /proc/mounts.
(false-if-exception (delete-file (scope "etc/mtab")))
@@ -309,14 +274,14 @@ XXX TODO: use Linux xattr/setxattr to remove (settrans in) /libexec/RUNSYSTEM
(system (find-long-option "gnu.system" args))
(to-load (find-long-option "gnu.load" args)))
(false-if-exception (delete-file "/hurd"))
(let ((hurd/hurd (readlink* (string-append system "/profile/hurd"))))
(symlink hurd/hurd "/hurd"))
(format #t "Setting-up essential translators...\n")
(setenv "PATH" (string-append system "/profile/bin"))
(set-hurd-device-translators)
(false-if-exception (delete-file "/hurd"))
(let ((hurd/hurd (readlink* (string-append system "/profile/hurd"))))
(symlink hurd/hurd "/hurd"))
(format #t "Starting pager...\n")
(unless (zero? (system* "/hurd/mach-defpager"))
(format #t "FAILED...Good luck!\n"))
+13 -50
View File
@@ -5,9 +5,6 @@
;;; Copyright © 2017 Marius Bakke <mbakke@fastmail.com>
;;; Copyright © 2020, 2022 Tobias Geerinckx-Rice <me@tobias.gr>
;;; Copyright © 2020 Mathieu Othacehe <m.othacehe@gmail.com>
;;; Copyright © 2022 Pavel Shlyak <p.shlyak@pantherx.org>
;;; Copyright © 2022 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
;;; Copyright © 2023 Efraim Flashner <efraim@flashner.co.il>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -29,7 +26,6 @@
#:use-module (guix build syscalls)
#:use-module (guix build utils)
#:use-module (guix store database)
#:use-module (guix utils)
#:use-module (gnu build bootloader)
#:use-module (gnu build install)
#:use-module (gnu build linux-boot)
@@ -44,7 +40,6 @@
convert-disk-image
genimage
initialize-efi-partition
initialize-efi32-partition
initialize-root-partition
make-iso9660-image))
@@ -53,13 +48,12 @@
"Take SEXP, a tuple as returned by 'partition->gexp', and turn it into a
<partition> record."
(match sexp
((size file-system file-system-options label uuid flags)
((size file-system file-system-options label uuid)
(partition (size size)
(file-system file-system)
(file-system-options file-system-options)
(label label)
(uuid uuid)
(flags flags)))))
(uuid uuid)))))
(define (size-in-kib size)
"Convert SIZE expressed in bytes, to kilobytes and return it as a string."
@@ -87,10 +81,7 @@ turn doesn't take any constant overhead into account, force a 1-MiB minimum."
(journal-options "lazy_itable_init=1,lazy_journal_init=1"))
(apply invoke
`("fakeroot" "mke2fs" "-t" ,fs "-d" ,root
"-L" ,label
,@(if uuid
`("-U" ,(uuid->string uuid))
'())
"-L" ,label "-U" ,(uuid->string uuid)
"-E" ,(format #f "root_owner=~a:~a,~a"
owner-uid owner-gid journal-options)
,@fs-options
@@ -101,21 +92,16 @@ turn doesn't take any constant overhead into account, force a 1-MiB minimum."
(estimate-partition-size root)
size)))))))
(define* (make-vfat-image partition target root fs-bits)
(define* (make-vfat-image partition target root)
"Handle the creation of VFAT partition images. See 'make-partition-image'."
(let ((size (partition-size partition))
(label (partition-label partition))
(flags (partition-flags partition)))
(apply invoke "fakeroot" "mkdosfs" "-n" label "-C" target
"-F" (number->string fs-bits)
(size-in-kib
(if (eq? size 'guess)
(estimate-partition-size root)
size))
;; u-boot in particular needs the formatted block
;; size and the physical block size to be equal.
;; TODO: What about 4k blocks?
(if (member 'esp flags) (list "-S" "512") '()))
(label (partition-label partition)))
(invoke "fakeroot" "mkdosfs" "-n" label "-C" target
"-F" "16" "-S" "1024"
(size-in-kib
(if (eq? size 'guess)
(estimate-partition-size root)
size)))
(for-each (lambda (file)
(unless (member file '("." ".."))
(invoke "mcopy" "-bsp" "-i" target
@@ -123,14 +109,6 @@ turn doesn't take any constant overhead into account, force a 1-MiB minimum."
(string-append "::" file))))
(scandir root))))
(define* (make-unformatted-image partition target)
"Make an unformatted partition of a certain size."
(let ((size (partition-size partition)))
;; Create the file and then truncate it to the desired size.
(with-output-to-file target
(lambda _ (display "")))
(truncate-file target size)))
(define* (make-partition-image partition-sexp target root)
"Create and return the image of PARTITION-SEXP as TARGET. Use the given
ROOT directory to populate the image."
@@ -139,12 +117,8 @@ ROOT directory to populate the image."
(cond
((string-prefix? "ext" type)
(make-ext-image partition target root))
((or (string=? type "vfat") (string=? type "fat16"))
(make-vfat-image partition target root 16))
((string=? type "fat32")
(make-vfat-image partition target root 32))
((string=? type "unformatted")
(make-unformatted-image partition target))
((string=? type "vfat")
(make-vfat-image partition target root))
(else
(raise (condition
(&message
@@ -188,17 +162,6 @@ produced by #:references-graphs. Pass WAL-MODE? to call-with-database."
"Install in ROOT directory, an EFI loader using GRUB-EFI."
(install-efi-loader grub-efi root))
(define* (initialize-efi32-partition root
#:key
grub-efi32
#:allow-other-keys)
"Install in ROOT directory, an EFI 32bit loader using GRUB-EFI32."
(install-efi-loader grub-efi32 root
#:targets (cond ((target-x86?)
'("i386-efi" . "BOOTIA32.EFI"))
((target-arm?)
'("arm-efi" . "BOOTARM.EFI")))))
(define* (initialize-root-partition root
#:key
bootcfg
+22 -61
View File
@@ -1,7 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2013-2020, 2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2016 Chris Marusich <cmmarusich@gmail.com>
;;; Copyright © 2022 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -57,24 +56,19 @@ that the fonts, background images, etc. referred to by BOOTCFG are not GC'd."
(define* (evaluate-populate-directive directive target
#:key
(default-gid 0)
(default-uid 0)
(error-on-dangling-symlink? #t))
(default-uid 0))
"Evaluate DIRECTIVE, an sexp describing a file or directory to create under
directory TARGET. DEFAULT-UID and DEFAULT-GID are the default UID and GID in
the context of the caller. If the directive matches those defaults then,
'chown' won't be run. When ERROR-ON-DANGLING-SYMLINK? is true, abort with an
error when a dangling symlink would be created."
(define target* (if (string-suffix? "/" target)
target
(string-append target "/")))
'chown' won't be run."
(let loop ((directive directive))
(catch 'system-error
(lambda ()
(match directive
(('directory name)
(mkdir-p (string-append target* name)))
(mkdir-p (string-append target name)))
(('directory name uid gid)
(let ((dir (string-append target* name)))
(let ((dir (string-append target name)))
(mkdir-p dir)
;; If called from a context without "root" permissions, "chown"
;; to root will fail. In that case, do not try to run "chown"
@@ -84,38 +78,27 @@ error when a dangling symlink would be created."
(chown dir uid gid))))
(('directory name uid gid mode)
(loop `(directory ,name ,uid ,gid))
(chmod (string-append target* name) mode))
(chmod (string-append target name) mode))
(('file name)
(call-with-output-file (string-append target* name)
(call-with-output-file (string-append target name)
(const #t)))
(('file name (? string? content))
(call-with-output-file (string-append target* name)
(call-with-output-file (string-append target name)
(lambda (port)
(display content port))))
((new '-> old)
(let ((new* (string-append target* new)))
(let try ()
(catch 'system-error
(lambda ()
(when error-on-dangling-symlink?
;; When the symbolic link points to a relative path,
;; checking if its target exists must be done relatively
;; to the link location.
(unless (if (string-prefix? "/" old)
(file-exists? old)
(with-directory-excursion (dirname new*)
(file-exists? old)))
(error (format #f "symlink `~a' points to nonexistent \
file `~a'" new* old))))
(symlink old new*))
(lambda args
;; When doing 'guix system init' on the current '/', some
;; symlinks may already exists. Override them.
(if (= EEXIST (system-error-errno args))
(begin
(delete-file new*)
(try))
(apply throw args)))))))))
(let try ()
(catch 'system-error
(lambda ()
(symlink old (string-append target new)))
(lambda args
;; When doing 'guix system init' on the current '/', some
;; symlinks may already exists. Override them.
(if (= EEXIST (system-error-errno args))
(begin
(delete-file (string-append target new))
(try))
(apply throw args))))))))
(lambda args
;; Usually we can only get here when installing to an existing root,
;; as with 'guix system init foo.scm /'.
@@ -159,10 +142,7 @@ STORE."
includes /etc, /var, /run, /bin/sh, etc., and all the symlinks to SYSTEM.
EXTRAS is a list of directives appended to the built-in directives to populate
TARGET."
;; It's expected that some symbolic link targets do not exist yet, so do not
;; error on dangling links.
(for-each (cut evaluate-populate-directive <> target
#:error-on-dangling-symlink? #f)
(for-each (cut evaluate-populate-directive <> target)
(append (directives (%store-directory)) extras))
;; Add system generation 1.
@@ -282,31 +262,12 @@ disk."
(mount "/.rw-store" (%store-directory) "" MS_MOVE)
(rmdir "/.rw-store")))
(define (umount* directory)
"Unmount DIRECTORY, but retry a few times upon EBUSY."
(let loop ((attempts 5))
(catch 'system-error
(lambda ()
(umount directory))
(lambda args
(if (and (= EBUSY (system-error-errno args))
(> attempts 0))
(begin
(sleep 1)
(loop (- attempts 1)))
(apply throw args))))))
(define (unmount-cow-store target backing-directory)
"Unmount copy-on-write store."
(let ((tmp-dir "/remove"))
(mkdir-p tmp-dir)
(mount (%store-directory) tmp-dir "" MS_MOVE)
;; We might get EBUSY at this point, possibly because of lingering
;; processes with open file descriptors. Use 'umount*' to retry upon
;; EBUSY, leaving a bit of time. See <https://issues.guix.gnu.org/59884>.
(umount* tmp-dir)
(umount tmp-dir)
(rmdir tmp-dir)
(delete-file-recursively
(string-append target backing-directory))))
+328 -69
View File
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2021, 2022 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;; Copyright © 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -24,16 +24,16 @@
;;; Code:
(define-module (gnu build jami-service)
#:use-module (gnu build dbus-service)
#:use-module (ice-9 format)
#:use-module (ice-9 match)
#:use-module (ice-9 peg)
#:use-module (ice-9 rdelim)
#:use-module (ice-9 regex)
#:use-module (rnrs io ports)
#:autoload (shepherd service) (fork+exec-command)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-26)
#:export (jami-service-available?
account-fingerprint?
#:export (account-fingerprint?
account-details->recutil
get-accounts
get-usernames
@@ -51,12 +51,43 @@
set-all-moderators
set-moderator
username->all-moderators?
username->moderators))
username->moderators
dbus-available-services
dbus-service-available?
%send-dbus-binary
%send-dbus-bus
%send-dbus-user
%send-dbus-group
%send-dbus-debug
send-dbus
with-retries))
;;;
;;; Utilities.
;;;
(define-syntax-rule (with-retries n delay body ...)
"Retry the code in BODY up to N times until it doesn't raise an exception
nor return #f, else raise an error. A delay of DELAY seconds is inserted
before each retry."
(let loop ((attempts 0))
(catch #t
(lambda ()
(let ((result (begin body ...)))
(if (not result)
(error "failed attempt" attempts)
result)))
(lambda args
(if (< attempts n)
(begin
(sleep delay) ;else wait and retry
(loop (+ 1 attempts)))
(error "maximum number of retry attempts reached"
body ... args))))))
(define (alist->list alist)
"Flatten ALIST into a list."
(append-map (match-lambda
@@ -73,34 +104,212 @@ hexadecimal characters."
(and (string? val)
(regexp-exec account-fingerprint-rx val)))
;;;
;;; D-Bus reply parser.
;;;
(define (parse-dbus-reply reply)
"Return the parse tree of REPLY, a string returned by the 'dbus-send'
command."
;; Refer to 'man 1 dbus-send' for the grammar reference. Note that the
;; format of the replies doesn't match the format of the input, which is the
;; one documented, but it gives an idea. For an even better reference, see
;; the `print_iter' procedure of the 'dbus-print-message.c' file from the
;; 'dbus' package sources.
(define-peg-string-patterns
"contents <- header (item / container (item / container*)?)
item <-- WS type WS value NL
container <- array / dict / variant
array <-- array-start (item / container)* array-end
dict <-- array-start dict-entry* array-end
dict-entry <-- dict-entry-start item item dict-entry-end
variant <-- variant-start item
type <-- 'string' / 'int16' / 'uint16' / 'int32' / 'uint32' / 'int64' /
'uint64' / 'double' / 'byte' / 'boolean' / 'objpath'
value <-- (!NL .)* NL
header < (!NL .)* NL
variant-start < WS 'variant'
array-start < WS 'array [' NL
array-end < WS ']' NL
dict-entry-start < WS 'dict entry(' NL
dict-entry-end < WS ')' NL
DQ < '\"'
WS < ' '*
NL < '\n'*")
(peg:tree (match-pattern contents reply)))
(define (strip-quotes text)
"Strip the leading and trailing double quotes (\") characters from TEXT."
(let* ((text* (if (string-prefix? "\"" text)
(string-drop text 1)
text))
(text** (if (string-suffix? "\"" text*)
(string-drop-right text* 1)
text*)))
text**))
(define (deserialize-item item)
"Return the value described by the ITEM parse tree as a Guile object."
;; Strings are printed wrapped in double quotes (see the print_iter
;; procedure in dbus-print-message.c).
(match item
(('item ('type "string") ('value value))
(strip-quotes value))
(('item ('type "boolean") ('value value))
(if (string=? "true" value)
#t
#f))
(('item _ ('value value))
value)))
(define (serialize-boolean bool)
"Return the serialized format expected by dbus-send for BOOL."
(format #f "boolean:~:[false~;true~]" bool))
(define (dict->alist dict-parse-tree)
"Translate a dict parse tree to an alist."
(define (tuples->alist tuples)
(map (lambda (x) (apply cons x)) tuples))
(match dict-parse-tree
('dict
'())
(('dict ('dict-entry keys values) ...)
(let ((keys* (map deserialize-item keys))
(values* (map deserialize-item values)))
(tuples->alist (zip keys* values*))))))
(define (array->list array-parse-tree)
"Translate an array parse tree to a list."
(match array-parse-tree
('array
'())
(('array items ...)
(map deserialize-item items))))
;;;
;;; Low-level, D-Bus-related procedures.
;;;
;;; The following parameters are used in the jami-service-type service
;;; definition to conveniently customize the behavior of the send-dbus helper,
;;; even when called indirectly.
(define %send-dbus-binary (make-parameter "dbus-send"))
(define %send-dbus-bus (make-parameter #f))
(define %send-dbus-user (make-parameter #f))
(define %send-dbus-group (make-parameter #f))
(define %send-dbus-debug (make-parameter #f))
(define* (send-dbus #:key service path interface method
bus
dbus-send
user group
timeout
arguments)
"Return the response of DBUS-SEND, else raise an error. Unless explicitly
provided, DBUS-SEND takes the value of the %SEND-DBUS-BINARY parameter. BUS
can be used to specify the bus address, such as 'unix:path=/var/run/jami/bus'.
Alternatively, the %SEND-DBUS-BUS parameter can be used. ARGUMENTS can be
used to pass input values to a D-Bus method call. TIMEOUT is the amount of
time to wait for a reply in milliseconds before giving up with an error. USER
and GROUP allow choosing under which user/group the DBUS-SEND command is
executed. Alternatively, the %SEND-DBUS-USER and %SEND-DBUS-GROUP parameters
can be used instead."
(let* ((command `(,(if dbus-send
dbus-send
(%send-dbus-binary))
,@(if (or bus (%send-dbus-bus))
(list (string-append "--bus="
(or bus (%send-dbus-bus))))
'())
"--print-reply"
,@(if timeout
(list (format #f "--reply-timeout=~d" timeout))
'())
,(string-append "--dest=" service) ;e.g., cx.ring.Ring
,path ;e.g., /cx/ring/Ring/ConfigurationManager
,(string-append interface "." method)
,@(or arguments '())))
(temp-port (mkstemp! (string-copy "/tmp/dbus-send-output-XXXXXXX")))
(temp-file (port-filename temp-port)))
(dynamic-wind
(lambda ()
(let* ((uid (or (and=> (or user (%send-dbus-user))
(compose passwd:uid getpwnam)) -1))
(gid (or (and=> (or group (%send-dbus-group))
(compose group:gid getgrnam)) -1)))
(chown temp-port uid gid)))
(lambda ()
(let ((pid (fork+exec-command command
#:user (or user (%send-dbus-user))
#:group (or group (%send-dbus-group))
#:log-file temp-file)))
(match (waitpid pid)
((_ . status)
(let ((exit-status (status:exit-val status))
(output (call-with-port temp-port get-string-all)))
(if (= 0 exit-status)
output
(error "the send-dbus command exited with: "
command exit-status output)))))))
(lambda ()
(false-if-exception (delete-file temp-file))))))
(define (parse-account-ids reply)
"Return the Jami account IDs from REPLY, which is assumed to be the output
of the Jami D-Bus `getAccountList' method."
(array->list (parse-dbus-reply reply)))
(define (parse-account-details reply)
"Parse REPLY, which is assumed to be the output of the Jami D-Bus
`getAccountDetails' method, and return its content as an alist."
(dict->alist (parse-dbus-reply reply)))
(define (parse-contacts reply)
"Parse REPLY, which is assumed to be the output of the Jamid D-Bus
`getContacts' method, and return its content as an alist."
(match (parse-dbus-reply reply)
('array
'())
(('array dicts ...)
(map dict->alist dicts))))
;;;
;;; Higher-level, D-Bus-related procedures.
;;;
(define (validate-fingerprint fingerprint)
"Validate that fingerprint is 40 characters long."
(unless (account-fingerprint? fingerprint)
(error "Account fingerprint is not valid:" fingerprint)))
(define (jami-service-available?)
"Whether the Jami D-Bus service was acquired by the D-Bus daemon."
(unless (%current-dbus-connection)
(initialize-dbus-connection!))
(dbus-service-available? "cx.ring.Ring"))
(define (dbus-available-services)
"Return the list of available (acquired) D-Bus services."
(let ((reply (parse-dbus-reply
(send-dbus #:service "org.freedesktop.DBus"
#:path "/org/freedesktop/DBus"
#:interface "org.freedesktop.DBus"
#:method "ListNames"))))
;; Remove entries such as ":1.7".
(remove (cut string-prefix? ":" <>)
(array->list reply))))
;;;
;;; Bindings for the Jami D-Bus API.
;;;
(define (dbus-service-available? service)
"Predicate to check for the D-Bus SERVICE availability."
(member service (dbus-available-services)))
(define* (call-configuration-manager-method method #:optional arguments
#:key timeout)
"Query the Jami D-Bus ConfigurationManager interface with METHOD applied to
ARGUMENTS. TIMEOUT can optionally be provided as a value in seconds."
(unless (%current-dbus-connection)
(initialize-dbus-connection!))
(call-dbus-method method
#:path "/cx/ring/Ring/ConfigurationManager"
#:destination "cx.ring.Ring"
#:interface "cx.ring.Ring.ConfigurationManager"
#:arguments arguments
#:timeout timeout))
(define* (send-dbus/configuration-manager #:key method arguments timeout)
"Query the Jami D-Bus ConfigurationManager service."
(send-dbus #:service "cx.ring.Ring"
#:path "/cx/ring/Ring/ConfigurationManager"
#:interface "cx.ring.Ring.ConfigurationManager"
#:method method
#:arguments arguments
#:timeout timeout))
;;; The following methods are for internal use; they make use of the account
;;; ID, an implementation detail of Jami the user should not need to be
@@ -108,17 +317,22 @@ ARGUMENTS. TIMEOUT can optionally be provided as a value in seconds."
(define (get-account-ids)
"Return the available Jami account identifiers (IDs). Account IDs are an
implementation detail used to identify the accounts in Jami."
(vector->list (call-configuration-manager-method "getAccountList")))
(parse-account-ids
(send-dbus/configuration-manager #:method "getAccountList")))
(define (id->account-details id)
"Retrieve the account data associated with the given account ID."
(vector->list (call-configuration-manager-method "getAccountDetails"
(list id))))
(parse-account-details
(send-dbus/configuration-manager
#:method "getAccountDetails"
#:arguments (list (string-append "string:" id)))))
(define (id->volatile-account-details id)
"Retrieve the account data associated with the given account ID."
(vector->list (call-configuration-manager-method "getVolatileAccountDetails"
(list id))))
(parse-account-details
(send-dbus/configuration-manager
#:method "getVolatileAccountDetails"
#:arguments (list (string-append "string:" id)))))
(define (id->account id)
"Retrieve the complete account data associated with the given account ID."
@@ -148,16 +362,19 @@ implementation detail used to identify the accounts in Jami."
'()))))
(get-account-ids))))
(or (assoc-ref %username-to-id-cache username)
(let ((message (format #f "no account ID for ~:[username~;fingerprint~]"
(account-fingerprint? username))))
(let ((message (format #f "Could not retrieve a local account ID\
for ~:[username~;fingerprint~]" (account-fingerprint? username))))
(error message username))))
(define (account->username account)
"Return the public key fingerprint of ACCOUNT."
(assoc-ref account "Account.username"))
"Return USERNAME, the registered username associated with ACCOUNT, else its
public key fingerprint."
(or (assoc-ref account "Account.registeredName")
(assoc-ref account "Account.username")))
(define (id->username id)
"Return the public key fingerprint corresponding to account with ID, else #f."
"Return USERNAME, the registered username associated with ID, else its
public key fingerprint, else #f."
(account->username (id->account id)))
(define (get-accounts)
@@ -183,21 +400,27 @@ registered username."
should *not* be encrypted with a password. Return the username associated
with the account."
(invalidate-username-to-id-cache!)
(let ((id (call-configuration-manager-method
"addAccount" (list `#(("Account.archivePath" . ,archive)
("Account.type" . "RING"))))))
(let ((reply (send-dbus/configuration-manager
#:method "addAccount"
#:arguments (list (string-append
"dict:string:string:Account.archivePath,"
archive
",Account.type,RING")))))
;; The account information takes some time to be populated.
(with-retries 20 1
(let ((username (id->username id)))
(if (and=> username (negate string-null?))
username
#f)))))
(let ((id (deserialize-item (parse-dbus-reply reply))))
(with-retries 20 1
(let ((username (id->username id)))
(if (string-null? username)
#f
username))))))
(define (remove-account username)
"Delete the Jami account associated with USERNAME, the account 40 characters
fingerprint or a registered username."
(let ((id (username->id username)))
(call-configuration-manager-method "removeAccount" (list id)))
(send-dbus/configuration-manager
#:method "removeAccount"
#:arguments (list (string-append "string:" id))))
(invalidate-username-to-id-cache!))
(define* (username->contacts username)
@@ -207,16 +430,15 @@ contacts. USERNAME can be either the account 40 characters public key
fingerprint or a registered username. The contacts returned are represented
using their 40 characters fingerprint."
(let* ((id (username->id username))
;; The contacts are returned as "aa{ss}", that is, an array of arrays
;; containing (string . string) pairs.
(contacts (map vector->list
(vector->list (call-configuration-manager-method
"getContacts" (list id)))))
(reply (send-dbus/configuration-manager
#:method "getContacts"
#:arguments (list (string-append "string:" id))))
(all-contacts (parse-contacts reply))
(banned? (lambda (contact)
(and=> (assoc-ref contact "banned")
(cut string=? "true" <>))))
(banned (filter banned? contacts))
(not-banned (filter (negate banned?) contacts))
(banned (filter banned? all-contacts))
(not-banned (filter (negate banned?) all-contacts))
(fingerprint (cut assoc-ref <> "id")))
(values (map fingerprint not-banned)
(map fingerprint banned))))
@@ -227,20 +449,27 @@ the account associated with USERNAME (either a fingerprint or a registered
username). When BAN? is true, also mark the contact as banned."
(validate-fingerprint contact)
(let ((id (username->id username)))
(call-configuration-manager-method "removeContact" (list id contact ban?))))
(send-dbus/configuration-manager
#:method "removeContact"
#:arguments (list (string-append "string:" id)
(string-append "string:" contact)
(serialize-boolean ban?)))))
(define (add-contact contact username)
"Add CONTACT, the 40 characters public key fingerprint of a contact, to the
account of USERNAME (either a fingerprint or a registered username)."
(validate-fingerprint contact)
(let ((id (username->id username)))
(call-configuration-manager-method "addContact" (list id contact))))
(send-dbus/configuration-manager
#:method "addContact"
#:arguments (list (string-append "string:" id)
(string-append "string:" contact)))))
(define* (set-account-details details username #:key timeout)
"Set DETAILS, an alist containing the key value pairs to set for the account
of USERNAME, a registered username or account fingerprint. The value of the
parameters not provided are unchanged. TIMEOUT is a value in milliseconds to
pass to the `call-configuration-manager-method' procedure."
pass to the `send-dbus/configuration-manager' procedure."
(let* ((id (username->id username))
(current-details (id->account-details id))
(updated-details (map (match-lambda
@@ -248,29 +477,52 @@ pass to the `call-configuration-manager-method' procedure."
(or (and=> (assoc-ref details key)
(cut cons key <>))
(cons key value))))
current-details)))
(call-configuration-manager-method
"setAccountDetails" (list id (list->vector updated-details))
#:timeout timeout)))
current-details))
;; dbus-send does not permit sending null strings (it throws a
;; "malformed dictionary" error). Luckily they seem to have the
;; semantic of "default account value" in Jami; so simply drop them.
(updated-details* (remove (match-lambda
((_ . value)
(string-null? value)))
updated-details)))
(send-dbus/configuration-manager
#:timeout timeout
#:method "setAccountDetails"
#:arguments
(list (string-append "string:" id)
(string-append "dict:string:string:"
(string-join (alist->list updated-details*)
","))))))
(define (set-all-moderators enabled? username)
"Set the 'AllModerators' property to enabled? for the account of USERNAME, a
registered username or account fingerprint."
(let ((id (username->id username)))
(call-configuration-manager-method "setAllModerators" (list id enabled?))))
(send-dbus/configuration-manager
#:method "setAllModerators"
#:arguments
(list (string-append "string:" id)
(serialize-boolean enabled?)))))
(define (username->all-moderators? username)
"Return the 'AllModerators' property for the account of USERNAME, a
registered username or account fingerprint."
(let ((id (username->id username)))
(call-configuration-manager-method "isAllModerators" (list id))))
(let* ((id (username->id username))
(reply (send-dbus/configuration-manager
#:method "isAllModerators"
#:arguments
(list (string-append "string:" id)))))
(deserialize-item (parse-dbus-reply reply))))
(define (username->moderators username)
"Return the moderators for the account of USERNAME, a registered username or
account fingerprint."
(let* ((id (username->id username)))
(vector->list (call-configuration-manager-method "getDefaultModerators"
(list id)))))
(let* ((id (username->id username))
(reply (send-dbus/configuration-manager
#:method "getDefaultModerators"
#:arguments
(list (string-append "string:" id)))))
(array->list (parse-dbus-reply reply))))
(define (set-moderator contact enabled? username)
"Set the moderator flag to ENABLED? for CONTACT, the 40 characters public
@@ -278,8 +530,11 @@ key fingerprint of a contact for the account of USERNAME, a registered
username or account fingerprint."
(validate-fingerprint contact)
(let* ((id (username->id username)))
(call-configuration-manager-method "setDefaultModerator"
(list id contact enabled?))))
(send-dbus/configuration-manager #:method "setDefaultModerator"
#:arguments
(list (string-append "string:" id)
(string-append "string:" contact)
(serialize-boolean enabled?)))))
(define (disable-account username)
"Disable the account known by USERNAME, a registered username or account
@@ -288,7 +543,7 @@ fingerprint."
;; Waiting for the reply on this command takes a very
;; long time that trips the default D-Bus timeout value
;; (25 s), for some reason.
#:timeout 60))
#:timeout 60000))
(define (enable-account username)
"Enable the account known by USERNAME, a registered username or account
@@ -326,3 +581,7 @@ requirements."
(fold alist-delete account-details first-items))))
(string-join (map pair->recutil-property sorted-account-details) "\n"))
;; Local Variables:
;; eval: (put 'with-retries 'scheme-indent-function 2)
;; End:
+9 -9
View File
@@ -589,6 +589,15 @@ upon error."
(load-linux-modules-from-directory linux-modules
linux-module-directory)
(unless (or (member "hibernate=noresume" args)
;; Also handle the equivalent old-style argument.
;; See Documentation/admin-guide/kernel-parameters.txt.
(member "noresume" args))
;; Try to resume immediately after loading (storage) modules
;; but before any on-disk file systems have been mounted.
(false-if-exception ; failure is not fatal
(resume-if-hibernated (find-long-option "resume" args))))
(when keymap-file
(let ((status (system* "loadkeys" keymap-file)))
(unless (zero? status)
@@ -622,15 +631,6 @@ the root file system...\n" root-delay)
(unless (pre-mount)
(error "pre-mount actions failed")))
(unless (or (member "hibernate=noresume" args)
;; Also handle the equivalent old-style argument.
;; See Documentation/admin-guide/kernel-parameters.txt.
(member "noresume" args))
;; Try to resume immediately after loading (storage) modules
;; but before any on-disk file systems have been mounted.
(false-if-exception ; failure is not fatal
(resume-if-hibernated (find-long-option "resume" args))))
(setenv "EXT2FS_NO_MTAB_OK" "1")
;; Mount the root file system.
+12 -89
View File
@@ -1,6 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2015 David Thompson <davet@gnu.org>
;;; Copyright © 2017-2019, 2022, 2023 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2017, 2018, 2019 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -233,7 +233,7 @@ that host UIDs (respectively GIDs) map to in the namespace."
;; The parent process must initialize the user namespace for the child
;; before it can boot. To negotiate this, a pipe is used such that the
;; child process blocks until the parent writes to it.
(match (socketpair PF_UNIX (logior SOCK_CLOEXEC SOCK_STREAM) 0)
(match (socketpair PF_UNIX SOCK_STREAM 0)
((child . parent)
(let ((flags (namespaces->bit-mask namespaces)))
(match (clone flags)
@@ -301,28 +301,8 @@ delete it when leaving the dynamic extent of this call."
(lambda ()
(false-if-exception (delete-file-recursively tmp-dir))))))
(define (wait-child-process)
"Wait for one child process and return a pair, like 'waitpid', or return #f
if there are no child processes left."
(catch 'system-error
(lambda ()
(waitpid WAIT_ANY))
(lambda args
(if (= ECHILD (system-error-errno args))
#f
(apply throw args)))))
(define (status->exit-status status)
"Reify STATUS as an exit status."
(or (status:exit-val status)
;; See <http://www.tldp.org/LDP/abs/html/exitcodes.html#EXITCODESREF>.
(+ 128 (or (status:term-sig status)
(status:stop-sig status)))))
(define* (call-with-container mounts thunk #:key (namespaces %namespaces)
(host-uids 1) (guest-uid 0) (guest-gid 0)
(relayed-signals (list SIGINT SIGTERM))
(child-is-pid1? #t)
(process-spawned-hook (const #t)))
"Run THUNK in a new container process and return its exit status; call
PROCESS-SPAWNED-HOOK with the PID of the new process that has been spawned.
@@ -340,71 +320,27 @@ can map more than a single uid/gid.
GUEST-UID and GUEST-GID specify the first UID (respectively GID) that host
UIDs (respectively GIDs) map to in the namespace.
RELAYED-SIGNALS is the list of signals that are \"relayed\" to the container
process when caught by its parent.
When CHILD-IS-PID1? is true, and if NAMESPACES contains 'pid', then the child
process runs directly as PID 1. As such, it is responsible for (1) installing
signal handlers and (2) reaping terminated processes by calling 'waitpid'.
When CHILD-IS-PID1? is false, a new intermediate process is created instead
that takes this responsibility.
Note that if THUNK needs to load any additional Guile modules, the relevant
module files must be present in one of the mappings in MOUNTS and the Guile
load path must be adjusted as needed."
(define thunk*
(if (and (memq 'pid namespaces)
(not child-is-pid1?))
(lambda ()
;; Behave like an init process: create a sub-process that calls
;; THUNK, and wait for child processes. Furthermore, forward
;; RELAYED-SIGNALS to the child process.
(match (primitive-fork)
(0
(call-with-clean-exit thunk))
(pid
(install-signal-handlers pid)
(let loop ()
(match (wait-child-process)
((child . status)
(if (= child pid)
(primitive-exit (status->exit-status status))
(loop)))
(#f
(primitive-exit 128))))))) ;cannot happen
thunk))
(define (periodically-schedule-asyncs)
;; XXX: In Guile there's a time window where a signal-handling async could
;; be queued without being processed by the time we enter a blocking
;; syscall like waitpid(2) (info "(guile) Signals"). This terrible hack
;; ensures pending asyncs get a chance to run periodically.
(sigaction SIGALRM (lambda _ (alarm 1)))
(alarm 1))
(define (install-signal-handlers pid)
;; Install handlers that forward signals to PID.
(define (relay-signal signal)
(false-if-exception (kill pid signal)))
(periodically-schedule-asyncs)
(for-each (lambda (signal)
(sigaction signal relay-signal))
relayed-signals))
(call-with-temporary-directory
(lambda (root)
(let ((pid (run-container root mounts namespaces host-uids thunk*
(let ((pid (run-container root mounts namespaces host-uids thunk
#:guest-uid guest-uid
#:guest-gid guest-gid)))
(install-signal-handlers pid)
;; Catch SIGINT and kill the container process.
(sigaction SIGINT
(lambda (signum)
(false-if-exception
(kill pid SIGKILL))))
(process-spawned-hook pid)
(match (waitpid pid)
((_ . status) status))))))
(define (container-excursion pid thunk)
"Run THUNK as a child process within the namespaces of process PID and
return the exit status, an integer as returned by 'waitpid'."
return the exit status."
(define (namespace-file pid namespace)
(string-append "/proc/" (number->string pid) "/ns/" namespace))
@@ -432,29 +368,16 @@ return the exit status, an integer as returned by 'waitpid'."
'("user" "ipc" "uts" "net" "pid" "mnt"))
(purify-environment)
(chdir "/")
;; Per setns(2), changing the PID namespace only applies to child
;; processes, not to the process itself. Thus fork so that THUNK runs
;; in the right PID namespace, which also gives it access to /proc.
(match (primitive-fork)
(0 (call-with-clean-exit thunk))
(pid (primitive-exit
(match (waitpid pid)
((_ . status)
(or (status:exit-val status) 127)))))))))
(thunk))))
(pid
(match (waitpid pid)
((_ . status)
status)))))
(status:exit-val status))))))
(define (container-excursion* pid thunk)
"Like 'container-excursion', but return the return value of THUNK."
(match (pipe)
((in . out)
;; Make sure IN and OUT are not inherited if THUNK forks + execs.
(fcntl in F_SETFD FD_CLOEXEC)
(fcntl out F_SETFD FD_CLOEXEC)
(match (container-excursion pid
(lambda ()
(close-port in)
+1 -134
View File
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2014, 2016, 2018, 2019, 2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2014, 2016, 2018, 2019 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
;;; Copyright © 2018 Danny Milosavljevic <dannym@scratchpost.org>
;;;
@@ -28,7 +28,6 @@
#:use-module (rnrs io ports)
#:use-module (rnrs bytevectors)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-9 gnu)
#:use-module (srfi srfi-11)
#:use-module (srfi srfi-26)
#:use-module (ice-9 ftw)
@@ -51,17 +50,6 @@
load-linux-module*
load-linux-modules-from-directory
pci-devices
pci-device?
pci-device-vendor
pci-device-id
pci-device-class
pci-device-module-alias
storage-pci-device?
network-pci-device?
display-pci-device?
load-pci-device-database
current-module-debugging-port
device-module-aliases
@@ -441,127 +429,6 @@ key such as 'MAJOR or 'DEVTYPE and each cdr is the corresponding value."
(line
(loop (cons (key=value->pair line) result))))))
;; PCI device known to the Linux kernel.
(define-immutable-record-type <pci-device>
(pci-device vendor device class module-alias)
pci-device?
(vendor pci-device-vendor) ;integer
(device pci-device-id) ;integer
(class pci-device-class) ;integer
(module-alias pci-device-module-alias)) ;string | #f
(define (pci-device-class-predicate mask bits)
(lambda (device)
"Return true if DEVICE has the chosen class."
(= (logand mask (pci-device-class device)) bits)))
(define storage-pci-device? ;"Mass storage controller" class
(pci-device-class-predicate #xff0000 #x010000))
(define network-pci-device? ;"Network controller" class
(pci-device-class-predicate #xff0000 #x020000))
(define display-pci-device? ;"Display controller" class
(pci-device-class-predicate #xff0000 #x030000))
(define (pci-devices)
"Return the list of PCI devices of the system (<pci-device> records)."
(define (read-hex port)
(let ((line (read-line port)))
(and (string? line)
(string-prefix? "0x" line)
(string->number (string-drop line 2) 16))))
(filter-map (lambda (directory)
(define properties
(call-with-input-file (string-append directory "/uevent")
read-uevent))
(define vendor
(call-with-input-file (string-append directory "/vendor")
read-hex))
(define device
(call-with-input-file (string-append directory "/device")
read-hex))
(define class
(call-with-input-file (string-append directory "/class")
read-hex))
(pci-device vendor device class
(assq-ref properties 'MODALIAS)))
(find-files "/sys/bus/pci/devices"
#:stat lstat)))
(define (read-pci-device-database port)
"Parse the 'pci.ids' database that ships with the pciutils package and is
maintained at <https://pci-ids.ucw.cz/>."
(define (comment? str)
(string-prefix? "#" (string-trim str)))
(define (blank? str)
(string-null? (string-trim-both str)))
(define (device? str)
(eqv? #\tab (string-ref str 0)))
(define (subvendor? str)
(string-prefix? "\t\t" str))
(define (class? str)
(string-prefix? "C " str))
(define (parse-id-line str)
(let* ((str (string-trim-both str))
(space (string-index str char-set:whitespace)))
(values (string->number (string-take str space) 16)
(string-trim (string-drop str (+ 1 space))))))
(define (finish vendor vendor-id devices table)
(fold (lambda (device table)
(match device
((device-id . name)
(vhash-consv (logior (ash vendor-id 16) device-id)
(cons vendor name)
table))))
table
devices))
(let loop ((table vlist-null)
(vendor-id #f)
(vendor #f)
(devices '()))
(match (read-line port)
((? eof-object?)
(let ((table (if (and vendor vendor-id)
(finish vendor vendor-id devices table)
table)))
(lambda (vendor device)
(match (vhash-assv (logior (ash vendor 16) device) table)
(#f
(values #f #f))
((_ . (vendor . name))
(values vendor name))))))
((? comment?)
(loop table vendor-id vendor devices))
((? blank?)
(loop table vendor-id vendor devices))
((? subvendor?) ;currently ignored
(loop table vendor-id vendor devices))
((? class?) ;currently ignored
(loop table vendor-id vendor devices))
((? device? line)
(let-values (((id name) (parse-id-line line)))
(loop table vendor-id vendor
(if (and vendor-id vendor) ;class or device?
(alist-cons id name devices)
devices))))
(line
(let ((table (if (and vendor vendor-id)
(finish vendor vendor-id devices table)
table)))
(let-values (((vendor-id vendor) (parse-id-line line)))
(loop table vendor-id vendor '())))))))
(define (load-pci-device-database file)
"Read the 'pci.ids' database at FILE (get it from the pciutils package or
from <https://pci-ids.ucw.cz/>) and return a lookup procedure that takes a PCI
vendor ID and a device ID (two integers) and returns the vendor name and
device name as two values."
(let ((port (open-file file "r0")))
(call-with-gzip-input-port port
read-pci-device-database)))
(define (device-module-aliases device)
"Return the list of module aliases required by DEVICE, a /dev file name, as
in this example:
+58 -144
View File
@@ -1,8 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2016-2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2018 Chris Marusich <cmmarusich@gmail.com>
;;; Copyright © 2022, 2023 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;; Copyright © 2023 Bruno Victal <mirai@makinata.eu>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -23,21 +21,19 @@
#:use-module (srfi srfi-9)
#:use-module (srfi srfi-26)
#:use-module (srfi srfi-64)
#:use-module (srfi srfi-71)
#:use-module (rnrs io ports)
#:use-module (ice-9 match)
#:use-module (ice-9 popen)
#:use-module (ice-9 regex)
#:export (marionette?
marionette-pid
make-marionette
marionette-eval
wait-for-file
wait-for-tcp-port
wait-for-unix-socket
marionette-control
marionette-screen-text
wait-for-screen-text
%default-ocrad-arguments
%qwerty-us-keystrokes
marionette-type
@@ -109,14 +105,11 @@ QEMU monitor and to the guest's backdoor REPL."
"-monitor" (string-append "unix:" socket-directory "/monitor")
"-chardev" (string-append "socket,id=repl,path=" socket-directory
"/repl")
"-chardev" (string-append "socket,id=qga,server=on,wait=off,path="
socket-directory "/qemu-ga")
;; See
;; <http://www.linux-kvm.org/page/VMchannel_Requirements#Invocation>.
"-device" "virtio-serial"
"-device" "virtserialport,chardev=repl,name=org.gnu.guix.port.0"
"-device" "virtserialport,chardev=qga,name=org.qemu.guest_agent.0"))
"-device" "virtserialport,chardev=repl,name=org.gnu.guix.port.0"))
(define (accept* port)
(match (select (list port) '() (list port) timeout)
@@ -181,18 +174,7 @@ QEMU monitor and to the guest's backdoor REPL."
(($ <marionette> command pid monitor (= force repl))
(write exp repl)
(newline repl)
(with-exception-handler
(lambda (exn)
(simple-format
(current-error-port)
"error reading marionette response: ~A
remaining response: ~A\n"
exn
(get-line repl))
(raise-exception exn))
(lambda ()
(read repl))
#:unwind? #t))))
(read repl))))
(define* (wait-for-file file marionette
#:key (timeout 10) (read 'read))
@@ -201,14 +183,7 @@ FILE has not shown up after TIMEOUT seconds, raise an error."
(match (marionette-eval
`(let loop ((i ,timeout))
(cond ((file-exists? ,file)
(cons 'success
(let ((content
(call-with-input-file ,file ,read)))
(if (eof-object? content)
;; #<eof> can't be read, so convert to the
;; empty string
""
content))))
(cons 'success (call-with-input-file ,file ,read)))
((> i 0)
(sleep 1)
(loop (- i 1)))
@@ -221,38 +196,31 @@ FILE has not shown up after TIMEOUT seconds, raise an error."
(error "file didn't show up" file))))
(define* (wait-for-tcp-port port marionette
#:key
(timeout 20)
(address `(make-socket-address AF_INET
INADDR_LOOPBACK
,port)))
#:key (timeout 20))
"Wait for up to TIMEOUT seconds for PORT to accept connections in
MARIONETTE. ADDRESS must be an expression that returns a socket address,
typically a call to 'make-socket-address'. Raise an error on failure."
MARIONETTE. Raise an error on failure."
;; Note: The 'connect' loop has to run within the guest because, when we
;; forward ports to the host, connecting to the host never raises
;; ECONNREFUSED.
(match (marionette-eval
`(let* ((address ,address)
(sock (socket (sockaddr:fam address) SOCK_STREAM 0)))
(let loop ((i 0))
(catch 'system-error
(lambda ()
(connect sock address)
(close-port sock)
'success)
(lambda args
(if (< i ,timeout)
(begin
(sleep 1)
(loop (+ 1 i)))
(list 'failure address))))))
`(begin
(let ((sock (socket PF_INET SOCK_STREAM 0)))
(let loop ((i 0))
(catch 'system-error
(lambda ()
(connect sock AF_INET INADDR_LOOPBACK ,port)
(close-port sock)
'success)
(lambda args
(if (< i ,timeout)
(begin
(sleep 1)
(loop (+ 1 i)))
'failure))))))
marionette)
('success #t)
(('failure address)
(error "nobody's listening on port"
(list (inet-ntop (sockaddr:fam address) (sockaddr:addr address))
(sockaddr:port address))))))
('failure
(error "nobody's listening on port" port))))
(define* (wait-for-unix-socket file-name marionette
#:key (timeout 20))
@@ -280,8 +248,8 @@ accept connections in MARIONETTE. Raise an error on failure."
(define (marionette-control command marionette)
"Run COMMAND in the QEMU monitor of MARIONETTE. COMMAND is a string such as
\"sendkey ctrl-alt-f1\" or \"screendump foo.ppm\" (info \"(QEMU) QEMU
Monitor\")."
\"sendkey ctrl-alt-f1\" or \"screendump foo.ppm\" (info \"(qemu-doc)
pcsys_monitor\")."
(match marionette
(($ <marionette> _ _ monitor)
(display command monitor)
@@ -289,106 +257,54 @@ Monitor\")."
;; The "quit" command terminates QEMU immediately, with no output.
(unless (string=? command "quit") (wait-for-monitor-prompt monitor)))))
(define %default-ocrad-arguments
'("--invert" "--scale=10"))
(define* (marionette-screen-text marionette
#:key
(ocrad "ocrad"))
"Take a screenshot of MARIONETTE, perform optical character
recognition (OCR), and return the text read from the screen as a string. Do
this by invoking OCRAD (file name for GNU Ocrad's command)"
(define (random-file-name)
(string-append "/tmp/marionette-screenshot-"
(number->string (random (expt 2 32)) 16)
".ppm"))
(define* (invoke-ocrad-ocr image #:key (ocrad "ocrad")
(ocr-arguments %default-ocrad-arguments))
"Invoke the OCRAD command on image, and return the recognized text."
(let* ((command (string-join `(,ocrad ,@ocr-arguments ,image)))
(pipe (open-input-pipe command))
(text (get-string-all pipe)))
(unless (zero? (close-pipe pipe))
(error "'ocrad' failed" ocrad))
text))
(define* (invoke-tesseract-ocr image #:key (tesseract "tesseract")
(ocr-arguments '()))
"Invoke the TESSERACT command on IMAGE, and return the recognized text."
(let* ((output-basename (tmpnam))
(output-basename* (string-append output-basename ".txt"))
(arguments (cons* image output-basename ocr-arguments)))
(let ((image (random-file-name)))
(dynamic-wind
(const #t)
(lambda ()
(let ((exit-val (status:exit-val
(apply system* tesseract arguments))))
(unless (zero? exit-val)
(error "'tesseract' failed" tesseract))
(call-with-input-file output-basename* get-string-all)))
(lambda ()
(false-if-exception (delete-file output-basename))
(false-if-exception (delete-file output-basename*))))))
(marionette-control (string-append "screendump " image)
marionette)
(define* (marionette-screen-text marionette #:key (ocr "ocrad")
ocr-arguments)
"Take a screenshot of MARIONETTE, perform optical character
recognition (OCR), and return the text read from the screen as a string, along
the screen dump image used. Do this by invoking OCR, which should be the file
name of GNU Ocrad's@command{ocrad} or Tesseract OCR's @command{tesseract}
command. The screen dump image returned as the second value should be deleted
if it is not needed."
(define image (string-append (tmpnam) ".ppm"))
;; Use the QEMU Monitor to save an image of the screen to the host.
(marionette-control (string-append "screendump " image) marionette)
;; Process it via the OCR.
(cond
((string-contains ocr "ocrad")
(values (invoke-ocrad-ocr image
#:ocrad ocr
#:ocr-arguments
(or ocr-arguments %default-ocrad-arguments))
image))
((string-contains ocr "tesseract")
(values (invoke-tesseract-ocr image
#:tesseract ocr
#:ocr-arguments (or ocr-arguments '()))
image))
(else (error "unsupported ocr command"))))
;; Tell Ocrad to invert the image colors (make it black on white) and
;; to scale the image up, which significantly improves the quality of
;; the result. In spite of this, be aware that OCR confuses "y" and
;; "V" and sometimes erroneously introduces white space.
(let* ((pipe (open-pipe* OPEN_READ ocrad
"-i" "-s" "10" image))
(text (get-string-all pipe)))
(unless (zero? (close-pipe pipe))
(error "'ocrad' failed" ocrad))
text))
(lambda ()
(false-if-exception (delete-file image))))))
(define* (wait-for-screen-text marionette predicate
#:key
(ocr "ocrad")
ocr-arguments
(timeout 30)
pre-action
post-action)
#:key (timeout 30) (ocrad "ocrad"))
"Wait for TIMEOUT seconds or until the screen text on MARIONETTE matches
PREDICATE, whichever comes first. Raise an error when TIMEOUT is exceeded.
The error contains the recognized text along the preserved file name of the
screen dump, which is relative to the current working directory. If
PRE-ACTION is provided, it should be a thunk to call before each OCR attempt.
Likewise for POST-ACTION, except it runs at the end of a successful OCR."
PREDICATE, whichever comes first. Raise an error when TIMEOUT is exceeded."
(define start
(car (gettimeofday)))
(define end
(+ start timeout))
(let loop ((last-text #f)
(last-screendump #f))
(let loop ()
(if (> (car (gettimeofday)) end)
(let ((screendump-backup (string-drop last-screendump 5)))
;; Move the file from /tmp/fileXXXXXX.pmm to the current working
;; directory, so that it is preserved in the test derivation output.
(copy-file last-screendump screendump-backup)
(delete-file last-screendump)
(error "'wait-for-screen-text' timeout"
'ocr-text: last-text
'screendump: screendump-backup))
(let* ((_ (and (procedure? pre-action) (pre-action)))
(text screendump
(marionette-screen-text marionette
#:ocr ocr
#:ocr-arguments ocr-arguments))
(_ (and (procedure? post-action) (post-action)))
(result (predicate text)))
(cond (result
(delete-file screendump)
result)
(else
(sleep 1)
(loop text screendump)))))))
(error "'wait-for-screen-text' timeout" predicate)
(or (predicate (marionette-screen-text marionette #:ocrad ocrad))
(begin
(sleep 1)
(loop))))))
(define %qwerty-us-keystrokes
;; Maps "special" characters to their keystrokes.
@@ -410,10 +326,8 @@ Likewise for POST-ACTION, except it runs at the end of a successful OCR."
(#\> . "shift-dot")
(#\. . "dot")
(#\, . "comma")
(#\: . "shift-semicolon")
(#\; . "semicolon")
(#\' . "apostrophe")
(#\! . "shift-1")
(#\" . "shift-apostrophe")
(#\` . "grave_accent")
(#\bs . "backspace")
+21 -73
View File
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2020-2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2020, 2021 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
;;;
;;; This file is part of GNU Guix.
@@ -47,52 +47,6 @@
;; to syslog.
#'(format (current-output-port) fmt args ...))))))
(define-syntax with-modules
(syntax-rules ()
"Dynamically load the given MODULEs at run time, making the chosen
bindings available within the lexical scope of BODY."
((_ ((module #:select (bindings ...)) rest ...) body ...)
(let* ((iface (resolve-interface 'module))
(bindings (module-ref iface 'bindings))
...)
(with-modules (rest ...) body ...)))
((_ () body ...)
(begin body ...))))
(define (wait-for-readable-fd port timeout)
"Wait until PORT has data available for reading or TIMEOUT has expired.
Return #t in the former case and #f in the latter case."
(match (resolve-module '(fibers) #f #:ensure #f) ;using Fibers?
(#f
(log "blocking on socket...~%")
(match (select (list port) '() '() timeout)
(((_) () ()) #t)
((() () ()) #f)))
(fibers
;; We're running on the Shepherd 0.9+ with Fibers. Arrange to make a
;; non-blocking wait so that other fibers can be scheduled in while we
;; wait for PORT.
(with-modules (((fibers) #:select (spawn-fiber sleep))
((fibers channels)
#:select (make-channel put-message get-message)))
;; Make PORT non-blocking.
(let ((flags (fcntl port F_GETFL)))
(fcntl port F_SETFL (logior O_NONBLOCK flags)))
(let ((channel (make-channel)))
(spawn-fiber
(lambda ()
(sleep timeout) ;suspends the fiber
(put-message channel 'timeout)))
(spawn-fiber
(lambda ()
(lookahead-u8 port) ;suspends the fiber
(put-message channel 'readable)))
(log "suspending fiber on socket...~%")
(match (get-message channel)
('readable #t)
('timeout #f)))))))
(define* (secret-service-send-secrets port secret-root
#:key (retry 60)
(handshake-timeout 120))
@@ -119,11 +73,8 @@ wait for at most HANDSHAKE-TIMEOUT seconds for handshake to complete. Return
files)))
(log "sending secrets to ~a~%" port)
(let ((sock (socket AF_INET (logior SOCK_CLOEXEC SOCK_STREAM) 0))
(addr (make-socket-address AF_INET INADDR_LOOPBACK port))
(sleep (if (resolve-module '(fibers) #f)
(module-ref (resolve-interface '(fibers)) 'sleep)
sleep)))
(let ((sock (socket AF_INET SOCK_STREAM 0))
(addr (make-socket-address AF_INET INADDR_LOOPBACK port)))
;; Connect to QEMU on the forwarded port. The 'connect' call succeeds as
;; soon as QEMU is ready, even if there's no server listening on the
;; forward port inside the guest.
@@ -142,22 +93,23 @@ wait for at most HANDSHAKE-TIMEOUT seconds for handshake to complete. Return
;; Wait for "hello" message from the server. This is the only way to know
;; that we're really connected to the server inside the guest.
(if (wait-for-readable-fd sock handshake-timeout)
(match (read sock)
(('secret-service-server ('version version ...))
(log "sending files from ~s...~%" secret-root)
(send-files sock)
(log "done sending files to port ~a~%" port)
(close-port sock)
secret-root)
(x
(log "invalid handshake ~s~%" x)
(close-port sock)
#f))
(begin ;timeout
(log "timeout while sending files to ~a~%" port)
(close-port sock)
#f))))
(match (select (list sock) '() '() handshake-timeout)
(((_) () ())
(match (read sock)
(('secret-service-server ('version version ...))
(log "sending files from ~s...~%" secret-root)
(send-files sock)
(log "done sending files to port ~a~%" port)
(close-port sock)
secret-root)
(x
(log "invalid handshake ~s~%" x)
(close-port sock)
#f)))
((() () ()) ;timeout
(log "timeout while sending files to ~a~%" port)
(close-port sock)
#f))))
(define (delete-file* file)
"Ensure FILE does not exist."
@@ -177,7 +129,7 @@ and #f otherwise."
;; Wait for a TCP connection on PORT. Note: We cannot use the
;; virtio-serial ports, which would be safer, because they are
;; (presumably) unsupported on GNU/Hurd.
(let ((sock (socket AF_INET (logior SOCK_CLOEXEC SOCK_STREAM) 0)))
(let ((sock (socket AF_INET SOCK_STREAM 0)))
(bind sock AF_INET INADDR_ANY port)
(listen sock 1)
(log "waiting for secrets on port ~a...~%" port)
@@ -250,8 +202,4 @@ and #f otherwise."
(close-port port))
result))
;;; Local Variables:
;;; eval: (put 'with-modules 'scheme-indent-function 1)
;;; End:
;;; secret-service.scm ends here
+31 -64
View File
@@ -1,8 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2017, 2018, 2019, 2020, 2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2017, 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2020 Mathieu Othacehe <othacehe@gnu.org>
;;; Copyright © 2022 Leo Nikkilä <hello@lnikki.la>
;;; Copyright © 2022 Arun Isaac <arunisaac@systemreboot.net>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -32,8 +30,7 @@
exec-command
%precious-signals)
#:autoload (shepherd system) (unblock-signals)
#:export (default-mounts
make-forkexec-constructor/container
#:export (make-forkexec-constructor/container
fork+exec-command/container))
;;; Commentary:
@@ -106,13 +103,8 @@
separate mount and PID name space. Return the \"outer\" PID. "
(match (container-excursion* pid
(lambda ()
;; XXX: Trick for Shepherd 0.9: prevent 'read-pid-file' from
;; using (@ (fibers) sleep), which would try to suspend the
;; current task, which doesn't work in this extra process.
(with-continuation-barrier
(lambda ()
(read-pid-file pid-file
#:max-delay max-delay)))))
(read-pid-file pid-file
#:max-delay max-delay)))
(#f
;; Send SIGTERM to the whole process group.
(catch-system-error (kill (- pid) SIGTERM))
@@ -122,28 +114,6 @@ separate mount and PID name space. Return the \"outer\" PID. "
;; PID is always 1, but that's not what Shepherd needs to know.
pid)))
(define* (exec-command* command #:key user group log-file pid-file
(supplementary-groups '())
(directory "/") (environment-variables (environ)))
"Like 'exec-command', but first restore signal handles modified by
shepherd (PID 1)."
;; First restore the default handlers.
(for-each (cut sigaction <> SIG_DFL) %precious-signals)
;; Unblock any signals that have been blocked by the parent process.
(unblock-signals %precious-signals)
(mkdir-p "/var/run")
(clean-up pid-file)
(exec-command command
#:user user
#:group group
#:supplementary-groups supplementary-groups
#:log-file log-file
#:directory directory
#:environment-variables environment-variables))
(define* (make-forkexec-constructor/container command
#:key
(namespaces
@@ -151,7 +121,6 @@ shepherd (PID 1)."
(mappings '())
(user #f)
(group #f)
(supplementary-groups '())
(log-file #f)
pid-file
(pid-file-timeout 5)
@@ -187,7 +156,7 @@ namespace, in addition to essential bind-mounts such /proc."
(when log-file
;; Create LOG-FILE so we can map it in the container.
(unless (file-exists? log-file)
(close (open log-file (logior O_CREAT O_APPEND O_CLOEXEC) #o640))
(call-with-output-file log-file (const #t))
(when user
(let ((pw (getpwnam user)))
(chown log-file (passwd:uid pw) (passwd:gid pw))))))
@@ -195,16 +164,24 @@ namespace, in addition to essential bind-mounts such /proc."
(let ((pid (run-container container-directory
mounts namespaces 1
(lambda ()
(exec-command* command
#:user user
#:group group
#:supplementary-groups
supplementary-groups
#:pid-file pid-file
#:log-file log-file
#:directory directory
#:environment-variables
environment-variables)))))
;; First restore the default handlers.
(for-each (cut sigaction <> SIG_DFL)
%precious-signals)
;; Unblock any signals that have been blocked
;; by the parent process.
(unblock-signals %precious-signals)
(mkdir-p "/var/run")
(clean-up pid-file)
(exec-command command
#:user user
#:group group
#:log-file log-file
#:directory directory
#:environment-variables
environment-variables)))))
(if pid-file
(if (or (memq 'mnt namespaces) (memq 'pid namespaces))
(read-pid-file/container pid pid-file
@@ -232,24 +209,14 @@ on Hurd systems for instance, fallback to direct forking."
((head . rest)
(loop rest (cons head result))))))
(let ((container-support? (file-exists? "/proc/self/ns")))
(if (and container-support?
(not (and pid (= pid (getpid)))))
(container-excursion* pid
(lambda ()
;; Note: In the Shepherd 0.9, 'fork+exec-command' expects to be
;; called from the shepherd process (because it creates a pipe to
;; capture stdout/stderr and spawns a logging fiber) so we cannot
;; use it here.
(match (primitive-fork)
(0 (dynamic-wind
(const #t)
(lambda ()
(apply exec-command* command (strip-pid args)))
(lambda ()
(primitive-_exit 127))))
(pid pid)))) ;XXX: assuming the same PID namespace
(apply fork+exec-command command (strip-pid args)))))
(let ((container-support?
(file-exists? "/proc/self/ns"))
(fork-proc (lambda ()
(apply fork+exec-command command
(strip-pid args)))))
(if container-support?
(container-excursion* pid fork-proc)
(fork-proc))))
;; Local Variables:
;; eval: (put 'container-excursion* 'scheme-indent-function 1)
+117 -81
View File
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2012-2023 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2012-2021 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2017, 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
;;; Copyright © 2018, 2019 Clément Lassieur <clement@lassieur.org>
;;; Copyright © 2020 Julien Lepiller <julien@lepiller.eu>
@@ -21,17 +21,18 @@
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (gnu ci)
#:use-module (guix build-system channel)
#:use-module (guix channels)
#:use-module (guix config)
#:autoload (guix describe) (package-channels)
#:use-module (guix memoization)
#:use-module (guix describe)
#:use-module (guix store)
#:use-module (guix grafts)
#:use-module (guix profiles)
#:use-module (guix packages)
#:autoload (guix transformations) (tunable-package? tuned-package)
#:use-module (guix channels)
#:use-module (guix config)
#:use-module (guix derivations)
#:use-module (guix build-system)
#:use-module (guix monads)
#:use-module (guix gexp)
#:use-module (guix ui)
@@ -40,14 +41,12 @@
#:use-module ((guix utils) #:select (%current-system))
#:use-module ((guix scripts system) #:select (read-operating-system))
#:use-module ((guix scripts pack)
#:select (self-contained-tarball))
#:select (lookup-compressor self-contained-tarball))
#:use-module (gnu bootloader)
#:use-module (gnu bootloader u-boot)
#:use-module (gnu compression)
#:use-module (gnu image)
#:use-module (gnu packages)
#:use-module (gnu packages gcc)
#:use-module (gnu packages gdb)
#:use-module (gnu packages base)
#:use-module (gnu packages gawk)
#:use-module (gnu packages guile)
@@ -56,7 +55,6 @@
#:use-module (gnu packages multiprecision)
#:use-module (gnu packages make-bootstrap)
#:use-module (gnu packages package-management)
#:use-module (guix platform)
#:use-module (gnu system)
#:use-module (gnu system image)
#:use-module (gnu system vm)
@@ -73,6 +71,8 @@
image->job
%core-packages
%cross-targets
channel-source->package
arguments->systems
cuirass-jobs))
@@ -139,7 +139,7 @@ SYSTEM."
;; Note: Don't put the '-final' package variants because (1) that's
;; implicit, and (2) they cannot be cross-built (due to the explicit input
;; chain.)
(list gcc-10 gcc-11 gcc-12 glibc binutils gdb-minimal
(list gcc-8 gcc-9 gcc-10 gcc-11 glibc binutils
gmp mpfr mpc coreutils findutils diffutils patch sed grep
gawk gnu-gettext hello guile-2.2 guile-3.0 zlib gzip xz guix
%bootstrap-binaries-tarball
@@ -169,6 +169,17 @@ SYSTEM."
(drop-right %core-packages 6)
%core-packages))
(define %cross-targets
'("mips64el-linux-gnu"
"arm-linux-gnueabihf"
"aarch64-linux-gnu"
"powerpc-linux-gnu"
"powerpc64le-linux-gnu"
"riscv64-linux-gnu"
"i586-pc-gnu" ;aka. GNU/Hurd
"i686-w64-mingw32"
"x86_64-w64-mingw32"))
(define (cross-jobs store system)
"Return a list of cross-compilation jobs for SYSTEM."
(define (from-32-to-64? target)
@@ -210,7 +221,7 @@ SYSTEM."
package target system))
(packages-to-cross-build target)))
(remove (either from-32-to-64? same? pointless?)
(targets))))
%cross-targets)))
(define* (guix-jobs store systems #:key source commit)
"Return a list of jobs for Guix itself."
@@ -253,44 +264,77 @@ otherwise use the IMAGE name."
(drv (run-with-store store
(mbegin %store-monad
(set-guile-for-build (default-guile))
(lower-object (system-image image) system)))))
(lower-object (system-image image))))))
(parameterize ((%graft? #f))
(derivation->job name drv))))
(define* (image-jobs store system
#:key source commit)
(define (image-jobs store system)
"Return a list of jobs that build images for SYSTEM."
(define MiB
(expt 2 20))
(parameterize ((current-guix-package
(channel-source->package source #:commit commit)))
(if (member system %guix-system-supported-systems)
`(,(image->job store
(image
(inherit efi-disk-image)
(operating-system installation-os))
#:name "usb-image"
#:system system)
,(image->job
store
(image
(inherit (image-with-label
iso9660-image
(string-append "GUIX_" system "_"
(if (> (string-length %guix-version) 7)
(substring %guix-version 0 7)
%guix-version))))
(operating-system installation-os))
#:name "iso9660-image"
#:system system)
;; Only cross-compile Guix System images from x86_64-linux for now.
,@(if (string=? system "x86_64-linux")
(map (cut image->job store <>
#:system system)
%guix-system-images)
'()))
'())))
(if (member system %guix-system-supported-systems)
`(,(image->job store
(image
(inherit efi-disk-image)
(operating-system installation-os))
#:name "usb-image"
#:system system)
,(image->job
store
(image
(inherit (image-with-label
iso9660-image
(string-append "GUIX_" system "_"
(if (> (string-length %guix-version) 7)
(substring %guix-version 0 7)
%guix-version))))
(operating-system installation-os))
#:name "iso9660-image"
#:system system)
;; Only cross-compile Guix System images from x86_64-linux for now.
,@(if (string=? system "x86_64-linux")
(map (cut image->job store <>
#:system system)
%guix-system-images)
'()))
'()))
(define channel-build-system
;; Build system used to "convert" a channel instance to a package.
(let* ((build (lambda* (name inputs
#:key source commit system
#:allow-other-keys)
(mlet* %store-monad ((source (if (string? source)
(return source)
(lower-object source)))
(instance
-> (checkout->channel-instance
source #:commit commit)))
(channel-instances->derivation (list instance)))))
(lower (lambda* (name #:key system source commit
#:allow-other-keys)
(bag
(name name)
(system system)
(build build)
(arguments `(#:source ,source
#:commit ,commit))))))
(build-system (name 'channel)
(description "Turn a channel instance into a package.")
(lower lower))))
(define* (channel-source->package source #:key commit)
"Return a package for the given channel SOURCE, a lowerable object."
(package
(inherit guix)
(version (string-append (package-version guix) "+"))
(build-system channel-build-system)
(arguments `(#:source ,source
#:commit ,commit))
(inputs '())
(native-inputs '())
(propagated-inputs '())))
(define* (system-test-jobs store system
#:key source commit)
@@ -343,32 +387,29 @@ otherwise use the IMAGE name."
;; Return the name of a package's job.
package-name)
(define base-packages
(mlambda (system)
"Return the set of packages considered to be part of the base for SYSTEM."
(delete-duplicates
(append-map (match-lambda
((_ package _ ...)
(match (package-transitive-inputs package)
(((_ inputs _ ...) ...)
inputs))))
(%final-inputs system)))))
(define package->job
(lambda* (store package system #:key (suffix ""))
"Return a job for PACKAGE on SYSTEM, or #f if this combination is not
(let ((base-packages
(delete-duplicates
(append-map (match-lambda
((_ package _ ...)
(match (package-transitive-inputs package)
(((_ inputs _ ...) ...)
inputs))))
(%final-inputs)))))
(lambda* (store package system #:key (suffix ""))
"Return a job for PACKAGE on SYSTEM, or #f if this combination is not
valid. Append SUFFIX to the job name."
(cond ((member package (base-packages system))
(package-job store (string-append "base." (job-name package))
package system #:suffix suffix))
((supported-package? package system)
(let ((drv (package-derivation store package system
#:graft? #f)))
(and (substitutable-derivation? drv)
(package-job store (job-name package)
package system #:suffix suffix))))
(else
#f))))
(cond ((member package base-packages)
(package-job store (string-append "base." (job-name package))
package system #:suffix suffix))
((supported-package? package system)
(let ((drv (package-derivation store package system
#:graft? #f)))
(and (substitutable-derivation? drv)
(package-job store (job-name package)
package system #:suffix suffix))))
(else
#f)))))
(define %x86-64-micro-architectures
;; Micro-architectures for which we build tuned variants.
@@ -421,9 +462,9 @@ valid. Append SUFFIX to the job name."
(map channel-url channels)))
arguments))
(define (manifests->jobs store manifests systems)
(define (manifests->jobs store manifests)
"Return the list of jobs for the entries in MANIFESTS, a list of file
names, for each one of SYSTEMS."
names."
(define (load-manifest manifest)
(save-module-excursion
(lambda ()
@@ -434,12 +475,11 @@ names, for each one of SYSTEMS."
(string-append (manifest-entry-name entry) "-"
(manifest-entry-version entry)))
(define (manifest-entry->job entry system)
(define (manifest-entry->job entry)
(let* ((obj (manifest-entry-item entry))
(drv (parameterize ((%graft? #f))
(run-with-store store
(lower-object obj system)
#:system system)))
(lower-object obj))))
(max-silent-time (or (and (package? obj)
(assoc-ref (package-properties obj)
'max-silent-time))
@@ -451,13 +491,11 @@ names, for each one of SYSTEMS."
#:max-silent-time max-silent-time
#:timeout timeout)))
(let ((entries (delete-duplicates
(append-map (compose manifest-entries load-manifest)
manifests)
manifest-entry=?)))
(append-map (lambda (system)
(map (cut manifest-entry->job <> system) entries))
systems)))
(map manifest-entry->job
(delete-duplicates
(append-map (compose manifest-entries load-manifest)
manifests)
manifest-entry=?)))
(define (arguments->systems arguments)
"Return the systems list from ARGUMENTS."
@@ -539,9 +577,7 @@ names, for each one of SYSTEMS."
hello system))))
('images
;; Build Guix System images only.
(image-jobs store system
#:source source
#:commit commit))
(image-jobs store system))
('system-tests
;; Build Guix System tests only.
(system-test-jobs store system
@@ -579,7 +615,7 @@ names, for each one of SYSTEMS."
(('manifests . rest)
;; Build packages in the list of manifests.
(let ((manifests (arguments->manifests rest channels)))
(manifests->jobs store manifests systems)))
(manifests->jobs store manifests)))
(else
(error "unknown subset" subset))))
systems)))
-69
View File
@@ -1,69 +0,0 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2022 Mathieu Othacehe <othacehe@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (gnu compression)
#:use-module (guix gexp)
#:use-module (guix ui)
#:use-module ((gnu packages compression) #:hide (zip))
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-9)
#:use-module (ice-9 match)
#:export (compressor
compressor?
compressor-name
compressor-extension
compressor-command
%compressors
lookup-compressor))
;; Type of a compression tool.
(define-record-type <compressor>
(compressor name extension command)
compressor?
(name compressor-name) ;string (e.g., "gzip")
(extension compressor-extension) ;string (e.g., ".lz")
(command compressor-command)) ;gexp (e.g., #~(list "/gnu/store/…/gzip"
; "-9n" ))
(define %compressors
;; Available compression tools.
(list (compressor "gzip" ".gz"
#~(list #+(file-append gzip "/bin/gzip") "-9n"))
(compressor "lzip" ".lz"
#~(list #+(file-append lzip "/bin/lzip") "-9"))
(compressor "xz" ".xz"
#~(append (list #+(file-append xz "/bin/xz")
"-e")
(%xz-parallel-args)))
(compressor "bzip2" ".bz2"
#~(list #+(file-append bzip2 "/bin/bzip2") "-9"))
(compressor "zstd" ".zst"
;; The default level 3 compresses better than gzip in a
;; fraction of the time, while the highest level 19
;; (de)compresses more slowly and worse than xz.
#~(list #+(file-append zstd "/bin/zstd") "-3"))
(compressor "none" "" #f)))
(define (lookup-compressor name)
"Return the compressor object called NAME. Error out if it could not be
found."
(or (find (match-lambda
(($ <compressor> name*)
(string=? name* name)))
%compressors)
(leave (G_ "~a: compressor not found~%") name)))
+4 -41
View File
@@ -1,6 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2021 Andrew Tropin <andrew@trop.in>
;;; Copyright © 2022 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -28,22 +27,18 @@
#:use-module (guix diagnostics)
#:use-module (guix gexp)
#:use-module (guix store)
#:use-module (ice-9 match)
#:use-module (ice-9 regex)
#:export (home-environment
home-environment?
this-home-environment
home-environment-derivation
home-environment-packages
home-environment-user-services
home-environment-essential-services
home-environment-services
home-environment-location
home-environment-with-provenance
home-generation-base))
home-environment-with-provenance))
;;; Comment:
;;;
@@ -97,27 +92,13 @@
(home-environment-essential-services he))))
(define* (home-environment-derivation he)
"Return a derivation that builds home environment."
"Return a derivation that builds OS."
(let* ((services (home-environment-services he))
(home (fold-services services
#:target-type home-service-type)))
(service-value home)))
(define (home-environment-configuration-file he)
"Return the configuration file of HE, based on its 'location' field, or #f
if it could not be determined."
(let ((file (and=> (home-environment-location he)
location-file)))
(and file
(or (and (string-prefix? "/" file) file)
(search-path %load-path file)))))
(define* (home-environment-with-provenance he
#:optional
(config-file
(home-environment-configuration-file
he)))
(define* (home-environment-with-provenance he config-file)
"Return a variant of HE that stores its own provenance information,
including CONFIG-FILE, if available. This is achieved by adding an instance
of HOME-PROVENANCE-SERVICE-TYPE to its services."
@@ -133,21 +114,3 @@ of HOME-PROVENANCE-SERVICE-TYPE to its services."
(run-with-store store (home-environment-derivation he)
#:system system
#:target target)))))
(define %profile-generation-rx
;; Regexp that matches profile generation.
(make-regexp "(.*)-([0-9]+)-link$"))
(define (home-generation-base file)
"If FILE is a Home generation GC root such as \"guix-home-42-link\",
return its corresponding base---e.g., \"guix-home\". Otherwise return #f.
This is similar to the 'generation-profile' procedure but applied to Home
generations."
(match (regexp-exec %profile-generation-rx file)
(#f #f)
(m (let ((profile (match:substring m 1)))
;; Distinguish from a "real" profile and from a system generation.
(and (file-exists? (string-append profile "/on-first-login"))
(file-exists? (string-append profile "/profile/manifest"))
profile)))))
+29 -196
View File
@@ -1,7 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2021-2023 Andrew Tropin <andrew@trop.in>
;;; Copyright © 2021 Andrew Tropin <andrew@trop.in>
;;; Copyright © 2021 Xinglu Chen <public@yoctocell.xyz>
;;; Copyright © 2022-2023 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -21,7 +20,6 @@
(define-module (gnu home services)
#:use-module (gnu services)
#:use-module ((gnu packages package-management) #:select (guix))
#:use-module ((gnu packages base) #:select (coreutils))
#:use-module (guix channels)
#:use-module (guix monads)
#:use-module (guix store)
@@ -33,47 +31,30 @@
#:use-module (guix diagnostics)
#:use-module (guix i18n)
#:use-module (guix modules)
#:use-module (guix memoization)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-9)
#:use-module (ice-9 match)
#:use-module (ice-9 vlist)
#:export (home-service-type
home-profile-service-type
home-environment-variables-service-type
home-files-service-type
home-xdg-configuration-files-service-type
home-xdg-data-files-service-type
home-run-on-first-login-service-type
home-activation-service-type
home-run-on-change-service-type
home-provenance-service-type
literal-string
literal-string?
literal-string-value
with-shell-quotation-bindings
environment-variable-shell-definitions
home-files-directory
xdg-configuration-files-directory
xdg-data-files-directory
fold-home-service-types
lookup-home-service-types
home-provenance
define-service-type-mapping
system->home-service-type
%initialize-gettext)
#:re-export (service
service-type
service-extension
for-home
for-home?))
service-extension))
;;; Comment:
;;;
@@ -184,60 +165,6 @@ packages, configuration files, activation script, and so on.")))
configuration files that the user has declared in their
@code{home-environment} record.")))
;; Representation of a literal string.
(define-record-type <literal-string>
(literal-string str)
literal-string?
(str literal-string-value))
(define (with-shell-quotation-bindings exp)
"Insert EXP, a gexp, in a lexical environment providing the
'shell-single-quote' and 'shell-double-quote' bindings."
#~(let* ((quote-string
(lambda (value quoted-chars)
(list->string (string-fold-right
(lambda (chr lst)
(if (memq chr quoted-chars)
(append (list #\\ chr) lst)
(cons chr lst)))
'()
value))))
(shell-double-quote
(lambda (value)
;; Double-quote VALUE, leaving dollar sign as is.
(string-append "\"" (quote-string value '(#\" #\\))
"\"")))
(shell-single-quote
(lambda (value)
;; Single-quote VALUE to enter a literal string.
(string-append "'" (quote-string value '(#\'))
"'"))))
#$exp))
(define (environment-variable-shell-definitions variables)
"Return a gexp that evaluates to a list of POSIX shell statements defining
VARIABLES, a list of environment variable name/value pairs. The returned code
ensures variable values are properly quoted."
(with-shell-quotation-bindings
#~(string-append
#$@(map (match-lambda
((key . #f)
"")
((key . #t)
#~(string-append "export " #$key "\n"))
((key . (or (? string? value)
(? file-like? value)
(? gexp? value)))
#~(string-append "export " #$key "="
(shell-double-quote #$value)
"\n"))
((key . (? literal-string? value))
#~(string-append "export " #$key "="
(shell-single-quote
#$(literal-string-value value))
"\n")))
variables))))
(define (environment-variables->setup-environment-script vars)
"Return a file that can be sourced by a POSIX compliant shell which
initializes the environment. The file will source the home
@@ -250,7 +177,7 @@ If value is @code{#f} variable will be omitted.
If value is @code{#t} variable will be just exported.
For any other, value variable will be set to the @code{value} and
exported."
(define (warn-about-duplicate-definitions)
(define (warn-about-duplicate-defenitions)
(fold
(lambda (x acc)
(when (equal? (car x) (car acc))
@@ -261,18 +188,15 @@ exported."
(sort vars (lambda (a b)
(string<? (car a) (car b))))))
(warn-about-duplicate-definitions)
(warn-about-duplicate-defenitions)
(with-monad
%store-monad
(return
`(("setup-environment"
;; TODO: It's necessary to source ~/.guix-profile too
;; on foreign distros
,(computed-file "setup-environment"
#~(call-with-output-file #$output
(lambda (port)
(set-port-encoding! port "UTF-8")
(display "\
,(apply mixed-text-file "setup-environment"
"\
HOME_ENVIRONMENT=$HOME/.guix-home
GUIX_PROFILE=\"$HOME_ENVIRONMENT/profile\"
PROFILE_FILE=\"$HOME_ENVIRONMENT/profile/etc/profile\"
@@ -299,10 +223,17 @@ case $XCURSOR_PATH in
*) export XCURSOR_PATH=$HOME_ENVIRONMENT/profile/share/icons:$XCURSOR_PATH ;;
esac
" port)
(display
#$(environment-variable-shell-definitions vars)
port)))))))))
"
(append-map
(match-lambda
((key . #f)
'())
((key . #t)
(list "export " key "\n"))
((key . value)
(list "export " key "=" value "\n")))
vars)))))))
(define home-environment-variables-service-type
(service-type (name 'home-environment-variables)
@@ -352,12 +283,12 @@ directory containing FILES."
(extend append)
(default-value '())
(description "Files that will be put in
@file{~/.guix-home/files}, and further processed during activation.")))
@file{~~/.guix-home/files}, and further processed during activation.")))
(define xdg-configuration-files-directory ".config")
(define xdg-configuration-files-directory "config")
(define (xdg-configuration-files files)
"Add .config/ prefix to each file-path in FILES."
"Add config/ prefix to each file-path in FILES."
(map (match-lambda
((file-path . rest)
(cons (string-append xdg-configuration-files-directory "/" file-path)
@@ -365,7 +296,7 @@ directory containing FILES."
files))
(define home-xdg-configuration-files-service-type
(service-type (name 'home-xdg-configuration)
(service-type (name 'home-files)
(extensions
(list (service-extension home-files-service-type
xdg-configuration-files)))
@@ -373,30 +304,7 @@ directory containing FILES."
(extend append)
(default-value '())
(description "Files that will be put in
@file{~/.guix-home/files/.config}, and further processed during activation.")))
(define xdg-data-files-directory ".local/share")
(define (xdg-data-files files)
"Add .local/share prefix to each file-path in FILES."
(map (match-lambda
((file-path . rest)
(cons (string-append xdg-data-files-directory "/" file-path)
rest)))
files))
(define home-xdg-data-files-service-type
(service-type (name 'home-xdg-data)
(extensions
(list (service-extension home-files-service-type
xdg-data-files)))
(compose concatenate)
(extend append)
(default-value '())
(description "Files that will be put in
@file{~/.guix-home/files/.local/share}, and further processed during
activation.")))
@file{~~/.guix-home/files/config}, and further processed during activation.")))
(define %initialize-gettext
#~(begin
@@ -407,11 +315,9 @@ activation.")))
(define (compute-on-first-login-script _ gexps)
(program-file
"on-first-login"
(with-imported-modules (source-module-closure '((guix i18n)
(guix diagnostics)))
(with-imported-modules (source-module-closure '((guix i18n)))
#~(begin
(use-modules (guix i18n)
(guix diagnostics))
(use-modules (guix i18n))
#$%initialize-gettext
(let* ((xdg-runtime-dir (or (getenv "XDG_RUNTIME_DIR")
@@ -428,7 +334,7 @@ activation.")))
(begin #$@gexps (touch flag-file-path)))
;; TRANSLATORS: 'on-first-login' is the name of a service and
;; shouldn't be translated
(warning (G_ "XDG_RUNTIME_DIR doesn't exists, on-first-login script
(display (G_ "XDG_RUNTIME_DIR doesn't exists, on-first-login script
won't execute anything. You can check if xdg runtime directory exists,
XDG_RUNTIME_DIR variable is set to appropriate value and manually execute the
script by running '$HOME/.guix-home/on-first-login'"))))))))
@@ -459,9 +365,8 @@ extended with one gexp.")))
(he-path (string-append (getenv "HOME") "/.guix-home"))
(new-home-env (getenv "GUIX_NEW_HOME"))
(new-home (or new-home-env
;; Absolute path of the directory of the activation
;; file if called interactively.
(canonicalize-path (dirname (car (command-line))))))
;; Path of the activation file if called interactively
(dirname (car (command-line)))))
(old-home-env (getenv "GUIX_OLD_HOME"))
(old-home (or old-home-env
(if (file-exists? (he-init-file he-path))
@@ -469,9 +374,8 @@ extended with one gexp.")))
#f))))
(if (file-exists? (he-init-file new-home))
(let* ((port ((@ (ice-9 popen) open-input-pipe)
(format #f "source ~a && ~a -0"
(he-init-file new-home)
#$(file-append coreutils "/bin/env"))))
(format #f "source ~a && env -0"
(he-init-file new-home))))
(result ((@ (ice-9 rdelim) read-delimited) "" port))
(vars (map (lambda (x)
(let ((si (string-index x #\=)))
@@ -519,67 +423,6 @@ directory. @command{activate} script automatically called during
reconfiguration or generation switching. This service can be extended
with one gexp, but many times, and all gexps must be idempotent.")))
;;;
;;; Service type graph rewriting.
;;;
(define (service-type-mapping proc)
"Return a procedure that applies PROC to map a service type graph to another
one."
(define (rewrite extension)
(match (proc (service-extension-target extension))
(#f #f)
(target
(service-extension target
(service-extension-compute extension)))))
(define replace
(mlambdaq (type)
(service-type
(inherit type)
(name (symbol-append 'home- (service-type-name type)))
(location (service-type-location type))
(extensions (filter-map rewrite (service-type-extensions type))))))
replace)
(define %system/home-service-type-mapping
;; Mapping of System to Home services.
(make-hash-table))
(define system->home-service-type
;; Map the given System service type to the corresponding Home service type.
(let ()
(define (replace type)
(define replacement
(hashq-ref %system/home-service-type-mapping type
*unspecified*))
(if (eq? replacement *unspecified*)
type
replacement))
(service-type-mapping replace)))
(define-syntax define-service-type-mapping
(syntax-rules (=>)
((_ system-type => home-type)
(hashq-set! %system/home-service-type-mapping
system-type home-type))))
(define-syntax define-service-type-mappings
(syntax-rules (=>)
((_ (system-type => home-type) ...)
(begin
(define-service-type-mapping system-type => home-type)
...))))
(define-service-type-mappings
(system-service-type => home-service-type)
(activation-service-type => home-activation-service-type)
(profile-service-type => home-profile-service-type))
;;;
;;; On-change.
@@ -737,13 +580,3 @@ environment, and its configuration file, when available.")))
(define* (fold-home-service-types proc seed)
(fold-service-types proc seed (all-home-service-modules)))
(define lookup-home-service-types
(let ((table
(delay (fold-home-service-types (lambda (type result)
(vhash-consq (service-type-name type)
type result))
vlist-null))))
(lambda (name)
"Return the list of services with the given NAME (a symbol)."
(vhash-foldq* cons '() name (force table)))))
+9 -173
View File
@@ -1,8 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2022 ( <paren@disroot.org>
;;; Copyright © 2023 conses <contact@conses.eu>
;;; Copyright © 2023 Janneke Nieuwenhuizen <janneke@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -23,25 +20,15 @@
#:use-module (gnu home services)
#:use-module (gnu home services shepherd)
#:use-module (gnu services configuration)
#:autoload (gnu packages glib) (dbus)
#:autoload (gnu packages xdisorg) (redshift unclutter)
#:autoload (gnu packages xorg) (setxkbmap xmodmap)
#:autoload (gnu packages xdisorg) (redshift)
#:use-module (guix records)
#:use-module (guix gexp)
#:use-module (srfi srfi-1)
#:use-module (ice-9 match)
#:export (home-redshift-configuration
home-redshift-configuration?
home-redshift-service-type
home-dbus-configuration
home-dbus-service-type
home-unclutter-configuration
home-unclutter-service-type
home-xmodmap-configuration
home-xmodmap-service-type))
home-redshift-service-type))
;;;
@@ -104,26 +91,26 @@ queried for location information.")
"Nighttime color temperature (kelvins).")
(daytime-brightness
maybe-inexact-number
(maybe-inexact-number 'disabled)
"Daytime screen brightness, between 0.1 and 1.0.")
(nighttime-brightness
maybe-inexact-number
(maybe-inexact-number 'disabled)
"Nighttime screen brightness, between 0.1 and 1.0.")
(latitude
maybe-inexact-number
(maybe-inexact-number 'disabled)
"Latitude, when @code{location-provider} is @code{'manual}.")
(longitude
maybe-inexact-number
(maybe-inexact-number 'disabled)
"Longitude, when @code{location-provider} is @code{'manual}.")
(dawn-time
maybe-string
(maybe-string 'disabled)
"Custom time for the transition from night to day in the
morning---@code{\"HH:MM\"} format. When specified, solar elevation is not
used to determine the daytime/nighttime period.")
(dusk-time
maybe-string
(maybe-string 'disabled)
"Likewise, custom time for the transition from day to night in the
evening.")
@@ -174,8 +161,7 @@ format."))
(start #~(make-forkexec-constructor
(list #$(file-append redshift "/bin/redshift")
"-c" #$config-file)))
(stop #~(make-kill-destructor))
(actions (list (shepherd-configuration-action config-file))))))
(stop #~(make-kill-destructor)))))
(define home-redshift-service-type
(service-type
@@ -186,153 +172,3 @@ format."))
(description
"Run Redshift, a program that adjusts the color temperature of display
according to time of day.")))
;;;
;;; D-Bus.
;;;
(define-record-type* <home-dbus-configuration>
home-dbus-configuration make-home-dbus-configuration
home-dbus-configuration?
(dbus home-dbus-dbus ;file-like
(default dbus)))
(define (home-dbus-shepherd-services config)
(list (shepherd-service
(documentation "Run the D-Bus daemon in session-specific mode.")
(provision '(dbus))
(start #~(make-forkexec-constructor
(list #$(file-append (home-dbus-dbus config)
"/bin/dbus-daemon")
"--nofork" "--session"
(format #f "--address=unix:path=~a/bus"
(or (getenv "XDG_RUNTIME_DIR")
(format #f "/run/user/~a"
(getuid)))))
#:environment-variables
(cons "DBUS_VERBOSE=1"
(default-environment-variables))
#:log-file
(format #f "~a/log/dbus.log"
(or (getenv "XDG_STATE_HOME")
(format #f "~a/.local/state"
(getenv "HOME"))))))
(stop #~(make-kill-destructor)))))
(define (home-dbus-environment-variables config)
'(("DBUS_SESSION_BUS_ADDRESS"
. "unix:path=${XDG_RUNTIME_DIR:-/run/user/$UID}/bus")))
(define home-dbus-service-type
(service-type
(name 'home-dbus)
(extensions
(list (service-extension home-shepherd-service-type
home-dbus-shepherd-services)
(service-extension home-environment-variables-service-type
home-dbus-environment-variables)))
(default-value (home-dbus-configuration))
(description
"Run the session-specific D-Bus inter-process message bus.")))
;;;
;;; Unclutter.
;;;
(define-configuration/no-serialization home-unclutter-configuration
(unclutter
(file-like unclutter)
"The @code{unclutter} package to use.")
(idle-timeout
(integer 5)
"Timeout in seconds after which to hide the cursor."))
(define (home-unclutter-shepherd-service config)
(list
(shepherd-service
(provision '(unclutter))
(requirement '())
(one-shot? #t)
(start #~(make-forkexec-constructor
(list
#$(file-append
(home-unclutter-configuration-unclutter config)
"/bin/unclutter")
"-idle"
(number->string
#$(home-unclutter-configuration-idle-timeout config)))
#:log-file (string-append
(or (getenv "XDG_STATE_HOME")
(format #f "~a/.local/state"
(getenv "HOME")))
"/log/unclutter.log"))))))
(define home-unclutter-service-type
(service-type
(name 'home-unclutter)
(extensions
(list
(service-extension home-shepherd-service-type
home-unclutter-shepherd-service)))
(default-value (home-unclutter-configuration))
(description "Run the @code{unclutter} daemon, which, on systems using the
Xorg graphical display server, automatically hides the cursor after a
user-defined timeout has expired.")))
;;;
;;; Xmodmap.
;;;
(define-configuration/no-serialization home-xmodmap-configuration
(xmodmap
(file-like xmodmap)
"The @code{xmodmap} package to use.")
(key-map
(list '())
"List of expressions to be read by @code{xmodmap} on service startup."))
(define (serialize-xmodmap-configuration field-name val)
(define serialize-field
(match-lambda
((key . value)
(format #f "~a = ~a" key value))
(e e)))
#~(string-append
#$@(interpose (map serialize-field val) "\n" 'suffix)))
(define (xmodmap-shepherd-service config)
(define config-file
(mixed-text-file
"config"
(serialize-xmodmap-configuration
#f (home-xmodmap-configuration-key-map config))))
(list
(shepherd-service
(provision '(xmodmap))
(start #~(make-system-constructor
(string-join
(list #$(file-append
(home-xmodmap-configuration-xmodmap config)
"/bin/xmodmap")
#$config-file))))
(stop #~(make-system-constructor
#$(file-append setxkbmap "/bin/setxkbmap")))
(documentation "On startup, run @code{xmodmap} and read the expressions in
the configuration file. On stop, reset all the mappings back to the
defaults."))))
(define home-xmodmap-service-type
(service-type
(name 'home-xmodmap)
(extensions
(list
(service-extension home-shepherd-service-type
xmodmap-shepherd-service)))
(default-value (home-xmodmap-configuration))
(description "Run the @code{xmodmap} utility to modify keymaps and pointer
buttons under the Xorg display server via user-defined expressions.")))
-34
View File
@@ -1,34 +0,0 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2023 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (gnu home services dict)
#:use-module (gnu home services)
#:use-module (gnu services)
#:use-module (gnu services dict)
#:use-module ((gnu system shadow) #:select (account-service-type))
;; For the 'home-shepherd-service-type' mapping.
#:use-module (gnu home services shepherd)
#:export (home-dicod-service-type)
#:re-export (dicod-configuration))
(define home-dicod-service-type
(service-type
(inherit (system->home-service-type
(remove-service-extensions dicod-service-type
(list account-service-type))))
(default-value (for-home (dicod-configuration)))))
+7 -35
View File
@@ -1,8 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2021 Andrew Tropin <andrew@trop.in>
;;; Copyright © 2021 Xinglu Chen <public@yoctocell.xyz>
;;; Copyright © 2023 Giacomo Leidi <goodoldpaul@autistici.org>
;;; Copyright © 2023 Andrew Patterson <andrewpatt7@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -23,9 +21,6 @@
#:use-module (gnu home services)
#:use-module (gnu packages fontutils)
#:use-module (guix gexp)
#:use-module (srfi srfi-1)
#:use-module (ice-9 match)
#:use-module (sxml simple)
#:export (home-fontconfig-service-type))
@@ -38,36 +33,15 @@
;;;
;;; Code:
(define (write-fontconfig-doctype)
"Prints fontconfig's DOCTYPE to current-output-port."
;; This is necessary because SXML doesn't seem to have a way to represent a doctype,
;; but sxml->xml /does/ currently call any thunks in the SXML with the XML output port
;; as current-output-port, allowing the output to include arbitrary text instead of
;; just properly quoted XML.
(format #t "<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>"))
(define (config->sxml config)
"Converts a <home-fontconfig-configuration> record into the SXML representation
of fontconfig's fonts.conf file."
(define (snippets->sxml snippet)
(match snippet
((or (? string? dir)
(? gexp? dir))
`(dir ,dir))
((? list?)
snippet)))
`(*TOP* (*PI* xml "version='1.0'")
,write-fontconfig-doctype
(fontconfig
,@(map snippets->sxml config))))
(define (add-fontconfig-config-file config)
(define (add-fontconfig-config-file he-symlink-path)
`(("fontconfig/fonts.conf"
,(mixed-text-file
"fonts.conf"
(call-with-output-string
(lambda (port)
(sxml->xml (config->sxml config) port)))))))
"<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>
<dir>~/.guix-home/profile/share/fonts</dir>
</fontconfig>"))))
(define (regenerate-font-cache-gexp _)
`(("profile/share/fonts"
@@ -85,9 +59,7 @@ of fontconfig's fonts.conf file."
(service-extension
home-profile-service-type
(const (list fontconfig)))))
(compose concatenate)
(extend append)
(default-value '("~/.guix-home/profile/share/fonts"))
(default-value #f)
(description
"Provides configuration file for fontconfig and make
fc-* utilities aware of font packages installed in Guix Home's profile.")))
-225
View File
@@ -1,225 +0,0 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2023 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2023 Efraim Flashner <efraim@flashner.co.il>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (gnu home services gnupg)
#:use-module (guix gexp)
#:use-module ((guix records) #:select (match-record))
#:use-module (gnu services)
#:use-module (gnu services configuration)
#:use-module (gnu home services)
#:use-module (gnu home services shepherd)
#:autoload (gnu packages gnupg) (gnupg pinentry parcimonie)
#:export (home-gpg-agent-configuration
home-gpg-agent-configuration?
home-gpg-agent-configuration-gnupg
home-gpg-agent-configuration-pinentry-program
home-gpg-agent-configuration-ssh-support?
home-gpg-agent-configuration-default-cache-ttl
home-gpg-agent-configuration-max-cache-ttl
home-gpg-agent-configuration-max-cache-ttl-ssh
home-gpg-agent-configuration-extra-content
home-gpg-agent-service-type
home-parcimonie-configuration
home-parcimonie-configuration?
home-parcimonie-configuration-parcimonie
home-parcimonie-configuration-gnupg-already-torified?
home-parcimonie-configuration-refresh-guix-keyrings?
home-parcimonie-configuration-extra-content
home-parcimonie-service-type))
(define raw-configuration-string? string?)
;; Configuration of 'gpg-agent'.
(define-configuration/no-serialization home-gpg-agent-configuration
(gnupg
(file-like gnupg)
"The GnuPG package to use.")
(pinentry-program
(file-like (file-append pinentry "/bin/pinentry-curses"))
"Pinentry program to use. Pinentry is a small user interface that
@command{gpg-agent} delegates to anytime it needs user input for a passphrase
or @acronym{PIN, personal identification number} (@pxref{Top,,, pinentry,
Using the PIN-Entry}).")
(ssh-support?
(boolean #f)
"Whether to enable @acronym{SSH, secure shell} support. When true,
@command{gpg-agent} acts as a drop-in replacement for OpenSSH's
@command{ssh-agent} program, taking care of OpenSSH secret keys and directing
passphrase requests to the chosen Pinentry program.")
(default-cache-ttl
(integer 600)
"Time a cache entry is valid, in seconds.")
(max-cache-ttl
(integer 7200)
"Maximum time a cache entry is valid, in seconds. After this time a cache
entry will be expired even if it has been accessed recently.")
(default-cache-ttl-ssh
(integer 1800)
"Time a cache entry for SSH keys is valid, in seconds.")
(max-cache-ttl-ssh
(integer 7200)
"Maximum time a cache entry for SSH keys is valid, in seconds.")
(extra-content
(raw-configuration-string "")
"Raw content to add to the end of @file{~/.gnupg/gpg-agent.conf}."))
(define (home-gpg-agent-configuration-file config)
"Return the @file{gpg-agent.conf} file for @var{config}."
(match-record config <home-gpg-agent-configuration>
(pinentry-program default-cache-ttl max-cache-ttl
default-cache-ttl-ssh max-cache-ttl-ssh
extra-content)
(mixed-text-file "gpg-agent.conf"
"pinentry-program " pinentry-program "\n"
"default-cache-ttl "
(number->string default-cache-ttl) "\n"
"max-cache-ttl "
(number->string max-cache-ttl) "\n"
"default-cache-ttl-ssh "
(number->string default-cache-ttl-ssh) "\n"
"max-cache-ttl-ssh "
(number->string max-cache-ttl-ssh) "\n"
extra-content)))
(define (home-gpg-agent-shepherd-services config)
"Return the possibly-empty list of Shepherd services for @var{config}."
(match-record config <home-gpg-agent-configuration>
(gnupg ssh-support?)
;; 'gpg-agent' is started on demand by GnuPG's programs, but it has to be
;; started explicitly when OpenSSH support is enabled (info "(gnupg) Agent
;; Options").
(if ssh-support?
(let ((endpoint (lambda (name socket)
#~(endpoint
(make-socket-address
AF_UNIX
(string-append %user-runtime-dir
"/gnupg/" #$socket))
#:name #$name
#:socket-directory-permissions #o700))))
(list (shepherd-service
(provision '(gpg-agent ssh-agent))
(modules '((shepherd support))) ;for '%user-runtime-dir'
(start #~(make-systemd-constructor
(list #$(file-append gnupg "/bin/gpg-agent")
"--supervised" "--enable-ssh-support")
(list #$(endpoint "ssh" "S.gpg-agent.ssh")
#$(endpoint "browser" "S.gpg-agent.browser")
#$(endpoint "extra" "S.gpg-agent.extra")
;; #$(endpoint "scdaemon" "S.scdaemon")
#$(endpoint "std" "S.gpg-agent"))))
(stop #~(make-systemd-destructor))
(documentation "Start 'gpg-agent', the GnuPG passphrase
agent, with support for handling OpenSSH material."))))
'())))
(define (home-gpg-agent-files config)
`((".gnupg/gpg-agent.conf" ,(home-gpg-agent-configuration-file config))))
(define (home-gpg-agent-environment-variables config)
"Return GnuPG environment variables needed for @var{config}."
(if (home-gpg-agent-configuration-ssh-support? config)
`(("SSH_AUTH_SOCK"
. "$XDG_RUNTIME_DIR/gnupg/S.gpg-agent.ssh"))
'()))
(define home-gpg-agent-service-type
(service-type
(name 'home-gpg-agent)
(extensions
(list (service-extension home-files-service-type
home-gpg-agent-files)
(service-extension home-shepherd-service-type
home-gpg-agent-shepherd-services)
(service-extension home-environment-variables-service-type
home-gpg-agent-environment-variables)))
(default-value (home-gpg-agent-configuration))
(description
"Configure GnuPG's agent, @command{gpg-agent}, which is responsible for
managing OpenPGP and optionally SSH private keys. When SSH support is
enabled, @command{gpg-agent} acts as a drop-in replacement for OpenSSH's
@command{ssh-agent}.")))
(define-configuration/no-serialization home-parcimonie-configuration
(parcimonie
(file-like parcimonie)
"The parcimonie package to use.")
(verbose?
(boolean #f)
"Provide extra output to the log file.")
(gnupg-aleady-torified?
(boolean #f)
"GnuPG is already configured to use tor and parcimonie won't attempt to use
tor directly.")
(refresh-guix-keyrings?
(boolean #f)
"Also refresh any Guix keyrings found in the XDG_CONFIG_DIR.")
(extra-content
(raw-configuration-string "")
"Raw content to add to the parcimonie service."))
(define (home-parcimonie-shepherd-service config)
"Return a user service to run parcimonie."
(match-record config <home-parcimonie-configuration>
(parcimonie verbose? gnupg-aleady-torified?
refresh-guix-keyrings? extra-content)
(let ((log-file #~(string-append %user-log-dir "/parcimonie.log")))
(list (shepherd-service
(provision '(parcimonie))
(modules '((shepherd support) ;for '%user-log-dir'
(guix build utils)
(srfi srfi-1)))
(start #~(make-forkexec-constructor
(cons*
#$(file-append parcimonie "/bin/parcimonie")
#$@(if verbose?
'("--verbose")
'())
#$@(if gnupg-aleady-torified?
'("--gnupg_already_torified")
'())
#$@(if (not (string=? extra-content ""))
(list extra-content)
'())
#$@(if refresh-guix-keyrings?
'((append-map
(lambda (item)
(list (string-append "--gnupg_extra_args="
"--keyring=" item)))
(find-files
(string-append (getenv "XDG_CONFIG_HOME") "/guix")
"^trustedkeys\\.kbx$")))
'((list))))
#:log-file #$log-file))
(stop #~(make-kill-destructor))
(respawn? #t)
(documentation "Incrementally refresh gnupg keyring over Tor"))))))
(define home-parcimonie-service-type
(service-type
(name 'home-parcimonie)
(extensions
(list (service-extension home-shepherd-service-type
home-parcimonie-shepherd-service)))
(default-value (home-parcimonie-configuration))
(description
"Incrementally refresh GnuPG keyrings over Tor.")))
-44
View File
@@ -1,44 +0,0 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2022 Reily Siegel <mail@reilysiegel.com>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (gnu home services guix)
#:use-module (gnu home services)
#:use-module (guix channels)
#:use-module (guix gexp)
#:use-module (ice-9 pretty-print)
#:use-module (srfi srfi-1)
#:export (home-channels-service-type))
(define (channels-xdg-files channels)
`(("guix/channels.scm"
,(plain-file
"channels.scm"
(call-with-output-string
(lambda (port)
(pretty-print (cons 'list (map channel->code channels)) port)))))))
(define home-channels-service-type
(service-type
(name 'home-channels)
(default-value %default-channels)
(compose concatenate)
(extend append)
(extensions
(list (service-extension home-xdg-configuration-files-service-type
channels-xdg-files)))
(description "Manages the per-user Guix channels specification.")))
-222
View File
@@ -1,222 +0,0 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2023 Tanguy Le Carrour <tanguy@bioneland.org>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (gnu home services mail)
#:use-module (guix gexp)
#:use-module (gnu services)
#:use-module (gnu services configuration)
#:use-module (gnu home services)
#:use-module (gnu home services shepherd)
#:use-module (gnu packages mail)
#:use-module (ice-9 string-fun)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-26)
#:export (home-msmtp-configuration
home-msmtp-configuration?
home-msmtp-configuration-defaults
home-msmtp-configuration-accounts
home-msmtp-configuration-default-account
home-msmtp-configuration-extra-content
home-msmtp-service-type
msmtp-configuration
msmtp-configuration-auth?
msmtp-configuration-tls?
msmtp-configuration-tls-starttls?
msmtp-configuration-tls-trust-file
msmtp-configuration-log-file
msmtp-configuration-host
msmtp-configuration-port
msmtp-configuration-user
msmtp-configuration-from
msmtp-configuration-password-eval
msmtp-configuration-extra-content
msmtp-account
msmtp-account-name
msmtp-account-configuration))
(define-maybe string (prefix msmtp-configuration-))
(define-maybe boolean (prefix msmtp-configuration-))
(define-maybe integer (prefix msmtp-configuration-))
;; Serialization of 'msmtp'.
(define (uglify-symbol field-name)
(let* ((name (symbol->string field-name))
(ugly-name (string-replace-substring name "-" "_")))
(if (string-suffix? "?" ugly-name)
(string-drop-right ugly-name 1)
ugly-name)))
(define (msmtp-configuration-serialize-boolean field-name value)
#~(string-append #$(uglify-symbol field-name) " "
(if #$value "on" "off") "\n"))
(define (msmtp-configuration-serialize-string field-name value)
#~(string-append #$(uglify-symbol field-name) " " #$value "\n"))
(define (msmtp-configuration-serialize-maybe-string-no-underscore field-name value)
#~(if #$(maybe-value-set? value)
(string-append
#$(string-replace-substring (uglify-symbol field-name) "_" "") " " #$value "\n")
""))
(define (msmtp-configuration-serialize-integer field-name value)
#~(string-append #$(uglify-symbol field-name) " "
(number->string #$value) "\n"))
(define (msmtp-configuration-serialize-extra-content field-name value)
#~(if (string=? #$value "") "" (string-append #$value "\n")))
(define (msmtp-account-serialize-name field-name value)
#~(string-append "\naccount " #$value "\n"))
(define (msmtp-account-serialize-msmtp-configuration field-name value)
#~(string-append #$(serialize-configuration value msmtp-configuration-fields)))
(define (home-msmtp-configuration-serialize-list-of-msmtp-accounts field-name value)
#~(string-append #$@(map (cut serialize-configuration <> msmtp-account-fields)
value)))
(define (home-msmtp-configuration-serialize-msmtp-configuration field-name value)
#~(string-append "defaults\n"
#$(serialize-configuration value msmtp-configuration-fields)))
(define (home-msmtp-configuration-serialize-default-account field-name value)
#~(if #$(maybe-value-set? value)
(string-append "\naccount default : " #$value "\n")
""))
(define (home-msmtp-configuration-serialize-extra-content field-name value)
#~(if (string=? #$value "") "" (string-append #$value "\n")))
;; Configuration of 'msmtp'.
;; Source <https://marlam.de/msmtp/msmtp.html#Configuration-files>.
(define-configuration msmtp-configuration
(auth?
maybe-boolean
"Enable or disable authentication.")
(tls?
maybe-boolean
"Enable or disable TLS (also known as SSL) for secured connections.")
(tls-starttls?
maybe-boolean
"Choose the TLS variant: start TLS from within the session (on, default),
or tunnel the session through TLS (off).")
(tls-trust-file
maybe-string
"Activate server certificate verification using a list of
trusted Certification Authorities (CAs).")
(log-file
maybe-string
"Enable logging to the specified file. An empty argument disables logging.
The file name - directs the log information to standard output."
(serializer msmtp-configuration-serialize-maybe-string-no-underscore))
(host
maybe-string
"The SMTP server to send the mail to.")
(port
maybe-integer
"The port that the SMTP server listens on. The default is 25 (\"smtp\"),
unless TLS without STARTTLS is used, in which case it is 465 (\"smtps\").")
(user
maybe-string
"Set the user name for authentication.")
(from
maybe-string
"Set the envelope-from address.")
(password-eval
maybe-string
"Set the password for authentication to the output (stdout) of the command cmd."
(serializer msmtp-configuration-serialize-maybe-string-no-underscore))
(extra-content
(string "")
"Extra content appended as-is to the configuration block. Run
@command{man msmtp} for more information about the configuration file
format."
(serializer msmtp-configuration-serialize-extra-content))
(prefix msmtp-configuration-))
(define-configuration msmtp-account
(name
(string)
"The unique name of the account."
(serializer msmtp-account-serialize-name))
(configuration
(msmtp-configuration)
"The configuration for this given account.")
(prefix msmtp-account-))
(define (list-of-msmtp-accounts? lst)
(every msmtp-account? lst))
(define-configuration home-msmtp-configuration
(defaults
(msmtp-configuration (msmtp-configuration))
"The configuration that will be set as default for all accounts.")
(accounts
(list-of-msmtp-accounts '())
"A list of @code{msmtp-account} records which contain
information about all your accounts.")
(default-account
maybe-string
"Set the default account."
(serializer home-msmtp-configuration-serialize-default-account))
(extra-content
(string "")
"Extra content appended as-is to the configuration file. Run
@command{man msmtp} for more information about the configuration file
format."
(serializer home-msmtp-configuration-serialize-extra-content))
(prefix home-msmtp-configuration-))
(define (home-msmtp-files config)
(list
`(".config/msmtp/config"
,(mixed-text-file "msmtp-config"
(serialize-configuration config home-msmtp-configuration-fields)))))
(define (home-msmtp-profile-entries config)
(list msmtp))
(define home-msmtp-service-type
(service-type (name 'home-msmtp)
(extensions
(list (service-extension home-profile-service-type
home-msmtp-profile-entries)
(service-extension home-files-service-type
home-msmtp-files)))
(default-value (home-msmtp-configuration))
(description "Configure msmtp, a simple
@acronym{SMTP, Simple Mail Transfer Protocol} client that can relay email
to SMTP servers.")))
+66 -15
View File
@@ -1,8 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2021, 2023 Andrew Tropin <andrew@trop.in>
;;; Copyright © 2021 Andrew Tropin <andrew@trop.in>
;;; Copyright © 2021 Xinglu Chen <public@yoctocell.xyz>
;;; Copyright © 2022 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;; Copyright © 2023 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -20,9 +18,15 @@
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (gnu home services mcron)
#:use-module (gnu packages guile-xyz)
#:use-module (gnu home services)
#:use-module (gnu services shepherd)
#:use-module (gnu home services shepherd)
#:use-module (gnu services mcron) ;for the service mapping
#:use-module (guix records)
#:use-module (guix gexp)
#:use-module (srfi srfi-1)
#:use-module (ice-9 match)
#:export (home-mcron-configuration
home-mcron-service-type))
@@ -49,16 +53,63 @@
;;
;;; Code:
(define-syntax-rule (home-mcron-configuration fields ...)
;; Macro provided for backward compatibility.
(for-home (mcron-configuration fields ...)))
(define-record-type* <home-mcron-configuration> home-mcron-configuration
make-home-mcron-configuration
home-mcron-configuration?
(package home-mcron-configuration-package ; package
(default mcron))
(jobs home-mcron-configuration-jobs ; list of jobs
(default '())))
(define job-files (@@ (gnu services mcron) job-files))
(define shepherd-schedule-action
(@@ (gnu services mcron) shepherd-schedule-action))
(define home-mcron-shepherd-services
(match-lambda
(($ <home-mcron-configuration> mcron '()) ; no jobs to run
'())
(($ <home-mcron-configuration> mcron jobs)
(let ((files (job-files mcron jobs)))
(list (shepherd-service
(documentation "User cron jobs.")
(provision '(mcron))
(modules `((srfi srfi-1)
(srfi srfi-26)
(ice-9 popen) ; for the 'schedule' action
(ice-9 rdelim)
(ice-9 match)
,@%default-modules))
(start #~(make-forkexec-constructor
(list #$(file-append mcron "/bin/mcron") #$@files)
#:log-file (string-append
(or (getenv "XDG_LOG_HOME")
(format #f "~a/.local/var/log"
(getenv "HOME")))
"/mcron.log")))
(stop #~(make-kill-destructor))
(actions
(list (shepherd-schedule-action mcron files)))))))))
(define home-mcron-profile (compose list home-mcron-configuration-package))
(define (home-mcron-extend config jobs)
(home-mcron-configuration
(inherit config)
(jobs (append (home-mcron-configuration-jobs config)
jobs))))
(define home-mcron-service-type
(service-type
(inherit (system->home-service-type mcron-service-type))
(default-value (for-home (mcron-configuration)))))
(define-service-type-mapping
mcron-service-type => home-mcron-service-type)
;;; mcron.scm ends here
(service-type (name 'home-mcron)
(extensions
(list (service-extension
home-shepherd-service-type
home-mcron-shepherd-services)
(service-extension
home-profile-service-type
home-mcron-profile)))
(compose concatenate)
(extend home-mcron-extend)
(default-value (home-mcron-configuration))
(description
"Install and configure the GNU mcron cron job manager.")))
-68
View File
@@ -1,68 +0,0 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2023 Janneke Nieuwenhuizen <janneke@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (gnu home services media)
#:use-module (srfi srfi-26)
#:use-module (gnu home services)
#:use-module (gnu home services shepherd)
#:use-module (gnu packages kodi)
#:use-module (gnu services configuration)
#:use-module (gnu services shepherd)
#:use-module (guix records)
#:use-module (guix gexp)
#:export (home-kodi-configuration
home-kodi-service-type))
;;;
;;; Kodi.
;;;
(define-record-type* <home-kodi-configuration>
home-kodi-configuration make-home-kodi-configuration
home-kodi-configuration?
(kodi home-kodi-kodi ;file-like
(default kodi))
(extra-options home-kodi-extra-options ;list of string
(default '())))
(define (home-kodi-services config)
"Return a <shepherd-service> for kodi with CONFIG."
(match-record config <home-kodi-configuration>
(kodi extra-options)
(let* ((kodi (file-append kodi "/bin/kodi"))
(command #~'(#$kodi "-fs" #$@extra-options))
(log-file #~(string-append %user-log-dir "/kodi.log")))
(list (shepherd-service
(documentation "Run the kodi media center.")
(provision '(kodi))
(modules '((shepherd support))) ;for '%user-log-dir'
(start #~(make-forkexec-constructor #$command
#:log-file #$log-file))
(stop #~(make-kill-destructor)))))))
(define home-kodi-service-type
(service-type
(name 'home-kodi)
(default-value (home-kodi-configuration))
(extensions
(list (service-extension home-shepherd-service-type
home-kodi-services)))
(description
"Install and configure the Kodi media center so that it runs as a Shepherd
service.")))
-66
View File
@@ -1,66 +0,0 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2023 Janneke Nieuwenhuizen <janneke@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (gnu home services messaging)
#:use-module (srfi srfi-26)
#:use-module (gnu home services)
#:use-module (gnu home services shepherd)
#:use-module (gnu packages messaging)
#:use-module (gnu services configuration)
#:use-module (gnu services shepherd)
#:use-module (guix records)
#:use-module (guix gexp)
#:export (home-znc-configuration
home-znc-service-type))
;;;
;;; Znc.
;;;
(define-record-type* <home-znc-configuration>
home-znc-configuration make-home-znc-configuration
home-znc-configuration?
(znc home-znc-znc ;string
(default znc))
(extra-options home-znc-extra-options ;list of string
(default '())))
(define (home-znc-services config)
"Return a <shepherd-service> for znc with CONFIG."
(match-record config <home-znc-configuration>
(znc extra-options)
(let* ((znc (file-append znc "/bin/znc"))
(command #~'(#$znc "--foreground" #$@extra-options))
(log-file #~(string-append %user-log-dir "/znc.log")))
(list (shepherd-service
(documentation "Run the znc IRC bouncer.")
(provision '(znc))
(modules '((shepherd support))) ;for '%user-log-dir'
(start #~(make-forkexec-constructor #$command
#:log-file #$log-file))
(stop #~(make-kill-destructor)))))))
(define home-znc-service-type
(service-type
(name 'home-znc)
(default-value (home-znc-configuration))
(extensions
(list (service-extension home-shepherd-service-type
home-znc-services)))
(description
"Install and configure @command{znc}, an @acronym{IRC, Internet Relay
Chat} bouncer, as a Shepherd service.")))
-145
View File
@@ -1,145 +0,0 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2022 ( <paren@disroot.org>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify
;;; it under the terms of the GNU General Public License as published by
;;; the Free Software Foundation, either version 3 of the License, or
;;; (at your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (gnu home services pm)
#:use-module (guix gexp)
#:use-module (guix packages)
#:use-module (guix records)
#:use-module (gnu home services)
#:use-module (gnu home services shepherd)
#:use-module (gnu packages monitoring)
#:use-module (gnu services shepherd)
#:export (home-batsignal-configuration
home-batsignal-service-type))
;;;
;;; batsignal
;;;
;;; Daemon for running commands and displaying notifications on
;;; battery events.
;;;
(define-record-type* <home-batsignal-configuration>
home-batsignal-configuration make-home-batsignal-configuration
home-batsignal-configuration?
(warning-level batsignal-warning-level ;integer
(default 15))
(warning-message batsignal-warning-message ;string | #f
(default #f))
(critical-level batsignal-critical-level ;integer
(default 5))
(critical-message batsignal-critical-message ;string | #f
(default #f))
(danger-level batsignal-danger-level ;integer
(default 2))
(danger-command batsignal-danger-command ;file-like | string | #f
(default #f))
(full-level batsignal-full-level ;integer | #f
(default #f))
(full-message batsignal-full-message ;string | #f
(default #f))
(batteries batsignal-batteries ;list of string
(default '()))
(poll-delay batsignal-poll-delay ;integer
(default 60))
(icon batsignal-icon ;file-like | #f
(default #f))
(notifications? batsignal-notifications? ;boolean
(default #t))
(notifications-expire? batsignal-notifications-expire? ;boolean
(default #f))
(notification-command batsignal-notification-command ;string | #f
(default #f))
(ignore-missing? batsignal-ignore-missing? ;boolean
(default #f)))
(define (home-batsignal-shepherd-services config)
(let ((warning-level (batsignal-warning-level config))
(warning-message (batsignal-warning-message config))
(critical-level (batsignal-critical-level config))
(critical-message (batsignal-critical-message config))
(danger-level (batsignal-danger-level config))
(danger-command (batsignal-danger-command config))
(full-level (batsignal-full-level config))
(full-message (batsignal-full-message config))
(batteries (batsignal-batteries config))
(poll-delay (batsignal-poll-delay config))
(icon (batsignal-icon config))
(notifications? (batsignal-notifications? config))
(notifications-expire? (batsignal-notifications-expire? config))
(notification-command (batsignal-notification-command config))
(ignore-missing? (batsignal-ignore-missing? config)))
(list (shepherd-service
(provision '(batsignal))
(documentation "Run the batsignal battery-watching daemon.")
(start #~(make-forkexec-constructor
(append (list #$(file-append batsignal "/bin/batsignal")
"-w" (number->string #$warning-level)
"-c" (number->string #$critical-level)
"-d" (number->string #$danger-level)
"-m" (number->string #$poll-delay))
(if #$warning-message
(list "-W" #$warning-message)
(list))
(if #$critical-message
(list "-C" #$critical-message)
(list))
(if #$danger-command
(list "-D" #$danger-command)
(list))
(if #$full-level
(list "-f" (number->string #$full-level))
(list))
(if #$full-message
(list "-F" #$full-message)
(list))
(if (null? (list #$@batteries))
(list)
(list "-n" (string-join (list #$@batteries) ",")))
(if #$icon
(list "-I" #$icon)
(list))
(if #$notifications?
(list)
(list "-N"))
(if #$notifications-expire?
(list "-e")
(list))
(if #$notification-command
(list "-M" #$notification-command)
(list))
(if #$ignore-missing?
(list "-i")
(list)))
#:log-file (string-append
(or (getenv "XDG_STATE_HOME")
(format #f "~a/.local/state"
(getenv "HOME")))
"/log/batsignal.log")))
(stop #~(make-kill-destructor))))))
(define home-batsignal-service-type
(service-type
(name 'home-batsignal)
(extensions
(list (service-extension home-shepherd-service-type
home-batsignal-shepherd-services)))
(default-value (home-batsignal-configuration))
(description
"Run batsignal, a battery watching and notification daemon.")))
+114 -219
View File
@@ -1,7 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2021 Andrew Tropin <andrew@trop.in>
;;; Copyright © 2021 Xinglu Chen <public@yoctocell.xyz>
;;; Copyright © 2023 Efraim Flashner <efraim@flashner.co.il>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -20,14 +19,12 @@
(define-module (gnu home services shells)
#:use-module (gnu services configuration)
#:autoload (gnu system shadow) (%default-bashrc)
#:use-module (gnu home services utils)
#:use-module (gnu home services)
#:use-module (gnu packages shells)
#:use-module (gnu packages bash)
#:use-module (guix gexp)
#:use-module (guix packages)
#:use-module (guix records)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-26)
#:use-module (ice-9 match)
@@ -45,10 +42,7 @@
home-fish-service-type
home-fish-configuration
home-fish-extension
home-inputrc-service-type
home-inputrc-configuration))
home-fish-extension))
;;; Commentary:
;;;
@@ -83,7 +77,7 @@ user's customizations. Extend home-shell-profile service only if you
really know what you do."))
(define (add-shell-profile-file config)
`((".profile"
`(("profile"
,(mixed-text-file
"shell-profile"
"\
@@ -117,7 +111,16 @@ service type can be extended with a list of file-like objects.")))
(define (serialize-boolean field-name val) "")
(define (serialize-posix-env-vars field-name val)
(environment-variable-shell-definitions val))
#~(string-append
#$@(map
(match-lambda
((key . #f)
"")
((key . #t)
#~(string-append "export " #$key "\n"))
((key . value)
#~(string-append "export " #$key "=" #$value "\n")))
val)))
;;;
@@ -137,7 +140,7 @@ Shell startup process will continue with
(environment-variables
(alist '())
"Association list of environment variables to set for the Zsh session."
(serializer serialize-posix-env-vars))
serialize-posix-env-vars)
(zshenv
(text-config '())
"List of file-like objects, which will be added to @file{.zshenv}.
@@ -189,9 +192,9 @@ another process for example)."))
(mixed-text-file
"zprofile"
"\
# Set up the system, user profile, and related variables.
# Setups system and user profiles and related variables
source /etc/profile
# Set up the home environment profile.
# Setups home environment profile
source ~/.profile
# It's only necessary if zsh is a login shell, otherwise profiles will
@@ -208,18 +211,18 @@ source ~/.profile
(zsh-serialize-field config field)))))
(define (zsh-get-configuration-files config)
`((".zprofile" ,(zsh-file-by-field config 'zprofile)) ;; Always non-empty
,@(if (or (zsh-field-not-empty? config 'zshenv)
(zsh-field-not-empty? config 'environment-variables))
`((".zshenv" ,(zsh-file-by-field config 'zshenv))) '())
`(("zprofile" ,(zsh-file-by-field config 'zprofile)) ;; Always non-empty
,@(if (and (zsh-field-not-empty? config 'zshenv)
(zsh-field-not-empty? config 'environment-variables))
`(("zshenv" ,(zsh-file-by-field config 'zshenv))) '())
,@(if (zsh-field-not-empty? config 'zshrc)
`((".zshrc" ,(zsh-file-by-field config 'zshrc))) '())
`(("zshrc" ,(zsh-file-by-field config 'zshrc))) '())
,@(if (zsh-field-not-empty? config 'zlogin)
`((".zlogin" ,(zsh-file-by-field config 'zlogin))) '())
`(("zlogin" ,(zsh-file-by-field config 'zlogin))) '())
,@(if (zsh-field-not-empty? config 'zlogout)
`((".zlogout" ,(zsh-file-by-field config 'zlogout))) '())))
`(("zlogout" ,(zsh-file-by-field config 'zlogout))) '())))
(define (add-zsh-dot-configuration config)
(define (zsh-home-files config)
(define zshenv-auxiliary-file
(mixed-text-file
"zshenv-auxiliary"
@@ -227,14 +230,14 @@ source ~/.profile
"[[ -f $ZDOTDIR/.zshenv ]] && source $ZDOTDIR/.zshenv\n"))
(if (home-zsh-configuration-xdg-flavor? config)
`((".zshenv" ,zshenv-auxiliary-file))
`(("zshenv" ,zshenv-auxiliary-file))
(zsh-get-configuration-files config)))
(define (add-zsh-xdg-configuration config)
(define (zsh-xdg-configuration-files config)
(if (home-zsh-configuration-xdg-flavor? config)
(map
(lambda (lst)
(cons (string-append "zsh/" (car lst))
(cons (string-append "zsh/." (car lst))
(cdr lst)))
(zsh-get-configuration-files config))
'()))
@@ -295,10 +298,10 @@ source ~/.profile
(extensions
(list (service-extension
home-files-service-type
add-zsh-dot-configuration)
zsh-home-files)
(service-extension
home-xdg-configuration-files-service-type
add-zsh-xdg-configuration)
zsh-xdg-configuration-files)
(service-extension
home-profile-service-type
add-zsh-packages)))
@@ -313,24 +316,16 @@ source ~/.profile
;;;
(define (bash-serialize-aliases field-name val)
(with-shell-quotation-bindings
#~(string-append
#$@(map
(match-lambda
((key . #f)
"")
((key . #t)
#~(string-append "alias " #$key "\n"))
((key . (? literal-string? value))
#~(string-append "alias " #$key "="
(shell-single-quote
#$(literal-string-value value))
"\n"))
((key . value)
#~(string-append "alias " #$key "="
(shell-double-quote #$value)
"\n")))
val))))
#~(string-append
#$@(map
(match-lambda
((key . #f)
"")
((key . #t)
#~(string-append "alias " #$key "\n"))
((key . value)
#~(string-append "alias " #$key "=\"" #$value "\"\n")))
val)))
(define-configuration home-bash-configuration
(package
@@ -346,7 +341,7 @@ source ~/.profile
rules for the @code{home-environment-variables-service-type} apply
here (@pxref{Essential Home Services}). The contents of this field will be
added after the contents of the @code{bash-profile} field."
(serializer serialize-posix-env-vars))
serialize-posix-env-vars)
(aliases
(alist '())
"Association list of aliases to set for the Bash session. The aliases will be
@@ -363,7 +358,7 @@ turns into
@example
alias ls=\"ls -alF\"
@end example"
(serializer bash-serialize-aliases))
bash-serialize-aliases)
(bash-profile
(text-config '())
"List of file-like objects, which will be added to @file{.bash_profile}.
@@ -383,6 +378,43 @@ Used for executing user's commands at the exit of login shell. It
won't be read in some cases (if the shell terminates by exec'ing
another process for example)."))
;; TODO: Use value from (gnu system shadow)
(define guix-bashrc
"\
# Bash initialization for interactive non-login shells and
# for remote shells (info \"(bash) Bash Startup Files\").
# Export 'SHELL' to child processes. Programs such as 'screen'
# honor it and otherwise use /bin/sh.
export SHELL
if [[ $- != *i* ]]
then
# We are being invoked from a non-interactive shell. If this
# is an SSH session (as in \"ssh host command\"), source
# /etc/profile so we get PATH and other essential variables.
[[ -n \"$SSH_CLIENT\" ]] && source /etc/profile
# Don't do anything else.
return
fi
# Source the system-wide file.
if [[ -e /etc/bashrc ]]; then
source /etc/bashrc
fi
# Adjust the prompt depending on whether we're in 'guix environment'.
if [ -n \"$GUIX_ENVIRONMENT\" ]
then
PS1='\\u@\\h \\w [env]\\$ '
else
PS1='\\u@\\h \\w\\$ '
fi
alias ls='ls -p --color=auto'
alias ll='ls -l'
alias grep='grep --color=auto'\n")
(define (add-bash-configuration config)
(define (filter-fields field)
(filter-configuration-fields home-bash-configuration-fields
@@ -398,7 +430,7 @@ another process for example)."))
(field-obj (car (filter-fields field))))
(if (or extra-content
(not (null? ((configuration-field-getter field-obj) config))))
`(,(string-append "." (object->snake-case-string file-name))
`(,(object->snake-case-string file-name)
,(apply mixed-text-file
(object->snake-case-string file-name)
(append (or extra-content '())
@@ -407,35 +439,25 @@ another process for example)."))
(filter
(compose not null?)
`((".bash_profile"
`(("bash_profile"
,(mixed-text-file
"bash_profile"
"\
# Set up the system, user profile, and related variables.
# Setups system and user profiles and related variables
# /etc/profile will be sourced by bash automatically
# Set up the home environment profile.
# Setups home environment profile
if [ -f ~/.profile ]; then source ~/.profile; fi
# Honor per-interactive-shell startup file
if [ -f ~/.bashrc ]; then source ~/.bashrc; fi
"
;; The host distro might provide a bad 'PS1' default--e.g., not taking
;; $GUIX_ENVIRONMENT into account. Provide a good default here when
;; asked to. The default can be overridden below via
;; 'environment-variables'.
(if (home-bash-configuration-guix-defaults? config)
"PS1='\\u@\\h \\w${GUIX_ENVIRONMENT:+ [env]}\\$ '\n"
"")
(serialize-field 'bash-profile)
(serialize-field 'environment-variables)))
,@(list (file-if-not-empty
'bashrc
(if (home-bash-configuration-guix-defaults? config)
(list (serialize-field 'aliases)
(plain-file-content %default-bashrc))
(list (serialize-field 'aliases) guix-bashrc)
(list (serialize-field 'aliases))))
(file-if-not-empty 'bash-logout)))))
@@ -466,30 +488,31 @@ with text blocks from other extensions and the base service.")
with text blocks from other extensions and the base service."))
(define (home-bash-extensions original-config extension-configs)
(match-record original-config <home-bash-configuration>
(environment-variables aliases bash-profile bashrc bash-logout)
(home-bash-configuration
(inherit original-config)
(environment-variables
(append environment-variables
(append-map
home-bash-extension-environment-variables extension-configs)))
(aliases
(append aliases
(append-map
home-bash-extension-aliases extension-configs)))
(bash-profile
(append bash-profile
(append-map
home-bash-extension-bash-profile extension-configs)))
(bashrc
(append bashrc
(append-map
home-bash-extension-bashrc extension-configs)))
(bash-logout
(append bash-logout
(append-map
home-bash-extension-bash-logout extension-configs))))))
(match original-config
(($ <home-bash-configuration> _ _ _ environment-variables aliases
bash-profile bashrc bash-logout)
(home-bash-configuration
(inherit original-config)
(environment-variables
(append environment-variables
(append-map
home-bash-extension-environment-variables extension-configs)))
(aliases
(append aliases
(append-map
home-bash-extension-aliases extension-configs)))
(bash-profile
(append bash-profile
(append-map
home-bash-extension-bash-profile extension-configs)))
(bashrc
(append bashrc
(append-map
home-bash-extension-bashrc extension-configs)))
(bash-logout
(append bash-logout
(append-map
home-bash-extension-bash-logout extension-configs)))))))
(define home-bash-service-type
(service-type (name 'home-bash)
@@ -532,9 +555,9 @@ with text blocks from other extensions and the base service."))
((key . #f)
"")
((key . #t)
#~(string-append "set -x " #$key "\n"))
#~(string-append "set " #$key "\n"))
((key . value)
#~(string-append "set -x " #$key " " #$value "\n")))
#~(string-append "set " #$key " " #$value "\n")))
val)))
(define-configuration home-fish-configuration
@@ -548,22 +571,22 @@ with text blocks from other extensions and the base service."))
(environment-variables
(alist '())
"Association list of environment variables to set in Fish."
(serializer serialize-fish-env-vars))
serialize-fish-env-vars)
(aliases
(alist '())
"Association list of aliases for Fish, both the key and the value
should be a string. An alias is just a simple function that wraps a
command, If you want something more akin to @dfn{aliases} in POSIX
shells, see the @code{abbreviations} field."
(serializer serialize-fish-aliases))
serialize-fish-aliases)
(abbreviations
(alist '())
"Association list of abbreviations for Fish. These are words that,
when typed in the shell, will automatically expand to the full text."
(serializer serialize-fish-abbreviations)))
serialize-fish-abbreviations))
(define (fish-files-service config)
`(("fish/config.fish"
`(("config/fish/config.fish"
,(mixed-text-file
"fish-config.fish"
#~(string-append "\
@@ -627,7 +650,7 @@ end\n\n")
(service-type (name 'home-fish)
(extensions
(list (service-extension
home-xdg-configuration-files-service-type
home-files-service-type
fish-files-service)
(service-extension
home-profile-service-type
@@ -638,134 +661,6 @@ end\n\n")
(description "\
Install and configure Fish, the friendly interactive shell.")))
;;;
;;; Readline.
;;;
(define (serialize-inputrc-key-bindings field-name val)
#~(string-append
#$@(map
(match-lambda
((key . value)
#~(string-append #$key ": " #$value "\n")))
val)))
(define (serialize-inputrc-variables field-name val)
#~(string-append
#$@(map
(match-lambda
((key . #f)
#~(string-append "set " #$key " off\n"))
((key . #t)
#~(string-append "set " #$key " on\n"))
((key . value)
#~(string-append "set " #$key " " #$value "\n")))
val)))
(define (serialize-inputrc-conditional-constructs field-name val)
#~(string-append
#$@(map
(match-lambda
(("$endif" . _)
"$endif\n")
(("$include" . value)
#~(string-append "$include " #$value "\n"))
;; TODO: key can only be "$if" or "$else".
((key . value)
#~(string-append #$key "\n"
#$(serialize-configuration
value
home-inputrc-configuration-fields))))
val)))
(define (serialize-inputrc-extra-content field-name value)
#~(if (string=? #$value "") "" (string-append #$value "\n")))
(define-configuration home-inputrc-configuration
(key-bindings
(alist '())
"Association list of readline key bindings to be added to the
@code{~/.inputrc} file. This is where code like this:
@lisp
'((\"Control-l\" . \"clear-screen\"))
@end lisp
turns into
@example
Control-l: clear-screen
@end example"
(serializer serialize-inputrc-key-bindings))
(variables
(alist '())
"Association list of readline variables to set. This is where configuration
options like this:
@lisp
'((\"bell-style\" . \"visible\")
(\"colored-completion-prefix\" . #t))
@end lisp
turns into
@example
set bell-style visible
set colored-completion-prefix on
@end example"
(serializer serialize-inputrc-variables))
(conditional-constructs
(alist '())
"Association list of conditionals to add to the initialization file. This
includes @command{$if}, @command{else}, @command{endif} and @command{include}
and they receive a value of another @command{home-inputrc-configuration}.
@lisp
(conditional-constructs
`((\"$if mode=vi\" .
,(home-inputrc-configuration
(variables
`((\"show-mode-in-prompt\" . #t)))))
(\"$else\" .
,(home-inputrc-configuration
(key-bindings
`((\"Control-l\" . \"clear-screen\")))))
(\"$endif\" . #t)))
@end lisp
turns into
@example
$if mode=vi
set show-mode-in-prompt on
$else
Control-l: clear-screen
$endif
@end example"
(serializer serialize-inputrc-conditional-constructs))
(extra-content
(string "")
"Extra content appended as-is to the configuration file. Run @command{man
readline} for more information about all the configuration options."
(serializer serialize-inputrc-extra-content)))
(define (home-inputrc-files config)
(list
`(".inputrc"
,(mixed-text-file "inputrc"
(serialize-configuration
config
home-inputrc-configuration-fields)))))
(define home-inputrc-service-type
(service-type (name 'inputrc)
(extensions
(list (service-extension home-files-service-type
home-inputrc-files)))
(default-value (home-inputrc-configuration))
(description "Configure readline in @code{.inputrc}.")))
(define (generate-home-shell-profile-documentation)
(generate-documentation
+35 -59
View File
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2021, 2023 Andrew Tropin <andrew@trop.in>
;;; Copyright © 2021 Andrew Tropin <andrew@trop.in>
;;; Copyright © 2021 Xinglu Chen <public@yoctocell.xyz>
;;;
;;; This file is part of GNU Guix.
@@ -45,32 +45,28 @@
shepherd-service-auto-start?
shepherd-service-modules
shepherd-action
shepherd-configuration-action))
shepherd-action))
(define-record-type* <home-shepherd-configuration>
home-shepherd-configuration make-home-shepherd-configuration
home-shepherd-configuration?
(shepherd home-shepherd-configuration-shepherd
(default shepherd-0.10)) ; package
(default shepherd)) ; package
(auto-start? home-shepherd-configuration-auto-start?
(default #t))
(daemonize? home-shepherd-configuration-daemonize?
(default #t))
(services home-shepherd-configuration-services
(default '())))
(define (home-shepherd-configuration-file config)
(define (home-shepherd-configuration-file services shepherd)
"Return the shepherd configuration file for SERVICES. SHEPHERD is used
as shepherd package."
(let* ((daemonize? (home-shepherd-configuration-daemonize? config))
(services (home-shepherd-configuration-services config))
(_ (assert-valid-graph services))
(files (map shepherd-service-file services))
;; TODO: Add compilation of services, it can improve start
;; time.
;; (scm->go (cute scm->go <> shepherd))
)
(assert-valid-graph services)
(let ((files (map shepherd-service-file services))
;; TODO: Add compilation of services, it can improve start
;; time.
;; (scm->go (cute scm->go <> shepherd))
)
(define config
#~(begin
(use-modules (srfi srfi-34)
@@ -80,54 +76,42 @@ as shepherd package."
(map
(lambda (file) (load file))
'#$files))
#$@(if daemonize?
`((action 'root 'daemonize))
'())
(action 'root 'daemonize)
(format #t "Starting services...~%")
(let ((services-to-start
'#$(append-map shepherd-service-provision
(filter shepherd-service-auto-start?
services))))
(if (defined? 'start-in-the-background)
(start-in-the-background services-to-start)
(for-each start services-to-start))
(redirect-port (open-input-file "/dev/null")
(current-input-port)))))
(for-each
(lambda (service) (start service))
'#$(append-map shepherd-service-provision
(filter shepherd-service-auto-start?
services)))
(newline)))
(scheme-file "shepherd.conf" config)))
(define (launch-shepherd-gexp config)
(let* ((shepherd (home-shepherd-configuration-shepherd config)))
(let* ((shepherd (home-shepherd-configuration-shepherd config))
(services (home-shepherd-configuration-services config)))
(if (home-shepherd-configuration-auto-start? config)
(with-imported-modules '((guix build utils))
#~(unless (file-exists?
(string-append
(or (getenv "XDG_RUNTIME_DIR")
(format #f "/run/user/~a" (getuid)))
"/shepherd/socket"))
(let* ((state-dir (or (getenv "XDG_STATE_HOME")
(format #f "~a/.local/state"
(getenv "HOME"))))
(log-dir (string-append state-dir "/log")))
;; TODO: Remove it, 0.9.2 creates it automatically?
((@ (guix build utils) mkdir-p) log-dir)
(system*
#$(file-append shepherd "/bin/shepherd")
"--logfile"
(string-append log-dir "/shepherd.log")
"--config"
#$(home-shepherd-configuration-file config)))))
#~(let ((log-dir (or (getenv "XDG_LOG_HOME")
(format #f "~a/.local/var/log" (getenv "HOME")))))
((@ (guix build utils) mkdir-p) log-dir)
(system*
#$(file-append shepherd "/bin/shepherd")
"--logfile"
(string-append
log-dir
"/shepherd.log")
"--config"
#$(home-shepherd-configuration-file services shepherd))))
#~"")))
(define (reload-configuration-gexp config)
(let* ((shepherd (home-shepherd-configuration-shepherd config)))
(let* ((shepherd (home-shepherd-configuration-shepherd config))
(services (home-shepherd-configuration-services config)))
#~(system*
#$(file-append shepherd "/bin/herd")
"load" "root"
#$(home-shepherd-configuration-file config))))
#$(home-shepherd-configuration-file services shepherd))))
(define (ensure-shepherd-gexp config)
#~(if (file-exists?
@@ -138,18 +122,12 @@ as shepherd package."
#$(reload-configuration-gexp config)
#$(launch-shepherd-gexp config)))
(define (shepherd-xdg-configuration-files config)
`(("shepherd/init.scm" ,(home-shepherd-configuration-file config))))
(define home-shepherd-service-type
(define-public home-shepherd-service-type
(service-type (name 'home-shepherd)
(extensions
(list (service-extension
home-run-on-first-login-service-type
launch-shepherd-gexp)
(service-extension
home-xdg-configuration-files-service-type
shepherd-xdg-configuration-files)
(service-extension
home-activation-service-type
ensure-shepherd-gexp)
@@ -168,6 +146,4 @@ as shepherd package."
(default-value (home-shepherd-configuration))
(description "Configure and install userland Shepherd.")))
(define-service-type-mapping
shepherd-root-service-type => home-shepherd-service-type)
-151
View File
@@ -1,151 +0,0 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2023 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (gnu home services sound)
#:use-module (gnu home services)
#:use-module (gnu home services shepherd)
#:use-module (guix records)
#:use-module (guix gexp)
#:use-module (srfi srfi-1)
#:use-module (ice-9 match)
#:export (home-pulseaudio-rtp-sink-service-type
home-pulseaudio-rtp-source-service-type
%pulseaudio-rtp-multicast-address))
;;;
;;; PulseAudio support.
;;;
(define (with-pulseaudio-connection sock exp)
;; Wrap EXP in an expression where SOCK is bound to a socket connected to
;; the user's PulseAudio command-line interface socket.
#~(let* ((#$sock (socket AF_UNIX SOCK_STREAM 0))
(pulse-user-file
(lambda (name)
(string-append "/run/user/" (number->string (getuid))
"/pulse/" name)))
(file (pulse-user-file "cli")))
(let loop ((tries 0))
(catch #t
(lambda ()
(connect #$sock AF_UNIX file)
(let ((result #$exp))
(close-port #$sock)
result))
(lambda (key . args)
(if (and (eq? key 'system-error)
(= ENOENT (system-error-errno (cons key args)))
(< tries 3))
;; The CLI socket doesn't exist yet, so send pulseaudio
;; SIGUSR2 so that it creates it and listens to it.
(let ((pid (call-with-input-file (pulse-user-file "pid")
read)))
(when (and (integer? pid) (> pid 1))
(kill pid SIGUSR2))
((@ (fibers) sleep) 1)
(loop (+ tries 1)))
(begin
(close-port #$sock)
(apply throw key args))))))))
(define %pulseaudio-rtp-multicast-address
;; Default address used by 'module-rtp-sink' and 'module-rtp-recv'. This is
;; a multicast address, for the Session Announcement Protocol (SAP) and the
;; Session Description Protocol (SDP).
"224.0.0.56")
(define (pulseaudio-rtp-sink-shepherd-services destination-ip)
(list (shepherd-service
(provision '(pulseaudio-rtp-sink))
(start
#~(lambda* (#:optional (destination-ip #$destination-ip))
#$(with-pulseaudio-connection
#~sock
#~(begin
(display "\
load-module module-null-sink \
sink_name=rtp sink_properties=\"device.description='RTP network output'\"\n"
sock)
(display (string-append "\
load-module module-rtp-send source=rtp.monitor"
(if destination-ip
(string-append
" destination_ip="
destination-ip)
"")
"\n")
sock)
#t))))
(stop
#~(lambda (_)
#$(with-pulseaudio-connection
#~sock
#~(begin
(display "unload-module module-rtp-send\n"
sock)
(display "unload-module module-null-sink\n"
sock)
#f))))
(auto-start? #f))))
(define home-pulseaudio-rtp-sink-service-type
(service-type
(name 'pulseaudio-rtp-sink)
(extensions
(list (service-extension home-shepherd-service-type
pulseaudio-rtp-sink-shepherd-services)))
(description
"Define a PulseAudio sink to broadcast audio output over RTP, which can
then by played by another PulseAudio instance.")
;; By default, send to the SAP multicast address, 224.0.0.56, which can be
;; network-intensive.
(default-value %pulseaudio-rtp-multicast-address)))
(define (pulseaudio-rtp-source-shepherd-services source-ip)
(list (shepherd-service
(provision '(pulseaudio-rtp-source))
(start
#~(lambda* (#:optional (source-ip #$source-ip))
#$(with-pulseaudio-connection
#~sock
#~(begin
(format sock "\
load-module module-rtp-recv sap_address=~a\n" source-ip)
#t))))
(stop
#~(lambda (_)
#$(with-pulseaudio-connection
#~sock
#~(begin
(display "unload-module module-rtp-recv\n"
sock)
#f))))
(auto-start? #f))))
(define home-pulseaudio-rtp-source-service-type
(service-type
(name 'pulseaudio-rtp-source)
(extensions
(list (service-extension home-shepherd-service-type
pulseaudio-rtp-source-shepherd-services)))
(description
"Define a PulseAudio source to receive audio broadcasted over RTP by
another PulseAudio instance.")
(default-value %pulseaudio-rtp-multicast-address)))
-463
View File
@@ -1,463 +0,0 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2023 Janneke Nieuwenhuizen <janneke@gnu.org>
;;; Copyright © 2023 Nicolas Graves <ngraves@ngraves.fr>
;;; Copyright © 2023 Efraim Flashner <efraim@flashner.co.il>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (gnu home services ssh)
#:use-module (guix gexp)
#:use-module (guix records)
#:use-module (guix deprecation)
#:use-module (guix diagnostics)
#:use-module (guix i18n)
#:use-module (gnu services)
#:use-module (gnu services configuration)
#:use-module (guix modules)
#:use-module (gnu home services)
#:use-module (gnu home services shepherd)
#:use-module ((gnu home services utils)
#:select (object->camel-case-string))
#:autoload (gnu packages base) (glibc-utf8-locales)
#:use-module (gnu packages ssh)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-9)
#:use-module (srfi srfi-9 gnu)
#:use-module (srfi srfi-34)
#:use-module (srfi srfi-35)
#:use-module (ice-9 match)
#:autoload (ice-9 regex) (string-match match:substring)
#:export (home-openssh-configuration
home-openssh-configuration-authorized-keys
home-openssh-configuration-known-hosts
home-openssh-configuration-hosts
home-openssh-configuration-add-keys-to-agent
home-openssh-configuration?
home-ssh-agent-configuration
home-ssh-agent-openssh
home-ssh-agent-socket-directory
home-ssh-agent-extra-options
home-ssh-agent-configuration?
openssh-host
openssh-host-host-name
openssh-host-match-criteria
openssh-host-identity-file
openssh-host-name
openssh-host-port
openssh-host-user
openssh-host-forward-x11?
openssh-host-forward-x11-trusted?
openssh-host-forward-agent?
openssh-host-compression?
openssh-host-proxy-command
openssh-host-host-key-algorithms
openssh-host-accepted-key-types
openssh-host-extra-content
proxy-jump
proxy-jump-host-name
proxy-jump-port
proxy-jump-user
proxy-command
proxy-command->string
home-openssh-service-type
home-ssh-agent-service-type))
(define (serialize-field-name name)
(match name
('accepted-key-types "PubkeyAcceptedKeyTypes")
(_
(let ((name (let ((str (symbol->string name)))
(if (string-suffix? "?" str)
(string->symbol (string-drop-right str 1))
name))))
(object->camel-case-string name 'upper)))))
(define (serialize-string field value)
(string-append " " (serialize-field-name field)
" " value "\n"))
(define (address-family? obj)
(memv obj (list AF_INET AF_INET6)))
(define-maybe address-family)
(define (serialize-address-family field family)
(if (maybe-value-set? family)
(string-append " " (serialize-field-name field) " "
(cond ((= family AF_INET) "inet")
((= family AF_INET6) "inet6")
;; The 'else' branch is unreachable.
(else
(raise
(formatted-message
(G_ "~s: invalid address family value")
family))))
"\n")
""))
(define (natural-number? obj)
(and (integer? obj) (exact? obj) (> obj 0)))
(define (serialize-natural-number field value)
(string-append " " (serialize-field-name field) " "
(number->string value) "\n"))
(define-maybe boolean)
(define (serialize-boolean field value)
(string-append " " (serialize-field-name field) " "
(if value "yes" "no") "\n"))
(define-maybe string)
(define-maybe natural-number)
(define (serialize-raw-configuration-string field value)
(string-append value "\n"))
(define raw-configuration-string? string?)
(define (string-list? lst)
(and (pair? lst) (every string? lst)))
(define (serialize-string-list field lst)
(string-append " " (serialize-field-name field) " "
(string-join lst ",") "\n"))
(define-maybe string-list)
(define-record-type <proxy-command>
(proxy-command command)
proxy-command?
(command proxy-command->string))
(set-record-type-printer! <proxy-command>
(lambda (obj port)
(format port "#<proxy-command ~s>" (proxy-command->string obj))))
(define-configuration/no-serialization proxy-jump
(user
maybe-string
"User name on the remote host.")
(host-name
(string)
"Host name---e.g., @code{foo.example.org} or @code{192.168.1.2}.")
(port
maybe-natural-number
"TCP port number to connect to."))
(define (proxy-jump->string proxy-jump)
(match-record proxy-jump <proxy-jump>
(host-name user port)
(string-append
(if (maybe-value-set? user) (string-append user "@") "")
host-name
(if (maybe-value-set? port) (string-append ":" (number->string port)) ""))))
(define (proxy-command-or-jump-list? x)
(or (proxy-command? x)
(and (list? x)
(every proxy-jump? x))))
(define (serialize-proxy-command-or-jump-list field value)
(if (proxy-command? value)
(serialize-string 'proxy-command (proxy-command->string value))
(serialize-string-list 'proxy-jump (map proxy-jump->string value))))
(define-maybe proxy-command-or-jump-list)
(define (sanitize-proxy-command properties)
(lambda (value)
(when (maybe-value-set? value)
(warn-about-deprecation 'proxy-command properties #:replacement 'proxy))
(unless (maybe-string? value)
(configuration-field-error (source-properties->location properties) 'proxy-command value))
value))
(define ssh-match-keywords
'(canonical final exec host originalhost user localuser))
(define (match-criteria? str)
;; Rule out the case of "all" keyword.
(if (member str '("all"
"canonical all"
"final all"))
#t
(let* ((first (string-take str (string-index str #\ )))
(keyword (string->symbol (if (string-prefix? "!" first)
(string-drop first 1)
first))))
(memq keyword ssh-match-keywords))))
(define (serialize-match-criteria _ value)
(string-append "Match " value "\n"))
(define-maybe match-criteria)
(define-configuration openssh-host
(name
maybe-string
"Name of this host declaration. A @code{openssh-host} must define only
@code{name} or @code{match-criteria}. Use host-name @code{\"*\"} for
top-level options.")
(host-name
maybe-string
"Host name---e.g., @code{\"foo.example.org\"} or @code{\"192.168.1.2\"}.")
(match-criteria
maybe-match-criteria
"When specified, this string denotes the set of hosts to which the entry
applies, superseding the @code{host-name} field. Its first element must be
all or one of @code{ssh-match-keywords}. The rest of the elements are
arguments for the keyword, or other criteria. A @code{openssh-host} must
define only @code{name} or @code{match-criteria}. Other host configuration
options will apply to all hosts matching @code{match-criteria}.")
(address-family
maybe-address-family
"Address family to use when connecting to this host: one of
@code{AF_INET} (for IPv4 only), @code{AF_INET6} (for IPv6 only).
Additionally, the field can be left unset to allow any address family.")
(identity-file
maybe-string
"The identity file to use---e.g.,
@code{\"/home/charlie/.ssh/id_ed25519\"}.")
(port
maybe-natural-number
"TCP port number to connect to.")
(user
maybe-string
"User name on the remote host.")
(forward-x11?
maybe-boolean
"Whether to forward remote client connections to the local X11 graphical
display.")
(forward-x11-trusted?
maybe-boolean
"Whether remote X11 clients have full access to the original X11 graphical
display.")
(forward-agent?
maybe-boolean
"Whether the authentication agent (if any) is forwarded to the remote
machine.")
(compression?
maybe-boolean
"Whether to compress data in transit.")
(proxy-command
maybe-string
"The command to use to connect to the server. As an example, a command
to connect via an HTTP proxy at 192.0.2.0 would be: @code{\"nc -X
connect -x 192.0.2.0:8080 %h %p\"}. Using 'proxy-command' is deprecated, use
'proxy' instead."
(sanitizer (sanitize-proxy-command (current-source-location))))
(proxy
maybe-proxy-command-or-jump-list
"The command to use to connect to the server or a list of SSH hosts to jump
through before connecting to the server.")
(host-key-algorithms
maybe-string-list
"The list of accepted host key algorithms---e.g.,
@code{'(\"ssh-ed25519\")}.")
(accepted-key-types
maybe-string-list
"The list of accepted user public key types.")
(extra-content
(raw-configuration-string "")
"Extra content appended as-is to this @code{Host} block in
@file{~/.ssh/config}."))
(define (serialize-openssh-host config)
(define (openssh-host-name-or-match-field? field)
(or (eq? (configuration-field-name field) 'name)
(eq? (configuration-field-name field) 'match-criteria)))
(string-append
(if (maybe-value-set? (openssh-host-name config))
(if (maybe-value-set? (openssh-host-match-criteria config))
(raise
(formatted-message
(G_ "define either 'name' or 'match-criteria', not both")))
(string-append "Host " (openssh-host-name config) "\n"))
(if (maybe-value-set? (openssh-host-match-criteria config))
(serialize-match-criteria #t (openssh-host-match-criteria config))
(raise
(formatted-message
(G_ "define either 'name' or 'match-criteria' once")))))
(string-concatenate
(map (lambda (field)
((configuration-field-serializer field)
(configuration-field-name field)
((configuration-field-getter field) config)))
(remove openssh-host-name-or-match-field?
openssh-host-fields)))))
(define-record-type* <home-openssh-configuration>
home-openssh-configuration make-home-openssh-configuration
home-openssh-configuration?
(authorized-keys home-openssh-configuration-authorized-keys ;list of file-like
(default #f))
(known-hosts home-openssh-configuration-known-hosts ;unspec | list of file-like
(default *unspecified*))
(hosts home-openssh-configuration-hosts ;list of <openssh-host>
(default '()))
(add-keys-to-agent home-openssh-configuration-add-keys-to-agent ;string with limited values
(default "no")))
(define (serialize-add-keys-to-agent value)
(define (valid-time-string? str)
(and (> (string-length str) 0)
(equal?
str
(match:substring
(string-match "\
[0-9]+|([0-9]+[Ww])?([0-9]+[Dd])?([0-9]+[Hh])?([0-9]+[Mm])?([0-9]+[Ss])?"
str)))))
(string-append "AddKeysToAgent "
(cond ((member value '("yes" "no" "confirm" "ask")) value)
((valid-time-string? value) value)
((and (string-prefix? "confirm" value)
(valid-time-string?
(cdr (string-split value #\ )))) value)
;; The 'else' branch is unreachable.
(else
(raise
(formatted-message
(G_ "~s: invalid 'add-keys-to-agent' value")
value))))))
(define (openssh-configuration->string config)
(string-join
(cons* (serialize-add-keys-to-agent
(home-openssh-configuration-add-keys-to-agent config))
(map serialize-openssh-host
(home-openssh-configuration-hosts config)))
"\n"))
(define* (file-join name files #:optional (delimiter " "))
"Return a file in the store called @var{name} that is the concatenation
of all the file-like objects listed in @var{files}, with @var{delimited}
inserted after each of them."
(computed-file name
(with-imported-modules '((guix build utils))
#~(begin
(use-modules (guix build utils))
;; Support non-ASCII file names.
(setenv "GUIX_LOCPATH"
#+(file-append glibc-utf8-locales
"/lib/locale"))
(setlocale LC_ALL "en_US.utf8")
(call-with-output-file #$output
(lambda (output)
(for-each (lambda (file)
(call-with-input-file file
(lambda (input)
(dump-port input output)))
(display #$delimiter output))
'#$files)))))))
(define (openssh-configuration-files config)
(let* ((ssh-config (plain-file "ssh.conf"
(openssh-configuration->string config)))
(known-hosts (home-openssh-configuration-known-hosts config))
(authorized-keys (home-openssh-configuration-authorized-keys config))
(authorized-keys (and
authorized-keys
(file-join "authorized_keys" authorized-keys "\n"))))
`(,@(if authorized-keys
`((".ssh/authorized_keys" ,authorized-keys))
'())
,@(if (unspecified? known-hosts)
'()
`((".ssh/known_hosts"
,(file-join "known_hosts" known-hosts "\n"))))
(".ssh/config" ,ssh-config))))
(define openssh-activation
(with-imported-modules (source-module-closure
'((gnu build activation)))
#~(begin
(use-modules (gnu build activation))
;; Make sure ~/.ssh is #o700.
(let* ((home (getenv "HOME"))
(dot-ssh (string-append home "/.ssh")))
(mkdir-p/perms dot-ssh (getpw (getuid)) #o700)))))
(define home-openssh-service-type
(service-type
(name 'home-openssh)
(extensions
(list (service-extension home-files-service-type
openssh-configuration-files)
(service-extension home-activation-service-type
(const openssh-activation))))
(description "Configure the OpenSSH @acronym{SSH, secure shell} client
by providing a @file{~/.ssh/config} file, which is honored by the OpenSSH
client,@command{ssh}, and by other tools such as @command{guix deploy}.")
(default-value (home-openssh-configuration))))
;;;
;;; Ssh-agent.
;;;
(define-record-type* <home-ssh-agent-configuration>
home-ssh-agent-configuration make-home-ssh-agent-configuration
home-ssh-agent-configuration?
(openssh home-ssh-agent-openssh ;file-like
(default openssh))
(socket-directory home-ssh-agent-socket-directory ;string
(default #~(string-append %user-runtime-dir "/ssh-agent")))
(extra-options home-ssh-agent-extra-options ;list of string
(default '())))
(define (home-ssh-agent-services config)
"Return a <shepherd-service> for an ssh-agent with CONFIG."
(match-record config <home-ssh-agent-configuration>
(openssh socket-directory extra-options)
(let* ((ssh-agent (file-append openssh "/bin/ssh-agent"))
(socket-file #~(string-append #$socket-directory "/socket"))
(command #~`(#$ssh-agent
"-D" "-a" ,#$socket-file
#$@extra-options))
(log-file #~(string-append %user-log-dir "/ssh-agent.log")))
(list (shepherd-service
(documentation "Run the ssh-agent.")
(provision '(ssh-agent))
(modules '((shepherd support))) ;for '%user-runtime-dir', etc.
(start #~(lambda _
(unless (file-exists? #$socket-directory)
(mkdir-p #$socket-directory)
(chmod #$socket-directory #o700))
(fork+exec-command #$command #:log-file #$log-file)))
(stop #~(make-kill-destructor)))))))
(define (home-ssh-agent-environment-variables config)
'(("SSH_AUTH_SOCK"
. "${SSH_AUTH_SOCK-${XDG_RUNTIME_DIR-$HOME/.cache}/ssh-agent/socket}")))
(define home-ssh-agent-service-type
(service-type
(name 'home-ssh-agent)
(default-value (home-ssh-agent-configuration))
(extensions
(list (service-extension home-shepherd-service-type
home-ssh-agent-services)
(service-extension home-environment-variables-service-type
home-ssh-agent-environment-variables)))
(description
"Install and configure @command{ssh-agent} as a Shepherd service.")))
+10 -26
View File
@@ -54,10 +54,6 @@
(or (getenv "XDG_CONFIG_HOME")
(string-append (getenv "HOME") "/.config")))
(define xdg-data-home
(or (getenv "XDG_DATA_HOME")
(string-append (getenv "HOME") "/.local/share")))
(define backup-directory
(string-append home-directory "/" (number->string (current-time))
"-guix-home-legacy-configs-backup"))
@@ -65,30 +61,19 @@
(define (preprocess-file file)
"If file is in XDG-CONFIGURATION-FILES-DIRECTORY use
subdirectory from XDG_CONFIG_HOME to generate a target path."
(cond
((string-prefix? #$xdg-configuration-files-directory file)
(string-append
(substring xdg-config-home
(1+ (string-length home-directory)))
(substring file
(string-length #$xdg-configuration-files-directory))))
((string-prefix? #$xdg-data-files-directory file)
(string-append
(substring xdg-data-home
(1+ (string-length home-directory)))
(substring file
(string-length #$xdg-data-files-directory))))
(else file)))
(if (string-prefix? #$xdg-configuration-files-directory file)
(string-append
(substring xdg-config-home
(1+ (string-length home-directory)))
(substring file
(string-length #$xdg-configuration-files-directory)))
(string-append "." file)))
(define (target-file file)
;; Return the target of FILE, a config file name sans leading dot
;; such as "config/fontconfig/fonts.conf" or "bashrc".
(string-append home-directory "/" (preprocess-file file)))
(define (no-follow-file-exists? file)
"Return #t if file exists, even if it's a dangling symlink."
(->bool (false-if-exception (lstat file))))
(define (symlink-to-store? file)
(catch 'system-error
(lambda ()
@@ -127,7 +112,7 @@ subdirectory from XDG_CONFIG_HOME to generate a target path."
(const #t)
(lambda (file stat _) ;leaf
(let ((file (target-file (strip file))))
(when (no-follow-file-exists? file)
(when (file-exists? file)
;; DO NOT remove the file if it is no longer a symlink to
;; the store, it will be backed up later during
;; create-symlinks phase.
@@ -157,7 +142,6 @@ subdirectory from XDG_CONFIG_HOME to generate a target path."
#t
(G_ "Skipping ~a (not an empty directory)... done\n")
directory))
((= ENOENT errno) #t)
((= ENOTDIR errno) #t)
(else
(apply throw args)))))))))
@@ -187,7 +171,7 @@ subdirectory from XDG_CONFIG_HOME to generate a target path."
(lambda (file stat result) ;leaf
(let ((source (source-file (strip file)))
(target (target-file (strip file))))
(when (no-follow-file-exists? target)
(when (file-exists? target)
(backup-file (strip file)))
(format #t (G_ "Symlinking ~a -> ~a...")
target source)
@@ -196,7 +180,7 @@ subdirectory from XDG_CONFIG_HOME to generate a target path."
(lambda (directory stat result) ;down
(unless (string=? directory config-file-directory)
(let ((target (target-file (strip directory))))
(when (and (no-follow-file-exists? target)
(when (and (file-exists? target)
(not (file-is-directory? target)))
(backup-file (strip directory)))
-32
View File
@@ -1,32 +0,0 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2023 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (gnu home services syncthing)
#:use-module (gnu services)
#:use-module (gnu home services)
#:use-module (gnu services syncthing)
;; For the 'home-shepherd-service-type' mapping.
#:use-module (gnu home services shepherd)
#:export (home-syncthing-service-type)
#:re-export (syncthing-configuration
syncthing-configuration?))
(define home-syncthing-service-type
(service-type
(inherit (system->home-service-type syncthing-service-type))
(default-value (for-home (syncthing-configuration)))))
+48 -93
View File
@@ -1,7 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2021, 2022 Andrew Tropin <andrew@trop.in>
;;; Copyright © 2021 Andrew Tropin <andrew@trop.in>
;;; Copyright © 2021 Xinglu Chen <public@yoctocell.xyz>
;;; Copyright © 2023 Bruno Victal <mirai@makinata.eu>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -23,9 +22,7 @@
#:use-module (gnu home services)
#:use-module (gnu packages freedesktop)
#:use-module (gnu home services utils)
#:use-module (guix deprecation)
#:use-module (guix gexp)
#:use-module (guix modules)
#:use-module (guix records)
#:use-module (guix i18n)
#:use-module (guix diagnostics)
@@ -37,24 +34,10 @@
#:export (home-xdg-base-directories-service-type
home-xdg-base-directories-configuration
home-xdg-base-directories-configuration?
home-xdg-base-directories-configuration-cache-home
home-xdg-base-directories-configuration-config-home
home-xdg-base-directories-configuration-data-home
home-xdg-base-directories-configuration-state-home
home-xdg-base-directories-configuration-log-home ; deprecated
home-xdg-base-directories-configuration-runtime-dir
home-xdg-user-directories-service-type
home-xdg-user-directories-configuration
home-xdg-user-directories-configuration?
home-xdg-user-directories-configuration-desktop
home-xdg-user-directories-configuration-documents
home-xdg-user-directories-configuration-download
home-xdg-user-directories-configuration-music
home-xdg-user-directories-configuration-pictures
home-xdg-user-directories-configuration-publicshare
home-xdg-user-directories-configuration-templates
home-xdg-user-directories-configuration-videos
xdg-desktop-action
xdg-desktop-entry
@@ -79,7 +62,6 @@
(define (serialize-path field-name val) "")
(define path? string?)
(define-maybe path)
(define-configuration home-xdg-base-directories-configuration
(cache-home
@@ -100,23 +82,18 @@ read-only shared data, analogus to @file{/usr/share}, but for user.")
(path "${XDG_RUNTIME_DIR:-/run/user/$UID}")
"Base directory for programs to store user-specific runtime files,
like sockets.")
;; TODO: deprecated field, use $XDG_STATE_HOME(/log) instead.
(log-home
maybe-path
(path "$HOME/.local/var/log")
"Base directory for programs to store log files, analogus to
@file{/var/log}, but for user. It is not a part of XDG Base Directory
Specification, but helps to make implementation of home services more
consistent."
(lambda (field-name val)
(when (maybe-value-set? val)
(warn-about-deprecation field-name #f #:replacement 'state-home))
(serialize-path field-name val)))
consistent.")
(state-home
(path "$HOME/.local/state")
"Base directory for programs to store state data that should persist
between (application) restarts, such as logs, but are not important or
portable enough to the user to warrant storing them in
@env{XDG_DATA_HOME}."))
(path "$HOME/.local/var/lib")
"Base directory for programs to store state files, like databases,
analogus to @file{/var/lib}, but for user. It is not a part of XDG
Base Directory Specification, but helps to make implementation of home
services more consistent."))
(define (home-xdg-base-directories-environment-variables-service config)
(map
@@ -125,41 +102,19 @@ portable enough to the user to warrant storing them in
#f "XDG_~a"
(object->snake-case-string (configuration-field-name field) 'upper))
((configuration-field-getter field) config)))
;; XXX: deprecated field, remove later
(if (maybe-value-set?
(home-xdg-base-directories-configuration-log-home config))
home-xdg-base-directories-configuration-fields
(filter-configuration-fields
home-xdg-base-directories-configuration-fields
'(log-home) #t))))
home-xdg-base-directories-configuration-fields))
(define (ensure-xdg-base-dirs-on-activation config)
(with-imported-modules '((guix build utils))
#~(begin
(use-modules (guix build utils))
(map (lambda (xdg-base-dir-variable)
(mkdir-p
(getenv
xdg-base-dir-variable)))
'#$(filter-map
(lambda (field)
(let ((variable
(string-append
"XDG_"
(object->snake-case-string
(configuration-field-name field) 'upper))))
;; XDG_RUNTIME_DIR shouldn't be created during activation
;; and will be provided by elogind or other service.
(and (not (string=? "XDG_RUNTIME_DIR" variable))
variable)))
;; XXX: deprecated field, remove later
(if (maybe-value-set?
(home-xdg-base-directories-configuration-log-home
config))
home-xdg-base-directories-configuration-fields
(filter-configuration-fields
home-xdg-base-directories-configuration-fields
'(log-home) #t)))))))
#~(map (lambda (xdg-base-dir-variable)
((@@ (guix build utils) mkdir-p)
(getenv
xdg-base-dir-variable)))
'#$(map (lambda (field)
(format
#f "XDG_~a"
(object->snake-case-string
(configuration-field-name field) 'upper)))
home-xdg-base-directories-configuration-fields)))
(define (last-extension-or-cfg config extensions)
"Picks configuration value from last provided extension. If there
@@ -178,10 +133,13 @@ are no extensions use configuration instead."
(default-value (home-xdg-base-directories-configuration))
(compose identity)
(extend last-extension-or-cfg)
(description "Configure XDG base directories. The
services of this service-type is instantiated by default, to provide
non-default value, extend the service-type (using @code{simple-service}
for example).")))
(description "Configure XDG base directories. This
service introduces two additional variables @env{XDG_STATE_HOME},
@env{XDG_LOG_HOME}. They are not a part of XDG specification, at
least yet, but are convenient to have, it improves the consistency
between different home services. The services of this service-type is
instantiated by default, to provide non-default value, extend the
service-type (using @code{simple-service} for example).")))
(define (generate-home-xdg-base-directories-documentation)
(generate-documentation
@@ -249,8 +207,8 @@ pre-populated content.")
home-xdg-user-directories-configuration-fields)))
#~(let ((ensure-dir
(lambda (path)
((@ (guix build utils) mkdir-p)
((@ (ice-9 string-fun) string-replace-substring)
(mkdir-p
((@@ (ice-9 string-fun) string-replace-substring)
path "$HOME" (getenv "HOME"))))))
(display "Creating XDG user directories...")
(map ensure-dir '#$dirs)
@@ -266,8 +224,6 @@ pre-populated content.")
home-activation-service-type
home-xdg-user-directories-activation-service)))
(default-value (home-xdg-user-directories-configuration))
(compose identity)
(extend last-extension-or-cfg)
(description "Configure XDG user directories. To
disable a directory, point it to the $HOME.")))
@@ -420,25 +376,25 @@ configuration."
(define (serialize-alist config)
(generic-serialize-alist append format-config config))
(define (serialize-xdg-desktop-action desktop-action)
(match-record desktop-action <xdg-desktop-action>
(action name config)
`(,(format #f "[Desktop Action ~a]\n"
(string-capitalize (maybe-object->string action)))
,(format #f "Name=~a\n" name)
,@(serialize-alist config))))
(define (serialize-xdg-desktop-action action)
(match action
(($ <xdg-desktop-action> action name config)
`(,(format #f "[Desktop Action ~a]\n"
(string-capitalize (maybe-object->string action)))
,(format #f "Name=~a\n" name)
,@(serialize-alist config)))))
(match-record entry <xdg-desktop-entry>
(file name type config actions)
(list (if (string-suffix? file ".desktop")
file
(string-append file ".desktop"))
`("[Desktop Entry]\n"
,(format #f "Name=~a\n" name)
,(format #f "Type=~a\n"
(string-capitalize (symbol->string type)))
,@(serialize-alist config)
,@(append-map serialize-xdg-desktop-action actions)))))
(match entry
(($ <xdg-desktop-entry> file name type config actions)
(list (if (string-suffix? file ".desktop")
file
(string-append file ".desktop"))
`("[Desktop Entry]\n"
,(format #f "Name=~a\n" name)
,(format #f "Type=~a\n"
(string-capitalize (symbol->string type)))
,@(serialize-alist config)
,@(append-map serialize-xdg-desktop-action actions))))))
(define-configuration home-xdg-mime-applications-configuration
(added
@@ -465,8 +421,7 @@ that the application cannot open the specified MIME type.")
(define (add-xdg-desktop-entry-file entry)
(let ((file (first entry))
(config (second entry)))
;; TODO: Use xdg-data-files instead of home-files here
(list (format #f "applications/~a" file)
(list (format #f "local/share/applications/~a" file)
(apply mixed-text-file
(format #f "xdg-desktop-~a-entry" file)
config))))
@@ -513,7 +468,7 @@ that the application cannot open the specified MIME type.")
(service-type (name 'home-xdg-mime-applications)
(extensions
(list (service-extension
home-xdg-data-files-service-type
home-files-service-type
home-xdg-mime-applications-files)
(service-extension
home-xdg-configuration-files-service-type
+23 -127
View File
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2020, 2022 Mathieu Othacehe <othacehe@gnu.org>
;;; Copyright © 2020 Mathieu Othacehe <m.othacehe@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -17,13 +17,8 @@
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (gnu image)
#:use-module (guix platform)
#:use-module (gnu platform)
#:use-module (guix records)
#:use-module (guix diagnostics)
#:use-module (guix i18n)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-34)
#:use-module (srfi srfi-35)
#:export (partition
partition?
partition-device
@@ -59,155 +54,61 @@
os->image
os+platform->image))
;;;
;;; Sanitizers.
;;;
;; Image and partition sizes can be either be a size in bytes or the 'guess
;; symbol denoting that the size should be estimated by Guix, according to the
;; image content.
(define-with-syntax-properties (validate-size (value properties))
(unless (and value
(or (eq? value 'guess) (integer? value)))
(raise
(make-compound-condition
(condition
(&error-location
(location (source-properties->location properties))))
(formatted-message
(G_ "size (~a) can only be 'guess or a numeric expression ~%")
value 'field))))
value)
;;;
;;; Partition record.
;;;
;; The partition offset should be a bytes count as an integer.
(define-with-syntax-properties (validate-partition-offset (value properties))
(unless (and value (integer? value))
(raise
(make-compound-condition
(condition
(&error-location
(location (source-properties->location properties))))
(formatted-message
(G_ "the partition offset (~a) can only be a \
numeric expression ~%") value 'field))))
value)
;; The supported partition flags.
(define-with-syntax-properties (validate-partition-flags (value properties))
(let ((bad-flags (lset-difference eq? value '(boot esp))))
(unless (and (list? value) (null? bad-flags))
(raise
(make-compound-condition
(condition
(&error-location
(location (source-properties->location properties))))
(formatted-message
(G_ "unsupported partition flag(s): ~a ~%") bad-flags)))))
value)
(define-record-type* <partition> partition make-partition
partition?
(size partition-size ;size in bytes as integer or 'guess
(default 'guess)
(sanitize validate-size))
(offset partition-offset
(default 0) ;offset in bytes as integer
(sanitize validate-partition-offset))
(file-system partition-file-system
(default "ext4")) ;string
(device partition-device (default #f))
(size partition-size)
(offset partition-offset (default 0))
(file-system partition-file-system (default "ext4"))
(file-system-options partition-file-system-options
(default '())) ;list of strings
(label partition-label) ;string
(uuid partition-uuid
(default #false)) ;<uuid>
(flags partition-flags
(default '()) ;list of symbols
(sanitize validate-partition-flags))
(initializer partition-initializer
(default #false))) ;gexp | #false
(default '()))
(label partition-label (default #f))
(uuid partition-uuid (default #f))
(flags partition-flags (default '()))
(initializer partition-initializer (default #f)))
;;;
;;; Image record.
;;;
(define-syntax-rule (define-set-sanitizer name field set)
"Define NAME as a procedure or macro that raises an error if passed a value
that is not in SET, mentioning FIELD in the error message."
(define-with-syntax-properties (name (value properties))
(unless (memq value 'set)
(raise
(make-compound-condition
(condition
(&error-location
(location (source-properties->location properties))))
(formatted-message (G_ "~s: invalid '~a' value") value 'field))))
value))
;; The supported image formats.
(define-set-sanitizer validate-image-format format
(disk-image compressed-qcow2 docker iso9660 tarball wsl2))
;; The supported partition table types.
(define-set-sanitizer validate-partition-table-type partition-table-type
(mbr gpt))
(define-record-type* <image>
image make-image
image?
(name image-name ;symbol
(default #false))
(format image-format ;symbol
(sanitize validate-image-format))
(default #f))
(format image-format) ;symbol
(platform image-platform ;<platform>
(default #false))
(default #f))
(size image-size ;size in bytes as integer
(default 'guess)
(sanitize validate-size))
(operating-system image-operating-system) ;<operating-system>
(default 'guess))
(operating-system image-operating-system ;<operating-system>
(default #f))
(partition-table-type image-partition-table-type ; 'mbr or 'gpt
(default 'mbr)
(sanitize validate-partition-table-type))
(default 'mbr))
(partitions image-partitions ;list of <partition>
(default '()))
(compression? image-compression? ;boolean
(default #true))
(default #t))
(volatile-root? image-volatile-root? ;boolean
(default #true))
(default #t))
(shared-store? image-shared-store? ;boolean
(default #false))
(default #f))
(shared-network? image-shared-network? ;boolean
(default #false))
(default #f))
(substitutable? image-substitutable? ;boolean
(default #true)))
(default #t)))
;;;
;;; Image type.
;;;
;; The role of this record is to provide a constructor that is able to turn an
;; <operating-system> record into an <image> record. Some basic <image-type>
;; records are defined in the (gnu system image) module. They are able to
;; turn an <operating-system> record into an EFI or an ISO 9660 bootable
;; image, a Docker image or even a QCOW2 image.
;;
;; Other <image-type> records are defined in the (gnu system images ...)
;; modules. They are dedicated to specific machines such as Novena and Pine64
;; SoC boards that require specific images.
;;
;; All the available <image-type> records are collected by the 'image-modules'
;; procedure. This allows the "guix system image" command to turn a given
;; <operating-system> record into an image, thanks to the specified
;; <image-type>. In that case, the <image-type> look up is done using the
;; name field of the <image-type> record.
(define-record-type* <image-type>
image-type make-image-type
image-type?
@@ -220,15 +121,10 @@ that is not in SET, mentioning FIELD in the error message."
;;;
(define* (os->image os #:key type)
"Use the image constructor from TYPE, an <image-type> record to turn the
given OS, an <operating-system> record into an image and return it."
(let ((constructor (image-type-constructor type)))
(constructor os)))
(define* (os+platform->image os platform #:key type)
"Use the image constructor from TYPE, an <image-type> record to turn the
given OS, an <operating-system> record into an image targeting PLATFORM, a
<platform> record and return it."
(image
(inherit (os->image os #:type type))
(platform platform)))

Some files were not shown because too many files have changed in this diff Show More