mirror of
https://git.savannah.gnu.org/git/guix.git
synced 2026-07-09 02:34:06 +02:00
Compare commits
171 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 721c51ceb3 | |||
| 3c8170f65f | |||
| f927cc48e1 | |||
| 9d40ec0fcd | |||
| 83842db321 | |||
| cc625c9b1e | |||
| 7d21e9a8c4 | |||
| a524b98c67 | |||
| 062185b678 | |||
| 5e05e0f56f | |||
| 3b84bafcf7 | |||
| ebef32e07b | |||
| a49dd5b0ba | |||
| ab5334e4c6 | |||
| 8963701e2f | |||
| 6c65906c9a | |||
| ba4fb0c975 | |||
| 2c6136b6e3 | |||
| 579e3712b0 | |||
| ed906c84c7 | |||
| 4984e737b7 | |||
| 257ca91787 | |||
| f9293be58e | |||
| a7e7f29090 | |||
| 83ddbe0477 | |||
| 6ff0f60dab | |||
| 7a6a8ee7e0 | |||
| b8f4ed8f5d | |||
| 46fbea36ea | |||
| 2d8e56ac16 | |||
| 43d18521e8 | |||
| 3f2b0e12f1 | |||
| 189b1c4f27 | |||
| 6b6fb78724 | |||
| edb9a5b835 | |||
| 08bb73749e | |||
| e7f1e1a78d | |||
| a59afdc92e | |||
| c6b5161e97 | |||
| 01647fc80c | |||
| b77ec228af | |||
| a973d72355 | |||
| 387a9772c2 | |||
| dbc5b51cb9 | |||
| 2f7ab8e373 | |||
| 8e3d4f05df | |||
| d8a7e37b86 | |||
| a9429c8f22 | |||
| f0136b36ae | |||
| 1594aaecd5 | |||
| 95630d2d74 | |||
| e42753fd86 | |||
| 97a5819643 | |||
| 6bf2fa8d1c | |||
| ee2f074d0b | |||
| ca6993af91 | |||
| 892aac72a2 | |||
| 0db2a6e749 | |||
| 5268bd97b1 | |||
| 4c19c3eb06 | |||
| 806824c2c0 | |||
| 2d206cd3dc | |||
| 9223b81071 | |||
| 296398e672 | |||
| 7e2e7a34d1 | |||
| 3a29ec6d32 | |||
| fa5a062572 | |||
| 359636a408 | |||
| 4810804e72 | |||
| 4f407029bf | |||
| cddaf93e22 | |||
| 280097b71f | |||
| 36685334a0 | |||
| 38ec52136f | |||
| c63566c5cf | |||
| 09deb8a570 | |||
| b47d8363f9 | |||
| df8a042de8 | |||
| b3fb3c10b8 | |||
| 774042fede | |||
| 98bd43095c | |||
| 47f87b2e48 | |||
| 11302036f7 | |||
| b2907f5b25 | |||
| 4270d3cf98 | |||
| ec9d9bddc7 | |||
| e6db86b337 | |||
| 5418275398 | |||
| ca9527845f | |||
| 5e9018b389 | |||
| c2777bb64f | |||
| 91aa20e237 | |||
| 006538c527 | |||
| e7cf0ea660 | |||
| d293162615 | |||
| 970b7a949d | |||
| f833399811 | |||
| 94268d5021 | |||
| 83c3332758 | |||
| 5e796bfc22 | |||
| 69f284a35f | |||
| f172118ca4 | |||
| b31ef5638b | |||
| 521e0d32e3 | |||
| 10ee2542e8 | |||
| 0989c839dd | |||
| 65df5a4eb2 | |||
| d5f8bfcd14 | |||
| 6c4c0f16a6 | |||
| 5f628d773b | |||
| 6ac6a7e020 | |||
| 0d41fe4855 | |||
| 7c57821c68 | |||
| bca1157e47 | |||
| 9bf69d38aa | |||
| 3dc776cb71 | |||
| 8313f741a8 | |||
| bbb08831e0 | |||
| 1236a563b9 | |||
| e25ff31663 | |||
| 80194d9e47 | |||
| bc5654af82 | |||
| fab871ae7a | |||
| 94f8ba37cc | |||
| 6ccf8ea81f | |||
| 9f916d1476 | |||
| de86aaa097 | |||
| fcaed5b81e | |||
| 77b98bf187 | |||
| a7bc1c8dd3 | |||
| d3d6e8b31a | |||
| ea5039c765 | |||
| 296599dac5 | |||
| 4acddaa659 | |||
| 97cd9b73a6 | |||
| 65e5f1475d | |||
| a4c40efa05 | |||
| 40e07889d1 | |||
| 9c96dfd43c | |||
| c2f5510730 | |||
| c3417f0754 | |||
| 2d9c06c61d | |||
| d8ff47a75e | |||
| 2f817ab6ab | |||
| 90fb289b69 | |||
| 744bfc61da | |||
| 1f7cf5834c | |||
| cf7c7e2596 | |||
| 9ccb0cf70a | |||
| bbb5243817 | |||
| 7f3da8f882 | |||
| e8176d3152 | |||
| f73758f6c2 | |||
| 7b71cd6dab | |||
| 9bf44750dc | |||
| 0fe0a3a8ee | |||
| 283bc45649 | |||
| 9ca2f94b1b | |||
| 034459cc67 | |||
| e3d61d2082 | |||
| 8a55fde935 | |||
| 9bf0652b08 | |||
| 5d8515b337 | |||
| 385ba2f369 | |||
| fae2fcdbc9 | |||
| 0cccc2f52c | |||
| 22f7d4bce1 | |||
| 426038df3b | |||
| 693d75e859 | |||
| 8419221620 | |||
| 041a12c46b |
+3
-43
@@ -6,29 +6,15 @@
|
||||
(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).
|
||||
@@ -132,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))
|
||||
@@ -171,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))))
|
||||
|
||||
@@ -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
|
||||
@@ -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,4 +157,3 @@ tmp
|
||||
/gnu/packages/bootstrap
|
||||
/gnu/packages/aux-files/guile-guile-launcher.o
|
||||
/guile
|
||||
.DS_Store
|
||||
|
||||
@@ -4,15 +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"
|
||||
@@ -35,8 +32,10 @@
|
||||
(;; 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"
|
||||
|
||||
+55
-107
@@ -97,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 \
|
||||
@@ -129,30 +130,21 @@ 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/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 \
|
||||
guix/build-system/meson.scm \
|
||||
guix/build-system/mozilla.scm \
|
||||
guix/build-system/minify.scm \
|
||||
guix/build-system/minetest.scm \
|
||||
guix/build-system/asdf.scm \
|
||||
@@ -166,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 \
|
||||
@@ -174,7 +165,6 @@ 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 \
|
||||
@@ -202,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 \
|
||||
@@ -223,14 +212,12 @@ 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 \
|
||||
@@ -270,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 \
|
||||
@@ -279,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 \
|
||||
@@ -314,24 +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/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 \
|
||||
@@ -399,10 +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.0-arm.conf \
|
||||
gnu/packages/aux-files/linux-libre/6.0-arm64.conf \
|
||||
gnu/packages/aux-files/linux-libre/6.0-i686.conf \
|
||||
gnu/packages/aux-files/linux-libre/6.0-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 \
|
||||
@@ -424,9 +405,10 @@ AUX_FILES = \
|
||||
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/sanity-check-next.py \
|
||||
gnu/packages/aux-files/python/sitecustomize.py \
|
||||
gnu/packages/aux-files/renpy/renpy.in \
|
||||
gnu/packages/aux-files/run-in-namespace.c
|
||||
@@ -477,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 \
|
||||
@@ -493,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 \
|
||||
@@ -507,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 \
|
||||
@@ -529,14 +508,12 @@ SCM_TESTS = \
|
||||
tests/profiles.scm \
|
||||
tests/publish.scm \
|
||||
tests/pypi.scm \
|
||||
tests/read-print.scm \
|
||||
tests/records.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/telephony.scm \
|
||||
tests/sets.scm \
|
||||
@@ -585,7 +562,6 @@ SH_TESTS = \
|
||||
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 \
|
||||
@@ -593,7 +569,6 @@ SH_TESTS = \
|
||||
tests/guix-environment.sh \
|
||||
tests/guix-environment-container.sh \
|
||||
tests/guix-shell.sh \
|
||||
tests/guix-shell-export-manifest.sh \
|
||||
tests/guix-graph.sh \
|
||||
tests/guix-describe.sh \
|
||||
tests/guix-repl.sh \
|
||||
@@ -661,49 +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/cuirass/hurd-manifest.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/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
|
||||
@@ -752,35 +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_half := \
|
||||
gnu/packages/a% gnu/packages/b% gnu/packages/c% gnu/packages/d% \
|
||||
gnu/packages/e% gnu/packages/f% gnu/packages/g% gnu/packages/h% \
|
||||
gnu/packages/i% gnu/packages/j% gnu/packages/k% gnu/packages/l%
|
||||
|
||||
MODULES_CORE := guix.scm $(filter-out guix/scripts/%,$(filter guix/%,$(MODULES)))
|
||||
MODULES_PACKAGES1 := $(filter $(first_half),$(MODULES))
|
||||
MODULES_PACKAGES2 := $(filter-out $(first_half),$(filter gnu/packages/%,$(MODULES)))
|
||||
MODULES_PACKAGES := $(MODULES_PACKAGES1) $(MODULES_PACKAGES2)
|
||||
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
|
||||
|
||||
make-packages-go: make-packages1-go make-packages2-go
|
||||
.PHONY: make-packages-go
|
||||
|
||||
$(eval $(call guile-compilation-rule,make-system-go, \
|
||||
@@ -996,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" ; \
|
||||
@@ -1019,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 \
|
||||
@@ -1107,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,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
|
||||
@@ -17,120 +16,22 @@ Please send Guix bug reports to bug-guix@gnu.org.
|
||||
** 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>)
|
||||
@@ -142,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
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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])
|
||||
|
||||
+48
-251
@@ -1,7 +1,6 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2019-2025 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,10 +30,8 @@
|
||||
(guix gexp)
|
||||
(guix git)
|
||||
(guix git-download)
|
||||
(guix profiles)
|
||||
(guix utils)
|
||||
(git)
|
||||
(gnu packages)
|
||||
(gnu packages base)
|
||||
(gnu packages compression)
|
||||
(gnu packages gawk)
|
||||
@@ -53,116 +50,8 @@
|
||||
(define file-append*
|
||||
(@@ (guix self) file-append*))
|
||||
|
||||
(define (translated-texi-manuals source)
|
||||
"Return the translated texinfo manuals built from SOURCE."
|
||||
(define po4a
|
||||
(specification->package "po4a"))
|
||||
|
||||
(define gettext-minimal
|
||||
(specification->package "gettext-minimal"))
|
||||
|
||||
(define documentation
|
||||
(file-append* source "doc"))
|
||||
|
||||
(define documentation-po
|
||||
(file-append* source "po/doc"))
|
||||
|
||||
(define build
|
||||
(with-imported-modules '((guix build utils) (guix build po))
|
||||
#~(begin
|
||||
(use-modules (guix build utils) (guix build po)
|
||||
(ice-9 match) (ice-9 regex) (ice-9 textual-ports)
|
||||
(ice-9 vlist) (ice-9 threads)
|
||||
(srfi srfi-1))
|
||||
|
||||
(define (translate-tmp-texi po source output)
|
||||
"Translate Texinfo file SOURCE using messages from PO, and write
|
||||
the result to OUTPUT."
|
||||
(invoke #+(file-append po4a "/bin/po4a-translate")
|
||||
"-M" "UTF-8" "-L" "UTF-8" "-k" "0" "-f" "texinfo"
|
||||
"-m" source "-p" po "-l" output))
|
||||
|
||||
(define (canonicalize-whitespace str)
|
||||
;; Change whitespace (newlines, etc.) in STR to #\space.
|
||||
(string-map (lambda (chr)
|
||||
(if (char-set-contains? char-set:whitespace chr)
|
||||
#\space
|
||||
chr))
|
||||
str))
|
||||
|
||||
(define* (translate-texi prefix po lang
|
||||
#:key (extras '()))
|
||||
"Translate the manual for one language LANG using the PO file.
|
||||
PREFIX must be the prefix of the manual, 'guix' or 'guix-cookbook'. EXTRAS is
|
||||
a list of extra files, such as '(\"contributing\")."
|
||||
(for-each (lambda (file)
|
||||
(translate-tmp-texi po (string-append file ".texi")
|
||||
(string-append file "." lang
|
||||
".texi.tmp")))
|
||||
(cons prefix extras))
|
||||
|
||||
(for-each (lambda (file)
|
||||
(let* ((texi (string-append file "." lang ".texi"))
|
||||
(tmp (string-append texi ".tmp")))
|
||||
(copy-file tmp texi)
|
||||
(translate-cross-references texi po)))
|
||||
(cons prefix extras)))
|
||||
|
||||
(define (available-translations directory domain)
|
||||
;; Return the list of available translations under DIRECTORY for
|
||||
;; DOMAIN, a gettext domain such as "guix-manual". The result is
|
||||
;; a list of language/PO file pairs.
|
||||
(filter-map (lambda (po)
|
||||
(let ((base (basename po)))
|
||||
(and (string-prefix? (string-append domain ".")
|
||||
base)
|
||||
(match (string-split base #\.)
|
||||
((_ ... lang "po")
|
||||
(cons lang po))))))
|
||||
(find-files directory
|
||||
"\\.[a-z]{2}(_[A-Z]{2})?\\.po$")))
|
||||
|
||||
(define parallel-jobs
|
||||
;; Limit thread creation by 'n-par-for-each', mostly to put an
|
||||
;; upper bound on memory usage.
|
||||
(min (parallel-job-count) 4))
|
||||
|
||||
(mkdir #$output)
|
||||
(copy-recursively #$documentation "."
|
||||
#:log (%make-void-port "w"))
|
||||
|
||||
(for-each
|
||||
(lambda (file)
|
||||
(copy-file file (basename file)))
|
||||
(find-files #$documentation-po ".*.po$"))
|
||||
|
||||
(setenv "GUIX_LOCPATH"
|
||||
#+(file-append glibc-utf8-locales "/lib/locale"))
|
||||
(setenv "PATH" #+(file-append gettext-minimal "/bin"))
|
||||
(setenv "LC_ALL" "en_US.UTF-8")
|
||||
(setlocale LC_ALL "en_US.UTF-8")
|
||||
|
||||
(n-par-for-each parallel-jobs
|
||||
(match-lambda
|
||||
((language . po)
|
||||
(translate-texi "guix" po language
|
||||
#:extras '("contributing"))))
|
||||
(available-translations "." "guix-manual"))
|
||||
|
||||
(n-par-for-each parallel-jobs
|
||||
(match-lambda
|
||||
((language . po)
|
||||
(translate-texi "guix-cookbook" po language)))
|
||||
(available-translations "." "guix-cookbook"))
|
||||
|
||||
(for-each (lambda (file)
|
||||
(install-file file #$output))
|
||||
(append
|
||||
(find-files "." "contributing\\..*\\.texi$")
|
||||
(find-files "." "guix\\..*\\.texi$")
|
||||
(find-files "." "guix-cookbook\\..*\\.texi$"))))))
|
||||
|
||||
(computed-file "guix-translated-texinfo" build))
|
||||
(define translated-texi-manuals
|
||||
(@@ (guix self) translate-texi-manuals))
|
||||
|
||||
(define info-manual
|
||||
(@@ (guix self) info-manual))
|
||||
@@ -173,23 +62,11 @@ a list of extra files, such as '(\"contributing\")."
|
||||
(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))
|
||||
|
||||
(define %latest-guix-version
|
||||
;; Latest released version.
|
||||
"1.4.0")
|
||||
'("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
|
||||
@@ -297,16 +174,11 @@ as well as images, OS examples, and translations."
|
||||
(define %web-site-url
|
||||
;; URL of the web site home page.
|
||||
(or (getenv "GUIX_WEB_SITE_URL")
|
||||
"/"))
|
||||
|
||||
(define %manual-css-url
|
||||
;; URL of the main CSS file.
|
||||
(in-vicinity %web-site-url
|
||||
"themes/initial/css/manual.css"))
|
||||
"/software/guix/"))
|
||||
|
||||
(define %makeinfo-html-options
|
||||
;; Options passed to 'makeinfo --html'.
|
||||
`(,(string-append "--css-ref=" %manual-css-url)
|
||||
'("--css-ref=https://www.gnu.org/software/gnulib/manual.css"
|
||||
"-c" "EXTRA_HEAD=<meta name=\"viewport\" \
|
||||
content=\"width=device-width, initial-scale=1\" />"))
|
||||
|
||||
@@ -402,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)
|
||||
@@ -432,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
|
||||
@@ -628,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 ...)
|
||||
@@ -740,10 +602,9 @@ its <pre class=\"lisp\"> blocks (as produced by 'makeinfo --html')."
|
||||
|
||||
(define* (stylized-html source input
|
||||
#:key
|
||||
(latest-version %latest-guix-version)
|
||||
(languages %languages)
|
||||
(manual %manual)
|
||||
(manual-css-url %manual-css-url))
|
||||
(manual-css-url "/static/base/css/manual.css"))
|
||||
"Process all the HTML files in INPUT; add them MANUAL-CSS-URL as a <style>
|
||||
link, and add a menu to choose among LANGUAGES. Use the Guix PO files found
|
||||
in SOURCE."
|
||||
@@ -789,14 +650,6 @@ in SOURCE."
|
||||
(href ,url))
|
||||
,label)))
|
||||
|
||||
(define menu-item-separator
|
||||
;; Thin horizontal line to separate drop-down menu items.
|
||||
`(img (@ (class "hline")
|
||||
(src ,(in-vicinity
|
||||
#$%web-site-url
|
||||
"themes/initial/img/h-separator.png"))
|
||||
(alt ""))))
|
||||
|
||||
(define* (navigation-bar menus #:key split-node?)
|
||||
;; Return the navigation bar showing all of MENUS.
|
||||
`(header (@ (class "navbar"))
|
||||
@@ -843,43 +696,7 @@ in SOURCE."
|
||||
"https://translate.fedoraproject.org/projects/guix/documentation-cookbook/"
|
||||
"https://translate.fedoraproject.org/projects/guix/documentation-manual/")))))
|
||||
|
||||
(define (version-menu-items language split-node?)
|
||||
;; Return the menu items to select the version of the manual of
|
||||
;; the type of medium (PDF, split-node, etc.).
|
||||
(define language-extension
|
||||
(if (string=? language "en")
|
||||
""
|
||||
(string-append "." language)))
|
||||
|
||||
(define pdf-link
|
||||
(string-append (if split-node? "../" "")
|
||||
#$manual language-extension ".pdf"))
|
||||
|
||||
(define version-links
|
||||
(list (menu-item #$latest-version
|
||||
(string-append
|
||||
"/manual/" #$latest-version
|
||||
"/" language
|
||||
(if split-node? "/html_node" "")))
|
||||
(menu-item "development"
|
||||
(string-append
|
||||
"/manual/devel/" language
|
||||
(if split-node? "/html_node" "")))
|
||||
menu-item-separator))
|
||||
|
||||
(append (if (string=? #$manual "guix")
|
||||
version-links
|
||||
'())
|
||||
(list (if split-node?
|
||||
(menu-item "single page"
|
||||
(string-append "../" #$manual
|
||||
language-extension
|
||||
".html"))
|
||||
(menu-item "multiple pages"
|
||||
"html_node"))
|
||||
(menu-item "PDF" pdf-link))))
|
||||
|
||||
(define (stylized-html sxml file language)
|
||||
(define (stylized-html sxml file)
|
||||
;; Return SXML, which was read from FILE, with additional
|
||||
;; styling.
|
||||
(define split-node?
|
||||
@@ -902,16 +719,9 @@ in SOURCE."
|
||||
;; TODO: Add "Contribute" menu, to report
|
||||
;; errors, etc.
|
||||
(list (menu-dropdown
|
||||
#:label "Version"
|
||||
#:items
|
||||
(version-menu-items language
|
||||
split-node?))
|
||||
(menu-dropdown
|
||||
#:label
|
||||
`(img (@ (alt "Language")
|
||||
(src #$(in-vicinity
|
||||
%web-site-url
|
||||
"themes/initial/img/language-picker.svg"))))
|
||||
(src "/static/base/img/language-picker.svg")))
|
||||
#:items
|
||||
(language-menu-items file)))
|
||||
#:split-node? split-node?)
|
||||
@@ -923,13 +733,13 @@ in SOURCE."
|
||||
((? string? str)
|
||||
str))))
|
||||
|
||||
(define (process-html file language)
|
||||
(define (process-html file)
|
||||
;; Parse FILE and add links to translations. Install the result
|
||||
;; to #$output.
|
||||
(format (current-error-port) "processing ~a...~%" file)
|
||||
(let* ((shtml (parameterize ((%strict-tokenizer? #t))
|
||||
(call-with-input-file file html->shtml)))
|
||||
(processed (stylized-html shtml file language))
|
||||
(processed (stylized-html shtml file))
|
||||
(base (string-drop file (string-length #$input)))
|
||||
(target (string-append #$output base)))
|
||||
(mkdir-p (dirname target))
|
||||
@@ -937,15 +747,6 @@ in SOURCE."
|
||||
(lambda (port)
|
||||
(write-shtml-as-html processed port)))))
|
||||
|
||||
(define (input-file-language file)
|
||||
;; Return the language code of FILE, an input file, as a string
|
||||
;; like "sv" or "zh-cn".
|
||||
(match (string-tokenize (string-drop file
|
||||
(string-length #$input))
|
||||
(char-set-complement
|
||||
(char-set #\/)))
|
||||
((language _ ...) language)))
|
||||
|
||||
;; Install a UTF-8 locale so we can process UTF-8 files.
|
||||
(setenv "GUIX_LOCPATH"
|
||||
#+(file-append glibc-utf8-locales "/lib/locale"))
|
||||
@@ -956,8 +757,7 @@ in SOURCE."
|
||||
(n-par-for-each (parallel-job-count)
|
||||
(lambda (file)
|
||||
(if (string-suffix? ".html" file)
|
||||
(let ((language (input-file-language file)))
|
||||
(process-html file language))
|
||||
(process-html file)
|
||||
;; Copy FILE as is to #$output.
|
||||
(let* ((base (string-drop file (string-length #$input)))
|
||||
(target (string-append #$output base)))
|
||||
@@ -1024,8 +824,7 @@ makeinfo OPTIONS."
|
||||
(let* ((texi (language->texi-file-name language))
|
||||
(opts `("--html"
|
||||
"-c" ,(string-append "TOP_NODE_UP_URL=/manual/"
|
||||
#$%latest-guix-version
|
||||
"/" language)
|
||||
language)
|
||||
#$@options
|
||||
,texi)))
|
||||
(format #t "building HTML manual for language '~a'...~%"
|
||||
@@ -1082,22 +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-scheme-basic
|
||||
texlive-bin ;for GUIX_TEXMF
|
||||
texlive-epsf
|
||||
texlive-ec
|
||||
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))
|
||||
@@ -1114,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)
|
||||
@@ -1169,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
|
||||
@@ -1243,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"))
|
||||
@@ -1483,7 +1284,6 @@ commit date (an integer)."
|
||||
(setenv "PATH"
|
||||
(string-append #+tar "/bin:"
|
||||
#+xz "/bin:"
|
||||
#+zstd "/bin:"
|
||||
#+texinfo "/bin"))
|
||||
(invoke "tar" "xf" #$(package-source guile))
|
||||
(mkdir-p (string-append #$output "/en/html_node"))
|
||||
@@ -1547,9 +1347,7 @@ by 'html-identifier-indexes'."
|
||||
|
||||
|
||||
(let* ((root (canonicalize-path
|
||||
(string-append (or (current-source-directory)
|
||||
(string-append (getcwd) "/doc"))
|
||||
"/..")))
|
||||
(string-append (current-source-directory) "/..")))
|
||||
(commit date (latest-commit+date root))
|
||||
(version (or (getenv "GUIX_MANUAL_VERSION")
|
||||
(string-take commit 7)))
|
||||
@@ -1596,8 +1394,7 @@ by 'html-identifier-indexes'."
|
||||
(merge-index-alists guix-split-node-indexes guile-split-node-indexes))
|
||||
|
||||
(format (current-error-port)
|
||||
"building manual from work tree (~a) around commit ~a, ~a~%"
|
||||
root
|
||||
"building manual from work tree around commit ~a, ~a~%"
|
||||
commit
|
||||
(let* ((time (make-time time-utc 0 date))
|
||||
(date (time-utc->date time)))
|
||||
|
||||
+55
-397
@@ -29,7 +29,6 @@ choice.
|
||||
* 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
|
||||
|
||||
@@ -225,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
|
||||
@@ -278,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
|
||||
@@ -291,7 +291,7 @@ 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
|
||||
@@ -320,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
|
||||
@@ -457,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
|
||||
|
||||
@@ -674,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
|
||||
@@ -786,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
|
||||
@@ -819,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
|
||||
@@ -833,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.
|
||||
@@ -929,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 {Scheme 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 {Scheme 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 {Scheme 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 {Scheme 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
|
||||
|
||||
@@ -1089,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 Guile’s @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
|
||||
@@ -1153,18 +1036,18 @@ 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 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{ISSUE_NUMBER}@@debbugs.gnu.org}, where @var{ISSUE_NUMBER} is
|
||||
the tracking number (@pxref{Sending a Patch Series}).
|
||||
@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
|
||||
@@ -1174,6 +1057,15 @@ 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
|
||||
@@ -1357,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
|
||||
@@ -1371,7 +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}.
|
||||
@email{@var{NNN}-done@@debbugs.gnu.org}.
|
||||
|
||||
@node Configuring Git
|
||||
@subsection Configuring Git
|
||||
@@ -1409,180 +1300,19 @@ git config --local format.thread shallow
|
||||
git config --local sendemail.thread no
|
||||
@end example
|
||||
|
||||
@node Sending a Patch Series
|
||||
@subsection Sending a Patch Series
|
||||
@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.
|
||||
|
||||
@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
|
||||
|
||||
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:
|
||||
|
||||
@example
|
||||
$ git send-email -1 -a --base=auto --to=guix-patches@@gnu.org
|
||||
@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 -1 -a --base=auto \
|
||||
--subject-prefix='PATCH core-updates' \
|
||||
--to=guix-patches@@gnu.org
|
||||
@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{-a} flag (which is short for @option{--annotate}).
|
||||
|
||||
The @option{--base=auto} flag automatically adds a note at the bottom
|
||||
of the patch of the commit it was based on, making it easier for
|
||||
maintainers to rebase and merge your patch.
|
||||
|
||||
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 -a} 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 -a
|
||||
$ git send-email -1 -a --base=auto -v @var{REVISION} \
|
||||
--to=@var{ISSUE_NUMBER}@@debbugs.gnu.org
|
||||
@end example
|
||||
|
||||
You can find out @var{ISSUE_NUMBER} either by searching on the mumi
|
||||
interface at @url{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
|
||||
The @file{etc/teams.scm} script may be used to notify all those who
|
||||
may be interested in your patch of its existence (@pxref{Teams}).
|
||||
Use @command{etc/teams.scm list-teams} to display all the teams,
|
||||
decide which team(s) your patch relates to, and use
|
||||
@command{etc/teams.scm cc} to output various @command{git send-email}
|
||||
flags which will notify the appropriate team members, or use
|
||||
@command{etc/teams.scm cc-members} to detect the appropriate teams
|
||||
automatically.
|
||||
|
||||
@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 -a \
|
||||
--to=guix-patches@@gnu.org \
|
||||
$(etc/teams.scm cc-members ...)
|
||||
$ 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 \
|
||||
$(etc/teams.scm cc-members ...)
|
||||
$ 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} --base=auto \
|
||||
--to @var{ISSUE_NUMBER}@@debbugs.gnu.org
|
||||
@end example
|
||||
|
||||
If need be, you may use @option{--cover-letter -a} 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 $(./etc/teams.scm cc mentors) *.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 $(./etc/teams.scm cc-members HEAD~2 HEAD) *.patch
|
||||
@end example
|
||||
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
|
||||
|
||||
@node Tracking Bugs and Patches
|
||||
@section Tracking Bugs and Patches
|
||||
@@ -1805,23 +1535,14 @@ git config commit.gpgsign true
|
||||
git config user.signingkey CABBA6EA1DC0FF33
|
||||
@end example
|
||||
|
||||
To check that commits are signed with correct key, use:
|
||||
|
||||
@example
|
||||
make authenticate
|
||||
@end example
|
||||
|
||||
You can prevent yourself from accidentally pushing unsigned or signed
|
||||
with the wrong key commits to Savannah by using the pre-push Git hook
|
||||
located at @file{etc/git/pre-push}:
|
||||
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
|
||||
cp etc/git/pre-push .git/hooks/pre-push
|
||||
@end example
|
||||
|
||||
It additionally calls @code{make check-channel-news} to be sure
|
||||
@file{news.scm} file is correct.
|
||||
|
||||
@subsection Commit Policy
|
||||
|
||||
If you get commit access, please make sure to follow
|
||||
@@ -1976,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
|
||||
@@ -2231,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
|
||||
|
||||
+27
-705
@@ -11,7 +11,7 @@
|
||||
@set SUBSTITUTE-TOR-URL https://4zwzi66wwdaalbhgnix55ea3ab4pvvw66ll2ow53kjub6se4q2bclcyd.onion
|
||||
|
||||
@copying
|
||||
Copyright @copyright{} 2019, 2022 Ricardo Wurmus@*
|
||||
Copyright @copyright{} 2019 Ricardo Wurmus@*
|
||||
Copyright @copyright{} 2019 Efraim Flashner@*
|
||||
Copyright @copyright{} 2019 Pierre Neidhardt@*
|
||||
Copyright @copyright{} 2020 Oleg Pykhalov@*
|
||||
@@ -21,7 +21,6 @@ Copyright @copyright{} 2020 Brice Waegeneire@*
|
||||
Copyright @copyright{} 2020 André Batista@*
|
||||
Copyright @copyright{} 2020 Christine Lemmer-Webber@*
|
||||
Copyright @copyright{} 2021 Joshua Branson@*
|
||||
Copyright @copyright{} 2022 Maxim Cournoyer*
|
||||
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.3 or
|
||||
@@ -72,7 +71,6 @@ Weblate} (@pxref{Translating Guix,,, guix, GNU Guix reference manual}).
|
||||
* Scheme tutorials:: Meet your new favorite language!
|
||||
* Packaging:: Packaging tutorials
|
||||
* System Configuration:: Customizing the GNU System
|
||||
* Containers:: Isolated environments and nested systems
|
||||
* Advanced package management:: Power to the users!
|
||||
* Environment management:: Control environment
|
||||
|
||||
@@ -93,17 +91,8 @@ Packaging
|
||||
|
||||
System Configuration
|
||||
|
||||
* Auto-Login to a Specific TTY:: Automatically Login a User to a Specific TTY
|
||||
* Customizing the Kernel:: Creating and using a custom Linux kernel on Guix System.
|
||||
* Guix System Image API:: Customizing images to target specific platforms.
|
||||
* Using security keys:: How to use security keys with Guix System.
|
||||
* Connecting to Wireguard VPN:: Connecting to a Wireguard VPN.
|
||||
* Customizing a Window Manager:: Handle customization of a Window manager on Guix System.
|
||||
* Running Guix on a Linode Server:: Running Guix on a Linode Server. Running Guix on a Linode Server
|
||||
* Setting up a bind mount:: Setting up a bind mount in the file-systems definition.
|
||||
* Getting substitutes from Tor:: Configuring Guix daemon to get substitutes through Tor.
|
||||
* Setting up NGINX with Lua:: Configuring NGINX web-server to load Lua modules.
|
||||
* Music Server with Bluetooth Audio:: Headless music player with Bluetooth output.
|
||||
* Auto-Login to a Specific TTY:: Automatically Login a User to a Specific TTY
|
||||
* Customizing the Kernel:: Creating and using a custom Linux kernel on Guix System.
|
||||
|
||||
@end detailmenu
|
||||
@end menu
|
||||
@@ -133,7 +122,7 @@ language, install it with @code{guix install guile} and start a
|
||||
@dfn{REPL}---short for @uref{https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop,
|
||||
@dfn{read-eval-print loop}}---by running @code{guile} from the command line.
|
||||
|
||||
Alternatively you can also run @code{guix shell guile -- guile}
|
||||
Alternatively you can also run @code{guix environment --ad-hoc guile -- guile}
|
||||
if you'd rather not have Guile installed in your user profile.
|
||||
|
||||
In the following examples, lines show what you would type at the REPL;
|
||||
@@ -295,41 +284,24 @@ depends on the @code{(guix store)} module and it exports two variables,
|
||||
@code{ruby-build} and @code{ruby-build-system}.
|
||||
@end itemize
|
||||
|
||||
@quotation Going further
|
||||
Scheme is a language that has been widely used to teach programming and
|
||||
you'll find plenty of material using it as a vehicle. Here's a
|
||||
selection of documents to learn more about Scheme:
|
||||
For a more detailed introduction, check out
|
||||
@uref{http://www.troubleshooters.com/codecorn/scheme_guile/hello.htm, Scheme
|
||||
at a Glance}, by Steve Litt.
|
||||
|
||||
@itemize
|
||||
@item
|
||||
@uref{https://spritely.institute/static/papers/scheme-primer.html, @i{A
|
||||
Scheme Primer}}, by Christine Lemmer-Webber and the Spritely Institute.
|
||||
|
||||
@item
|
||||
@uref{http://www.troubleshooters.com/codecorn/scheme_guile/hello.htm,
|
||||
@i{Scheme at a Glance}}, by Steve Litt.
|
||||
|
||||
@item
|
||||
@uref{https://mitpress.mit.edu/sites/default/files/sicp/index.html,
|
||||
@i{Structure and Interpretation of Computer Programs}}, by Harold
|
||||
Abelson and Gerald Jay Sussman, with Julie Sussman. Colloquially known
|
||||
as ``SICP'', this book is a reference.
|
||||
|
||||
You can also install it and read it from your computer:
|
||||
|
||||
@example
|
||||
guix install sicp info-reader
|
||||
info sicp
|
||||
@end example
|
||||
|
||||
An @uref{https://sarabander.github.io/sicp/, unofficial ebook} is also
|
||||
available.
|
||||
|
||||
@end itemize
|
||||
One of the reference Scheme books is the seminal ``Structure and
|
||||
Interpretation of Computer Programs'', by Harold Abelson and Gerald Jay
|
||||
Sussman, with Julie Sussman. You'll find a
|
||||
@uref{https://mitpress.mit.edu/sites/default/files/sicp/index.html, free copy
|
||||
online}, together with
|
||||
@uref{https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-001-structure-and-interpretation-of-computer-programs-spring-2005/video-lectures/,
|
||||
videos of the lectures by the authors}. The book is available in Texinfo
|
||||
format as the @code{sicp} Guix package. Go ahead, run @code{guix install
|
||||
sicp} and start reading with @code{info sicp} (@pxref{,,, sicp, Structure and Interpretation of Computer Programs}).
|
||||
An @uref{https://sarabander.github.io/sicp/, unofficial ebook is also
|
||||
available}.
|
||||
|
||||
You'll find more books, tutorials and other resources at
|
||||
@url{https://schemers.org/}.
|
||||
@end quotation
|
||||
|
||||
|
||||
@c *********************************************************************
|
||||
@@ -931,7 +903,7 @@ Installed in the store and in the profile, as well as
|
||||
being present at build time.
|
||||
@end table
|
||||
|
||||
@xref{package Reference,,, guix, GNU Guix Reference Manual} for more details.
|
||||
@xref{Package Reference,,, guix, GNU Guix Reference Manual} for more details.
|
||||
|
||||
The distinction between the various inputs is important: if a dependency can be
|
||||
handled as an @emph{input} instead of a @emph{propagated input}, it should be done so, or
|
||||
@@ -1382,14 +1354,12 @@ reference.
|
||||
* Auto-Login to a Specific TTY:: Automatically Login a User to a Specific TTY
|
||||
* Customizing the Kernel:: Creating and using a custom Linux kernel on Guix System.
|
||||
* Guix System Image API:: Customizing images to target specific platforms.
|
||||
* Using security keys:: How to use security keys with Guix System.
|
||||
* Connecting to Wireguard VPN:: Connecting to a Wireguard VPN.
|
||||
* Customizing a Window Manager:: Handle customization of a Window manager on Guix System.
|
||||
* Running Guix on a Linode Server:: Running Guix on a Linode Server
|
||||
* Setting up a bind mount:: Setting up a bind mount in the file-systems definition.
|
||||
* Getting substitutes from Tor:: Configuring Guix daemon to get substitutes through Tor.
|
||||
* Setting up NGINX with Lua:: Configuring NGINX web-server to load Lua modules.
|
||||
* Music Server with Bluetooth Audio:: Headless music player with Bluetooth output.
|
||||
@end menu
|
||||
|
||||
@node Auto-Login to a Specific TTY
|
||||
@@ -1630,7 +1600,7 @@ letting you know what you're missing. If the file is blank then you're
|
||||
missing everything. The next step is to run:
|
||||
|
||||
@example shell
|
||||
guix shell -D linux-libre -- make localmodconfig
|
||||
guix environment linux-libre -- make localmodconfig
|
||||
@end example
|
||||
|
||||
and note the output. Do note that the @file{.config} file is still empty.
|
||||
@@ -1886,65 +1856,6 @@ guix system image --image-type=hurd-qcow2 my-hurd-os.scm
|
||||
|
||||
will instead produce a Hurd QEMU image.
|
||||
|
||||
@node Using security keys
|
||||
@section Using security keys
|
||||
@cindex 2FA, two-factor authentication
|
||||
@cindex U2F, Universal 2nd Factor
|
||||
@cindex security key, configuration
|
||||
|
||||
The use of security keys can improve your security by providing a second
|
||||
authentication source that cannot be easily stolen or copied, at least
|
||||
for a remote adversary (something that you have), to the main secret (a
|
||||
passphrase -- something that you know), reducing the risk of
|
||||
impersonation.
|
||||
|
||||
The example configuration detailed below showcases what minimal
|
||||
configuration needs to be made on your Guix System to allow the use of a
|
||||
Yubico security key. It is hoped the configuration can be useful for
|
||||
other security keys as well, with minor adjustments.
|
||||
|
||||
@subsection Configuration for use as a two-factor authenticator (2FA)
|
||||
|
||||
To be usable, the udev rules of the system should be extended with
|
||||
key-specific rules. The following shows how to extend your udev rules
|
||||
with the @file{lib/udev/rules.d/70-u2f.rules} udev rule file provided by
|
||||
the @code{libfido2} package from the @code{(gnu packages
|
||||
security-token)} module and add your user to the @samp{"plugdev"} group
|
||||
it uses:
|
||||
|
||||
@lisp
|
||||
(use-package-modules ... security-token ...)
|
||||
...
|
||||
(operating-system
|
||||
...
|
||||
(users (cons* (user-account
|
||||
(name "your-user")
|
||||
(group "users")
|
||||
(supplementary-groups
|
||||
'("wheel" "netdev" "audio" "video"
|
||||
"plugdev")) ;<- added system group
|
||||
(home-directory "/home/your-user"))
|
||||
%base-user-accounts))
|
||||
...
|
||||
(services
|
||||
(cons*
|
||||
...
|
||||
(udev-rules-service 'fido2 libfido2 #:groups '("plugdev")))))
|
||||
@end lisp
|
||||
|
||||
After re-configuring your system and re-logging in your graphical
|
||||
session so that the new group is in effect for your user, you can verify
|
||||
that your key is usable by launching:
|
||||
|
||||
@example
|
||||
guix shell ungoogled-chromium -- chromium chrome://settings/securityKeys
|
||||
@end example
|
||||
|
||||
and validating that the security key can be reset via the ``Reset your
|
||||
security key'' menu. If it works, congratulations, your security key is
|
||||
ready to be used with applications supporting two-factor authentication
|
||||
(2FA).
|
||||
|
||||
@node Connecting to Wireguard VPN
|
||||
@section Connecting to Wireguard VPN
|
||||
|
||||
@@ -2526,594 +2437,6 @@ ngx.say(stdout)
|
||||
#$(local-file "index.lua"))))))))))))))
|
||||
@end lisp
|
||||
|
||||
@node Music Server with Bluetooth Audio
|
||||
@section Music Server with Bluetooth Audio
|
||||
@cindex mpd
|
||||
@cindex music server, headless
|
||||
@cindex bluetooth, ALSA configuration
|
||||
|
||||
MPD, the Music Player Daemon, is a flexible server-side application for
|
||||
playing music. Client programs on different machines on the network ---
|
||||
a mobile phone, a laptop, a desktop workstation --- can connect to it to
|
||||
control the playback of audio files from your local music collection.
|
||||
MPD decodes the audio files and plays them back on one or many outputs.
|
||||
|
||||
By default MPD will play to the default audio device. In the example
|
||||
below we make things a little more interesting by setting up a headless
|
||||
music server. There will be no graphical user interface, no Pulseaudio
|
||||
daemon, and no local audio output. Instead we will configure MPD with
|
||||
two outputs: a bluetooth speaker and a web server to serve audio streams
|
||||
to any streaming media player.
|
||||
|
||||
Bluetooth is often rather frustrating to set up. You will have to pair
|
||||
your Bluetooth device and make sure that the device is automatically
|
||||
connected as soon as it powers on. The Bluetooth system service
|
||||
returned by the @code{bluetooth-service} procedure provides the
|
||||
infrastructure needed to set this up.
|
||||
|
||||
Reconfigure your system with at least the following services and
|
||||
packages:
|
||||
|
||||
@lisp
|
||||
(operating-system
|
||||
;; …
|
||||
(packages (cons* bluez bluez-alsa
|
||||
%base-packages))
|
||||
(services
|
||||
;; …
|
||||
(dbus-service #:services (list bluez-alsa))
|
||||
(bluetooth-service #:auto-enable? #t)))
|
||||
@end lisp
|
||||
|
||||
Start the @code{bluetooth} service and then use @command{bluetoothctl}
|
||||
to scan for Bluetooth devices. Try to identify your Bluetooth speaker
|
||||
and pick out its device ID from the resulting list of devices that is
|
||||
indubitably dominated by a baffling smorgasbord of your neighbors' home
|
||||
automation gizmos. This only needs to be done once:
|
||||
|
||||
@example
|
||||
$ bluetoothctl
|
||||
[NEW] Controller 00:11:22:33:95:7F BlueZ 5.40 [default]
|
||||
|
||||
[bluetooth]# power on
|
||||
[bluetooth]# Changing power on succeeded
|
||||
|
||||
[bluetooth]# agent on
|
||||
[bluetooth]# Agent registered
|
||||
|
||||
[bluetooth]# default-agent
|
||||
[bluetooth]# Default agent request successful
|
||||
|
||||
[bluetooth]# scan on
|
||||
[bluetooth]# Discovery started
|
||||
[CHG] Controller 00:11:22:33:95:7F Discovering: yes
|
||||
[NEW] Device AA:BB:CC:A4:AA:CD My Bluetooth Speaker
|
||||
[NEW] Device 44:44:FF:2A:20:DC My Neighbor's TV
|
||||
@dots{}
|
||||
|
||||
[bluetooth]# pair AA:BB:CC:A4:AA:CD
|
||||
Attempting to pair with AA:BB:CC:A4:AA:CD
|
||||
[CHG] Device AA:BB:CC:A4:AA:CD Connected: yes
|
||||
|
||||
[My Bluetooth Speaker]# [CHG] Device AA:BB:CC:A4:AA:CD UUIDs: 0000110b-0000-1000-8000-00xxxxxxxxxx
|
||||
[CHG] Device AA:BB:CC:A4:AA:CD UUIDs: 0000110c-0000-1000-8000-00xxxxxxxxxx
|
||||
[CHG] Device AA:BB:CC:A4:AA:CD UUIDs: 0000110e-0000-1000-8000-00xxxxxxxxxx
|
||||
[CHG] Device AA:BB:CC:A4:AA:CD Paired: yes
|
||||
Pairing successful
|
||||
|
||||
[CHG] Device AA:BB:CC:A4:AA:CD Connected: no
|
||||
|
||||
[bluetooth]#
|
||||
[bluetooth]# trust AA:BB:CC:A4:AA:CD
|
||||
[bluetooth]# [CHG] Device AA:BB:CC:A4:AA:CD Trusted: yes
|
||||
Changing AA:BB:CC:A4:AA:CD trust succeeded
|
||||
|
||||
[bluetooth]#
|
||||
[bluetooth]# connect AA:BB:CC:A4:AA:CD
|
||||
Attempting to connect to AA:BB:CC:A4:AA:CD
|
||||
[bluetooth]# [CHG] Device AA:BB:CC:A4:AA:CD RSSI: -63
|
||||
[CHG] Device AA:BB:CC:A4:AA:CD Connected: yes
|
||||
Connection successful
|
||||
|
||||
[My Bluetooth Speaker]# scan off
|
||||
[CHG] Device AA:BB:CC:A4:AA:CD RSSI is nil
|
||||
Discovery stopped
|
||||
[CHG] Controller 00:11:22:33:95:7F Discovering: no
|
||||
@end example
|
||||
|
||||
Congratulations, you can now automatically connect to your Bluetooth
|
||||
speaker!
|
||||
|
||||
It is now time to configure ALSA to use the @emph{bluealsa} Bluetooth
|
||||
module, so that you can define an ALSA pcm device corresponding to your
|
||||
Bluetooth speaker. For a headless server using @emph{bluealsa} with a
|
||||
fixed Bluetooth device is likely simpler than configuring Pulseaudio and
|
||||
its stream switching behavior. We configure ALSA by crafting a custom
|
||||
@code{alsa-configuration} for the @code{alsa-service-type}. The
|
||||
configuration will declare a @code{pcm} type @code{bluealsa} from the
|
||||
@code{bluealsa} module provided by the @code{bluez-alsa} package, and
|
||||
then define a @code{pcm} device of that type for your Bluetooth speaker.
|
||||
|
||||
All that is left then is to make MPD send audio data to this ALSA
|
||||
device. We also add a secondary MPD output that makes the currently
|
||||
played audio files available as a stream through a web server on port
|
||||
8080. When enabled a device on the network could listen to the audio
|
||||
stream by connecting any capable media player to the HTTP server on port
|
||||
8080, independent of the status of the Bluetooth speaker.
|
||||
|
||||
What follows is the outline of an @code{operating-system} declaration
|
||||
that should accomplish the above-mentioned tasks:
|
||||
|
||||
@lisp
|
||||
(use-modules (gnu))
|
||||
(use-service-modules audio dbus sound #;… etc)
|
||||
(use-package-modules audio linux #;… etc)
|
||||
(operating-system
|
||||
;; …
|
||||
(packages (cons* bluez bluez-alsa
|
||||
%base-packages))
|
||||
(services
|
||||
;; …
|
||||
(service mpd-service-type
|
||||
(mpd-configuration
|
||||
(user "your-username")
|
||||
(music-dir "/path/to/your/music")
|
||||
(address "192.168.178.20")
|
||||
(outputs (list (mpd-output
|
||||
(type "alsa")
|
||||
(name "MPD")
|
||||
(extra-options
|
||||
;; Use the same name as in the ALSA
|
||||
;; configuration below.
|
||||
'((device . "pcm.btspeaker"))))
|
||||
(mpd-output
|
||||
(type "httpd")
|
||||
(name "streaming")
|
||||
(enabled? #false)
|
||||
(always-on? #true)
|
||||
(tags? #true)
|
||||
(mixer-type 'null)
|
||||
(extra-options
|
||||
'((encoder . "vorbis")
|
||||
(port . "8080")
|
||||
(bind-to-address . "192.168.178.20")
|
||||
(max-clients . "0") ;no limit
|
||||
(quality . "5.0")
|
||||
(format . "44100:16:1"))))))))
|
||||
(dbus-service #:services (list bluez-alsa))
|
||||
(bluetooth-service #:auto-enable? #t)
|
||||
(service alsa-service-type
|
||||
(alsa-configuration
|
||||
(pulseaudio? #false) ;we don't need it
|
||||
(extra-options
|
||||
#~(string-append "\
|
||||
# Declare Bluetooth audio device type \"bluealsa\" from bluealsa module
|
||||
pcm_type.bluealsa @{
|
||||
lib \"" #$(file-append bluez-alsa "/lib/alsa-lib/libasound_module_pcm_bluealsa.so") "\"
|
||||
@}
|
||||
|
||||
# Declare control device type \"bluealsa\" from the same module
|
||||
ctl_type.bluealsa @{
|
||||
lib \"" #$(file-append bluez-alsa "/lib/alsa-lib/libasound_module_ctl_bluealsa.so") "\"
|
||||
@}
|
||||
|
||||
# Define the actual Bluetooth audio device.
|
||||
pcm.btspeaker @{
|
||||
type bluealsa
|
||||
device \"AA:BB:CC:A4:AA:CD\" # unique device identifier
|
||||
profile \"a2dp\"
|
||||
@}
|
||||
|
||||
# Define an associated controller.
|
||||
ctl.btspeaker @{
|
||||
type bluealsa
|
||||
@}
|
||||
"))))))
|
||||
@end lisp
|
||||
|
||||
Enjoy the music with the MPD client of your choice or a media player
|
||||
capable of streaming via HTTP!
|
||||
|
||||
|
||||
@c *********************************************************************
|
||||
@node Containers
|
||||
@chapter Containers
|
||||
|
||||
The kernel Linux provides a number of shared facilities that are
|
||||
available to processes in the system. These facilities include a shared
|
||||
view on the file system, other processes, network devices, user and
|
||||
group identities, and a few others. Since Linux 3.19 a user can choose
|
||||
to @emph{unshare} some of these shared facilities for selected
|
||||
processes, providing them (and their child processes) with a different
|
||||
view on the system.
|
||||
|
||||
A process with an unshared @code{mount} namespace, for example, has its
|
||||
own view on the file system --- it will only be able to see directories
|
||||
that have been explicitly bound in its mount namespace. A process with
|
||||
its own @code{proc} namespace will consider itself to be the only
|
||||
process running on the system, running as PID 1.
|
||||
|
||||
Guix uses these kernel features to provide fully isolated environments
|
||||
and even complete Guix System containers, lightweight virtual machines
|
||||
that share the host system's kernel. This feature comes in especially
|
||||
handy when using Guix on a foreign distribution to prevent interference
|
||||
from foreign libraries or configuration files that are available
|
||||
system-wide.
|
||||
|
||||
@menu
|
||||
* Guix Containers:: Perfectly isolated environments
|
||||
* Guix System Containers:: A system inside your system
|
||||
@end menu
|
||||
|
||||
@node Guix Containers
|
||||
@section Guix Containers
|
||||
|
||||
The easiest way to get started is to use @command{guix shell} with the
|
||||
@option{--container} option. @xref{Invoking guix shell,,, guix, GNU
|
||||
Guix Reference Manual} for a reference of valid options.
|
||||
|
||||
The following snippet spawns a minimal shell process with most
|
||||
namespaces unshared from the system. The current working directory is
|
||||
visible to the process, but anything else on the file system is
|
||||
unavailable. This extreme isolation can be very useful when you want to
|
||||
rule out any sort of interference from environment variables, globally
|
||||
installed libraries, or configuration files.
|
||||
|
||||
@example
|
||||
guix shell --container
|
||||
@end example
|
||||
|
||||
It is a bleak environment, barren, desolate. You will find that not
|
||||
even the GNU coreutils are available here, so to explore this deserted
|
||||
wasteland you need to use built-in shell commands. Even the usually
|
||||
gigantic @file{/gnu/store} directory is reduced to a faint shadow of
|
||||
itself.
|
||||
|
||||
@example sh
|
||||
$ echo /gnu/store/*
|
||||
/gnu/store/@dots{}-gcc-10.3.0-lib
|
||||
/gnu/store/@dots{}-glibc-2.33
|
||||
/gnu/store/@dots{}-bash-static-5.1.8
|
||||
/gnu/store/@dots{}-ncurses-6.2.20210619
|
||||
/gnu/store/@dots{}-bash-5.1.8
|
||||
/gnu/store/@dots{}-profile
|
||||
/gnu/store/@dots{}-readline-8.1.1
|
||||
@end example
|
||||
|
||||
@cindex exiting a container
|
||||
There isn't much you can do in an environment like this other than
|
||||
exiting it. You can use @key{^D} or @command{exit} to terminate this
|
||||
limited shell environment.
|
||||
|
||||
@cindex exposing directories, container
|
||||
@cindex sharing directories, container
|
||||
@cindex mapping locations, container
|
||||
You can make other directories available inside of the container
|
||||
environment; use @option{--expose=DIRECTORY} to bind-mount the given
|
||||
directory as a read-only location inside the container, or use
|
||||
@option{--share=DIRECTORY} to make the location writable. With an
|
||||
additional mapping argument after the directory name you can control the
|
||||
name of the directory inside the container. In the following example we
|
||||
map @file{/etc} on the host system to @file{/the/host/etc} inside a
|
||||
container in which the GNU coreutils are installed.
|
||||
|
||||
@example sh
|
||||
$ guix shell --container --share=/etc=/the/host/etc coreutils
|
||||
$ ls /the/host/etc
|
||||
@end example
|
||||
|
||||
Similarly, you can prevent the current working directory from being
|
||||
mapped into the container with the @option{--no-cwd} option. Another
|
||||
good idea is to create a dedicated directory that will serve as the
|
||||
container's home directory, and spawn the container shell from that
|
||||
directory.
|
||||
|
||||
@cindex hide system libraries, container
|
||||
@cindex avoid ABI mismatch, container
|
||||
On a foreign system a container environment can be used to compile
|
||||
software that cannot possibly be linked with system libraries or with
|
||||
the system's compiler toolchain. A common use-case in a research
|
||||
context is to install packages from within an R session. Outside of a
|
||||
container environment there is a good chance that the foreign compiler
|
||||
toolchain and incompatible system libraries are found first, resulting
|
||||
in incompatible binaries that cannot be used by R. In a container shell
|
||||
this problem disappears, as system libraries and executables simply
|
||||
aren't available due to the unshared @code{mount} namespace.
|
||||
|
||||
Let's take a comprehensive manifest providing a comfortable development
|
||||
environment for use with R:
|
||||
|
||||
@lisp
|
||||
(specifications->manifest
|
||||
(list "r-minimal"
|
||||
|
||||
;; base packages
|
||||
"bash-minimal"
|
||||
"glibc-locales"
|
||||
"nss-certs"
|
||||
|
||||
;; Common command line tools lest the container is too empty.
|
||||
"coreutils"
|
||||
"grep"
|
||||
"which"
|
||||
"wget"
|
||||
"sed"
|
||||
|
||||
;; R markdown tools
|
||||
"pandoc"
|
||||
|
||||
;; Toolchain and common libraries for "install.packages"
|
||||
"gcc-toolchain@@10"
|
||||
"gfortran-toolchain"
|
||||
"gawk"
|
||||
"tar"
|
||||
"gzip"
|
||||
"unzip"
|
||||
"make"
|
||||
"cmake"
|
||||
"pkg-config"
|
||||
"cairo"
|
||||
"libxt"
|
||||
"openssl"
|
||||
"curl"
|
||||
"zlib"))
|
||||
@end lisp
|
||||
|
||||
Let's use this to run R inside a container environment. For convenience
|
||||
we share the @code{net} namespace to use the host system's network
|
||||
interfaces. Now we can build R packages from source the traditional way
|
||||
without having to worry about ABI mismatch or incompatibilities.
|
||||
|
||||
@example sh
|
||||
$ guix shell --container --network --manifest=manifest.scm -- R
|
||||
|
||||
R version 4.2.1 (2022-06-23) -- "Funny-Looking Kid"
|
||||
Copyright (C) 2022 The R Foundation for Statistical Computing
|
||||
@dots{}
|
||||
> e <- Sys.getenv("GUIX_ENVIRONMENT")
|
||||
> Sys.setenv(GIT_SSL_CAINFO=paste0(e, "/etc/ssl/certs/ca-certificates.crt"))
|
||||
> Sys.setenv(SSL_CERT_FILE=paste0(e, "/etc/ssl/certs/ca-certificates.crt"))
|
||||
> Sys.setenv(SSL_CERT_DIR=paste0(e, "/etc/ssl/certs"))
|
||||
> install.packages("Cairo", lib=paste0(getwd()))
|
||||
@dots{}
|
||||
* installing *source* package 'Cairo' ...
|
||||
@dots{}
|
||||
* DONE (Cairo)
|
||||
|
||||
The downloaded source packages are in
|
||||
'/tmp/RtmpCuwdwM/downloaded_packages'
|
||||
> library("Cairo", lib=getwd())
|
||||
> # success!
|
||||
@end example
|
||||
|
||||
Using container shells is fun, but they can become a little cumbersome
|
||||
when you want to go beyond just a single interactive process. Some
|
||||
tasks become a lot easier when they sit on the rock solid foundation of
|
||||
a proper Guix System and its rich set of system services. The next
|
||||
section shows you how to launch a complete Guix System inside of a
|
||||
container.
|
||||
|
||||
|
||||
@node Guix System Containers
|
||||
@section Guix System Containers
|
||||
|
||||
The Guix System provides a wide array of interconnected system services
|
||||
that are configured declaratively to form a dependable stateless GNU
|
||||
System foundation for whatever tasks you throw at it. Even when using
|
||||
Guix on a foreign distribution you can benefit from the design of Guix
|
||||
System by running a system instance as a container. Using the same
|
||||
kernel features of unshared namespaces mentioned in the previous
|
||||
section, the resulting Guix System instance is isolated from the host
|
||||
system and only shares file system locations that you explicitly
|
||||
declare.
|
||||
|
||||
A Guix System container differs from the shell process created by
|
||||
@command{guix shell --container} in a number of important ways. While
|
||||
in a container shell the containerized process is a Bash shell process,
|
||||
a Guix System container runs the Shepherd as PID 1. In a system
|
||||
container all system services (@pxref{Services,,, guix, GNU Guix
|
||||
Reference Manual}) are set up just as they would be on a Guix System in
|
||||
a virtual machine or on bare metal---this includes daemons managed by
|
||||
the GNU@tie{}Shepherd (@pxref{Shepherd Services,,, guix, GNU Guix
|
||||
Reference Manual}) as well as other kinds of extensions to the operating
|
||||
system (@pxref{Service Composition,,, guix, GNU Guix Reference Manual}).
|
||||
|
||||
The perceived increase in complexity of running a Guix System container
|
||||
is easily justified when dealing with more complex applications that
|
||||
have higher or just more rigid requirements on their execution
|
||||
contexts---configuration files, dedicated user accounts, directories for
|
||||
caches or log files, etc. In Guix System the demands of this kind of
|
||||
software are satisfied through the deployment of system services.
|
||||
|
||||
|
||||
@node A Database Container
|
||||
@subsection A Database Container
|
||||
|
||||
A good example might be a PostgreSQL database server. Much of the
|
||||
complexity of setting up such a database server is encapsulated in this
|
||||
deceptively short service declaration:
|
||||
|
||||
@lisp
|
||||
(service postgresql-service-type
|
||||
(postgresql-configuration
|
||||
(postgresql postgresql-14)))
|
||||
@end lisp
|
||||
|
||||
A complete operating system declaration for use with a Guix System
|
||||
container would look something like this:
|
||||
|
||||
@lisp
|
||||
(use-modules (gnu))
|
||||
(use-package-modules databases)
|
||||
(use-service-modules databases)
|
||||
|
||||
(operating-system
|
||||
(host-name "container")
|
||||
(timezone "Europe/Berlin")
|
||||
(file-systems (cons (file-system
|
||||
(device (file-system-label "does-not-matter"))
|
||||
(mount-point "/")
|
||||
(type "ext4"))
|
||||
%base-file-systems))
|
||||
(bootloader (bootloader-configuration
|
||||
(bootloader grub-bootloader)
|
||||
(targets '("/dev/sdX"))))
|
||||
(services
|
||||
(cons* (service postgresql-service-type
|
||||
(postgresql-configuration
|
||||
(postgresql postgresql-14)
|
||||
(config-file
|
||||
(postgresql-config-file
|
||||
(log-destination "stderr")
|
||||
(hba-file
|
||||
(plain-file "pg_hba.conf"
|
||||
"\
|
||||
local all all trust
|
||||
host all all 10.0.0.1/32 trust"))
|
||||
(extra-config
|
||||
'(("listen_addresses" "*")
|
||||
("log_directory" "/var/log/postgresql")))))))
|
||||
(service postgresql-role-service-type
|
||||
(postgresql-role-configuration
|
||||
(roles
|
||||
(list (postgresql-role
|
||||
(name "test")
|
||||
(create-database? #t))))))
|
||||
%base-services)))
|
||||
@end lisp
|
||||
|
||||
With @code{postgresql-role-service-type} we define a role ``test'' and
|
||||
create a matching database, so that we can test right away without any
|
||||
further manual setup. The @code{postgresql-config-file} settings allow
|
||||
a client from IP address 10.0.0.1 to connect without requiring
|
||||
authentication---a bad idea in production systems, but convenient for
|
||||
this example.
|
||||
|
||||
Let's build a script that will launch an instance of this Guix System as
|
||||
a container. Write the @code{operating-system} declaration above to a
|
||||
file @file{os.scm} and then use @command{guix system container} to build
|
||||
the launcher. (@pxref{Invoking guix system,,, guix, GNU Guix Reference
|
||||
Manual}).
|
||||
|
||||
@example
|
||||
$ guix system container os.scm
|
||||
The following derivations will be built:
|
||||
/gnu/store/@dots{}-run-container.drv
|
||||
@dots{}
|
||||
building /gnu/store/@dots{}-run-container.drv...
|
||||
/gnu/store/@dots{}-run-container
|
||||
@end example
|
||||
|
||||
Now that we have a launcher script we can run it to spawn the new system
|
||||
with a running PostgreSQL service. Note that due to some as yet
|
||||
unresolved limitations we need to run the launcher as the root user, for
|
||||
example with @command{sudo}.
|
||||
|
||||
@example
|
||||
$ sudo /gnu/store/@dots{}-run-container
|
||||
system container is running as PID 5983
|
||||
@dots{}
|
||||
@end example
|
||||
|
||||
Background the process with @key{Ctrl-z} followed by @command{bg}. Note
|
||||
the process ID in the output; we will need it to connect to the
|
||||
container later. You know what? Let's try attaching to the container
|
||||
right now. We will use @command{nsenter}, a tool provided by the
|
||||
@code{util-linux} package:
|
||||
|
||||
@example
|
||||
$ guix shell util-linux
|
||||
$ sudo nsenter -a -t 5983
|
||||
root@@container /# pgrep -a postgres
|
||||
49 /gnu/store/@dots{}-postgresql-14.4/bin/postgres -D /var/lib/postgresql/data --config-file=/gnu/store/@dots{}-postgresql.conf -p 5432
|
||||
51 postgres: checkpointer
|
||||
52 postgres: background writer
|
||||
53 postgres: walwriter
|
||||
54 postgres: autovacuum launcher
|
||||
55 postgres: stats collector
|
||||
56 postgres: logical replication launcher
|
||||
root@@container /# exit
|
||||
@end example
|
||||
|
||||
The PostgreSQL service is running in the container!
|
||||
|
||||
|
||||
@node Container Networking
|
||||
@subsection Container Networking
|
||||
@cindex container networking
|
||||
|
||||
What good is a Guix System running a PostgreSQL database service as a
|
||||
container when we can only talk to it with processes originating in the
|
||||
container? It would be much better if we could talk to the database
|
||||
over the network.
|
||||
|
||||
The easiest way to do this is to create a pair of connected virtual
|
||||
Ethernet devices (known as @code{veth}). We move one of the devices
|
||||
(@code{ceth-test}) into the @code{net} namespace of the container and
|
||||
leave the other end (@code{veth-test}) of the connection on the host
|
||||
system.
|
||||
|
||||
@example
|
||||
pid=5983
|
||||
ns="guix-test"
|
||||
host="veth-test"
|
||||
client="ceth-test"
|
||||
|
||||
# Attach the new net namespace "guix-test" to the container PID.
|
||||
sudo ip netns attach $ns $pid
|
||||
|
||||
# Create the pair of devices
|
||||
sudo ip link add $host type veth peer name $client
|
||||
|
||||
# Move the client device into the container's net namespace
|
||||
sudo ip link set $client netns $ns
|
||||
@end example
|
||||
|
||||
Then we configure the host side:
|
||||
|
||||
@example
|
||||
sudo ip link set $host up
|
||||
sudo ip addr add 10.0.0.1/24 dev $host
|
||||
@end example
|
||||
|
||||
@dots{}and then we configure the client side:
|
||||
|
||||
@example
|
||||
sudo ip netns exec $ns ip link set lo up
|
||||
sudo ip netns exec $ns ip link set $client up
|
||||
sudo ip netns exec $ns ip addr add 10.0.0.2/24 dev $client
|
||||
@end example
|
||||
|
||||
At this point the host can reach the container at IP address 10.0.0.2,
|
||||
and the container can reach the host at IP 10.0.0.1. This is all we
|
||||
need to talk to the database server inside the container from the host
|
||||
system on the outside.
|
||||
|
||||
@example
|
||||
$ psql -h 10.0.0.2 -U test
|
||||
psql (14.4)
|
||||
Type "help" for help.
|
||||
|
||||
test=> CREATE TABLE hello (who TEXT NOT NULL);
|
||||
CREATE TABLE
|
||||
test=> INSERT INTO hello (who) VALUES ('world');
|
||||
INSERT 0 1
|
||||
test=> SELECT * FROM hello;
|
||||
who
|
||||
-------
|
||||
world
|
||||
(1 row)
|
||||
@end example
|
||||
|
||||
Now that we're done with this little demonstration let's clean up:
|
||||
|
||||
@example
|
||||
sudo kill $pid
|
||||
sudo ip netns del $ns
|
||||
sudo ip link del $host
|
||||
@end example
|
||||
|
||||
|
||||
@c *********************************************************************
|
||||
@node Advanced package management
|
||||
@chapter Advanced package management
|
||||
@@ -3210,9 +2533,8 @@ Let's dive in the set up!
|
||||
@node Basic setup with manifests
|
||||
@subsection Basic setup with manifests
|
||||
|
||||
A Guix profile can be set up @i{via} a @dfn{manifest}. A manifest is a
|
||||
snippet of Scheme code that specifies the set of packages you want to
|
||||
have in your profile; it looks like this:
|
||||
A Guix profile can be set up @emph{via} a so-called @emph{manifest specification} that looks like
|
||||
this:
|
||||
|
||||
@lisp
|
||||
(specifications->manifest
|
||||
@@ -3225,8 +2547,8 @@ have in your profile; it looks like this:
|
||||
"package-N"))
|
||||
@end lisp
|
||||
|
||||
@xref{Writing Manifests,,, guix, GNU Guix Reference Manual}, for
|
||||
more information about the syntax.
|
||||
@pxref{Invoking guix package,,, guix, GNU Guix Reference Manual}, for
|
||||
the syntax details.
|
||||
|
||||
We can create a manifest specification per profile and install them this way:
|
||||
|
||||
@@ -3464,7 +2786,7 @@ Maybe a dependency from our manifest has been updated; or we may have run
|
||||
garbage-collected.
|
||||
|
||||
@item
|
||||
Eventually, we set to work on that project again, so we run @code{guix shell
|
||||
Eventually, we set to work on that project again, so we run @code{guix environment
|
||||
-m manifest.scm}. But now we have to wait for Guix to build and install
|
||||
stuff!
|
||||
@end enumerate
|
||||
@@ -3503,8 +2825,8 @@ to reproduce the exact same profile:
|
||||
GUIX_EXTRA_PROFILES=$HOME/.guix-extra-profiles
|
||||
GUIX_EXTRA=$HOME/.guix-extra
|
||||
|
||||
mkdir -p "$GUIX_EXTRA"/my-project
|
||||
guix pull --channels=channel-specs.scm --profile="$GUIX_EXTRA/my-project/guix"
|
||||
mkdir "$GUIX_EXTRA"/my-project
|
||||
guix pull --channels=channel-specs.scm --profile "$GUIX_EXTRA/my-project/guix"
|
||||
|
||||
mkdir -p "$GUIX_EXTRA_PROFILES/my-project"
|
||||
"$GUIX_EXTRA"/my-project/guix/bin/guix package --manifest=/path/to/guix-my-project-manifest.scm --profile="$GUIX_EXTRA_PROFILES"/my-project/my-project
|
||||
|
||||
+696
-4273
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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=2026-01-19.09; # 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/1.4.0
|
||||
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/1.4.0
|
||||
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/
|
||||
|
||||
|
||||
+15
-15
@@ -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
|
||||
|
||||
+90
-109
@@ -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
@@ -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 ()
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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.
|
||||
|
||||
+50
-98
@@ -3,14 +3,13 @@
|
||||
# Copyright © 2017 sharlatan <sharlatanus@gmail.com>
|
||||
# Copyright © 2018 Ricardo Wurmus <rekado@elephly.net>
|
||||
# Copyright © 2018 Efraim Flashner <efraim@flashner.co.il>
|
||||
# Copyright © 2019–2020, 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 Maxim Cournoyer <maxim.cournoyer@gmail.com>
|
||||
# Copyright © 2022 Prafulla Giri <prafulla.giri@protonmail.com>
|
||||
# Copyright © 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com>
|
||||
#
|
||||
# This file is part of GNU Guix.
|
||||
#
|
||||
@@ -34,7 +33,7 @@ then
|
||||
exec bash "$0" "$@"
|
||||
fi
|
||||
|
||||
set -eo pipefail
|
||||
set -e
|
||||
|
||||
[ "$UID" -eq 0 ] || { echo "This script must be run as root."; exit 1; }
|
||||
|
||||
@@ -93,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,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
|
||||
@@ -230,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
|
||||
@@ -238,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}"
|
||||
@@ -262,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
|
||||
}
|
||||
@@ -293,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.
|
||||
@@ -318,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
|
||||
@@ -326,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
|
||||
}
|
||||
|
||||
@@ -338,7 +333,8 @@ sys_create_store()
|
||||
_debug "--- [ ${FUNCNAME[0]} ] ---"
|
||||
|
||||
if [[ -e "/var/guix" || -e "/gnu" ]]; then
|
||||
die "A previous Guix installation was found. Refusing to overwrite."
|
||||
_err "${ERR}A previous Guix installation was found. Refusing to overwrite."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "$tmp_path"
|
||||
@@ -492,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
|
||||
}
|
||||
|
||||
@@ -515,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"
|
||||
@@ -536,14 +514,15 @@ export PATH="$_GUIX_PROFILE/bin${PATH:+:}$PATH"
|
||||
export INFOPATH="$_GUIX_PROFILE/share/info:$INFOPATH"
|
||||
|
||||
# GUIX_PROFILE: User's default profile
|
||||
# Prefer the one from 'guix home' if it exists.
|
||||
GUIX_PROFILE="$HOME/.guix-home/profile"
|
||||
[ -L $GUIX_PROFILE ] || GUIX_PROFILE="$HOME/.guix-profile"
|
||||
GUIX_PROFILE="$HOME/.guix-profile"
|
||||
[ -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
|
||||
}
|
||||
|
||||
@@ -566,28 +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
|
||||
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"
|
||||
}
|
||||
|
||||
welcome()
|
||||
{
|
||||
local char
|
||||
cat<<"EOF"
|
||||
░░░ ░░░
|
||||
░░▒▒░░░░░░░░░ ░░░░░░░░░▒▒░░
|
||||
@@ -613,15 +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'
|
||||
read -r char
|
||||
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()
|
||||
@@ -641,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}"
|
||||
@@ -661,7 +614,6 @@ main()
|
||||
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}"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
+4
-593
@@ -6,18 +6,17 @@
|
||||
;; Copyright © 2019, 2020 Konrad Hinsen <konrad.hinsen@fastmail.net>
|
||||
;; Copyright © 2019, 2020, 2021 Julien Lepiller <julien@lepiller.eu>
|
||||
;; Copyright © 2019–2022 Florian Pelz <pelzflorian@pelzflorian.de>
|
||||
;; Copyright © 2020, 2022 Marius Bakke <marius@gnu.org>
|
||||
;; Copyright © 2020 Marius Bakke <mbakke@fastmail.com>
|
||||
;; Copyright © 2020, 2021 Mathieu Othacehe <m.othacehe@gmail.com>
|
||||
;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
|
||||
;; Copyright © 2020, 2021, 2022 Maxim Cournoyer <maxim.cournoyer@gmail.com>
|
||||
;; Copyright © 2021 Leo Famulari <leo@famulari.name>
|
||||
;; Copyright © 2021 Zhu Zihao <all_but_last@163.com>
|
||||
;; Copyright © 2021 Chris Marusich <cmmarusich@gmail.com>
|
||||
;; Copyright © 2021, 2022 Maxime Devos <maximedevos@telenet.be>
|
||||
;; Copyright © 2021 Maxime Devos <maximedevos@telenet.be>
|
||||
;; Copyright © 2021 Xinglu Chen <public@yoctocell.xyz>
|
||||
;; Copyright © 2021 Andrew Tropin <andrew@trop.in>
|
||||
;; Copyright © 2021 Jonathan Brielmaier <jonathan.brielmaier@web.de>
|
||||
;; Copyright © 2022 Thiago Jung Bauermann <bauermann@kolabnow.com>
|
||||
;;
|
||||
;; Copying and distribution of this file, with or without modification, are
|
||||
;; permitted in any medium without royalty provided the copyright notice and
|
||||
@@ -26,594 +25,6 @@
|
||||
(channel-news
|
||||
(version 0)
|
||||
|
||||
(entry (commit "788602b37ff42f730d4b7b569b0fb51465f147da")
|
||||
(title
|
||||
(en "New @option{--symlink} option for @command{guix shell}")
|
||||
(de "Neue Option @option{--symlink} für @command{guix shell}")
|
||||
(fr "Nouvelle option @option{--symlink} pour @command{guix shell}"))
|
||||
(body
|
||||
(en "The @command{guix shell} command has a new
|
||||
@option{--symlink} (or @option{-S}) option, to be used in conjunction with the
|
||||
@option{--container} (or @option{-C}) option to create a symbolic link inside
|
||||
the container. Run @command{info \"(guix) Invoking guix shell\"} for more
|
||||
information.")
|
||||
(de "Der Befehl @command{guix shell} verfügt jetzt über eine neue
|
||||
Befehlszeilenoption @option{--symlink} (oder @option{-S}), die zusammen mit der
|
||||
Option @option{--container} (oder @option{-C}) benutzt werden kann, um eine
|
||||
symbolische Verknüpfung im Container anzulegen. Führen Sie
|
||||
@command{info \"(guix.de) Aufruf von guix shell\"} aus, um mehr zu erfahren.")
|
||||
(fr "La commande @command{guix shell} dispose d'une nouvelle option,
|
||||
@option{--symlink} (ou @option{-S}), qui doit être utilisée en conjonction
|
||||
avec l'option @option{--container} (ou @option{-C}) pour créer un lien
|
||||
symbolique dans le conteneur. Lancer @command{info \"(guix.fr) Invoquer guix
|
||||
shell\"} pour plus d'informations.")))
|
||||
|
||||
(entry (commit "82a0a395d7051eab7b9f15ec4740d58c86413604")
|
||||
(title
|
||||
(en "Linux-libre kernel updated to 6.0")
|
||||
(de "Linux-libre-Kernel wird auf 6.0 aktualisiert")
|
||||
(fr "Le noyau linux-libre est mis à jour vers la 6.0")
|
||||
(pt "Kernel linux-libre atualizado para 6.0"))
|
||||
(body
|
||||
(en "The default version of the linux-libre kernel has been
|
||||
updated to the 6.0 release series.")
|
||||
(de "Der standardmäßig verwendete @code{linux-libre}-Kernel basiert
|
||||
jetzt auf der 6.0-Versionsreihe.")
|
||||
(fr "La version par défaut du noyau linux-libre est mise à jour
|
||||
vers la série des 6.0.")
|
||||
(pt "A versão padrão do kernel linux-libre foi atualizada para a
|
||||
série do kernel 6.0.")))
|
||||
|
||||
(entry (commit "400a7a4c80efbde1905ae98a298bbb5882d46a0d")
|
||||
(title
|
||||
(en "New build system for Python packages")
|
||||
(de "Neues Erstellungssystem für Python-Pakete")
|
||||
(fr "Nouveau système de construction pour les paquets Python")
|
||||
(pt "Novo sistema de compilação para pacotes Python"))
|
||||
(body
|
||||
(en "A new @var{pyproject-build-system} has been added. This
|
||||
is a redesign of @var{python-build-system} with support for @dfn{PEP 517}
|
||||
and @file{pyproject.toml} files. It also has built-in support for various
|
||||
test frameworks such as @command{pytest} and @code{nosetests}.
|
||||
|
||||
There is a complementary @code{python-toolchain} package that comes with
|
||||
updated versions of @command{pip}, @command{setuptools} and others.
|
||||
|
||||
The build system will eventually be merged into @var{python-build-system}
|
||||
but you are encouraged to use it for packages in the @code{guix} channel.
|
||||
Third party channels may want to wait until the API is stable (see the
|
||||
Guix manual for caveats).
|
||||
|
||||
Despite the name, @var{pyproject-build-system} also works with the
|
||||
``legacy'' @file{setup.py} format.")
|
||||
(de "Ein neues Erstellungssystem @var{pyproject-build-system} ist
|
||||
verfügbar. Es ist eine Neuauflage des @var{python-build-system}, die
|
||||
@dfn{PEP 517} und @file{pyproject.toml}-Dateien unterstützt. Auch wurde
|
||||
Unterstützung für Testrahmen wie @command{pytest} und @code{nosetests}
|
||||
eingebaut.
|
||||
|
||||
Ergänzend gibt es ein Paket @code{python-toolchain} mit aktualisierten Versionen
|
||||
von @command{pip}, @command{setuptools} und mehr.
|
||||
|
||||
Das Erstellungssystem wird in Zukunft Teil von @var{python-build-system} werden,
|
||||
aber wir würden es begrüßen, wenn Sie es für Pakete auf dem @code{guix}-Kanal
|
||||
verwenden würden. Drittanbieterkanäle warten vielleicht lieber auf eine
|
||||
stabile Programmierschnittstelle (siehe die im Guix-Handbuch genannten
|
||||
Einschränkungen).
|
||||
|
||||
Trotz dem Namen funktioniert @var{pyproject-build-system} auch mit dem „alten“
|
||||
@file{setup.py}-Format.")
|
||||
(fr "Un nouveau système de construction, @var{pyproject-build-system},
|
||||
a été ajouté. Il s'agit d'une refonte du @var{python-build-system} qui rajoute
|
||||
la prise en charge de @dfn{PEP 517} et des fichiers @file{pyproject.toml}.
|
||||
Il intègre aussi la prise en charge de divers cadriciels de test comme
|
||||
@command{pytest} ou @code{nosetests}.
|
||||
|
||||
Un paquet supplémentaire @code{python-toolchain} fournit des versions à jour
|
||||
de @command{pip}, @command{setuptools} et autres.
|
||||
|
||||
Le système de construction finira par être intégré au @var{python-build-system}
|
||||
mais nous vous encourageons à l'utiliser pour les paquets du canal @code{guix}.
|
||||
Les canaux tiers devraient attendre que l'API se stabilise (voir le manuel de
|
||||
Guix pour les mises en garde).
|
||||
|
||||
Contrairement à ce qu'indique son nom, @var{pyproject-build-system} fonctionne
|
||||
aussi avec « l'ancien » format @file{setup.py}.")
|
||||
(pt "Um novo sistema de compilação chamado @var{pyproject-build-system}
|
||||
foi adicionado. É um redesign do @var{python-build-system} com suporte à
|
||||
@dfn{PEP 517} e a arquivos @file{pyproject.toml}. Ele também inclui suporte a
|
||||
vários frameworks de teste tais como @command{pytest} e @code{nosetests}.
|
||||
|
||||
Há um pacote complementar @code{python-toolchain} que contém versões
|
||||
atualizadas do @command{pip}, @command{setuptools} e outros.
|
||||
|
||||
O sistema de compilação será eventualmente incorporado ao
|
||||
@var{python-build-system}, mas encorajamos você a usá-lo para pacotes no canal
|
||||
@code{guix}. Canais de terceiros podem querer esperar até a API se
|
||||
estabilizar (veja o manual do Guix para ressalvas).
|
||||
|
||||
Apesar do nome, o @var{pyproject-build-system} também funciona com o formato
|
||||
“legado” do @file{setup.py}.")))
|
||||
|
||||
(entry (commit "c7ba5f38b80433b040d3946b8fc0b1e8621ba30a")
|
||||
(title
|
||||
(en "New @option{--emulate-fhs} option for @command{guix shell}")
|
||||
(de "Neue Option @option{--emulate-fhs} für @command{guix shell}")
|
||||
(fr "Nouvelle option @option{--emulate-fhs} pour @command{guix shell}")
|
||||
(pt "Nova opção @option{--emulate-fhs} para o @command{guix shell}"))
|
||||
(body
|
||||
(en "The @command{guix shell} command has a new
|
||||
@option{--emulate-fhs} (or @option{-F}) option. Combined with
|
||||
@option{--container} (or @option{-C}), it emulates the file and directory
|
||||
layout specified by the Filesystem Hierarchy Standard (FHS), providing
|
||||
@file{/bin}, @file{/lib}, etc. within the container.
|
||||
|
||||
For example, the following command runs @file{/bin/ls} within such a
|
||||
container:
|
||||
|
||||
@example
|
||||
guix shell -CF coreutils -- /bin/ls
|
||||
@end example
|
||||
|
||||
Run @command{info \"(guix) Invoking guix shell\"} for more information.")
|
||||
(de "Der Befehl @command{guix shell} verfügt jetzt über eine neue
|
||||
Befehlszeilenoption @option{--emulate-fhs} (oder @option{-F}). Zusammen mit
|
||||
@option{--container} (oder @option{-C}) kann so die Datei- und
|
||||
Verzeichnisstruktur, die im @i{Filesystem Hierarchy Standard} (FHS) vorgegeben
|
||||
wird, nachgebildet werden. Das heißt, in der Container-Umgebung gibt es
|
||||
@file{/bin}, @file{/lib} und so weiter.
|
||||
|
||||
Zum Beispiel wird folgender Befehl @file{/bin/ls} in einem solchen Container
|
||||
ausführen:
|
||||
|
||||
@example
|
||||
guix shell -CF coreutils -- /bin/ls
|
||||
@end example
|
||||
|
||||
Führen Sie @command{info \"(guix.de) Aufruf von guix shell\"} aus, um mehr
|
||||
zu erfahren.")
|
||||
(fr "La commande @command{guix shell} dispose d'une nouvelle option,
|
||||
@option{--emulate-fhs} (ou @option{-F}). Avec @option{--container} (ou
|
||||
@option{-C}), elle permet d'imiter la disposition des fichiers et répertoires
|
||||
spécifiée par le @i{Filesystem Hierarchy Standard} (FHS) en fournissant
|
||||
@file{/bin}, @file{/lib}, etc. dans le conteneur.
|
||||
|
||||
Par exemple, la commande ci-dessous lance @file{/bin/ls} dans un tel
|
||||
conteneur :
|
||||
|
||||
@example
|
||||
guix shell -CF coreutils -- /bin/ls
|
||||
@end example
|
||||
|
||||
Lancer @command{info \"(guix.fr) Invoquer guix shell\"} pour plus
|
||||
d'informations.")
|
||||
(pt "O comando @command{guix shell} tem uma nova opção
|
||||
@option{--emulate-fhs} (ou @option{-F}). Combinada com
|
||||
@option{--container} (ou @option{-C}), ela emula o layout de arquivos e
|
||||
diretórios especificado pelo Padrão de Hierarquia do Sistema de
|
||||
Arquivos (Filesystem Hierarchy Standard — FHS), provendo @file{/bin},
|
||||
@file{/lib}, etc. dentro do contêiner.
|
||||
|
||||
Por exemplo, o comando seguinte executa @file{/bin/ls} dentro de um contêiner
|
||||
desse tipo:
|
||||
|
||||
@example
|
||||
guix shell -CF coreutils -- /bin/ls
|
||||
@end example
|
||||
|
||||
Execute @command{info \"(guix) Invoking guix shell\"} para mais informações.")))
|
||||
|
||||
(entry (commit "28ade1bab207974cce6a014e7187968511fc5526")
|
||||
(title
|
||||
(en "@option{--with-source} is now recursive")
|
||||
(de "@option{--with-source} ist jetzt rekursiv")
|
||||
(fr "@option{--with-source} est dorénavant récursive")
|
||||
(pt "@option{--with-source} agora é recursiva"))
|
||||
(body
|
||||
(en "The @option{--with-source} package transformation option now
|
||||
uses the specified source for all matching packages, including dependencies.
|
||||
This option is useful for all package maintainers, developers, and, in
|
||||
general, all users who want Guix to facilitate their rights to modify their
|
||||
software and share their changes.
|
||||
|
||||
Run @command{info \"(guix) Package Transformation Options\"} for more
|
||||
info.")
|
||||
(de "Die Paketumwandlungsoption @option{--with-source} wird jetzt den
|
||||
angegebenen Quellcode für sämtliche passende Pakete benutzen, Abhängigkeiten
|
||||
eingeschlossen. Die Option hilft Paketbetreuern, Entwicklern und allgemein allen
|
||||
Nutzern, die Guix benutzen, das Recht, ihre Software anzupassen und
|
||||
Änderungen zu teilen, leichter auszuüben.
|
||||
|
||||
Führen Sie für mehr Informationen @command{info \"(guix.de)
|
||||
Paketumwandlungsoptionen\"} aus.")
|
||||
(fr "L'option de transformation de paquet @option{--with-source}
|
||||
s'applique désormais à tous les paquets correspondant, y compris les
|
||||
dépendances. Cette option est utile pour les personnes qui maintiennent un
|
||||
logiciel, en développent un ou, plus généralement, pour toute personne qui
|
||||
souhaite que Guix facilite l'exercice de ses droits à modifier le logiciel et
|
||||
à partager ses changements.
|
||||
|
||||
Lancer @command{info \"(guix.fr) Options de transformation de paquets\"} pour
|
||||
plus d'informations.")
|
||||
(pt "A opção de transformação de pacote @option{--with-source} agora
|
||||
usa a fonte especificada para todos os pacotes correspondentes, incluindo
|
||||
dependências. Essa opção é útil para todos os mantenedores de pacotes,
|
||||
desenvolvedores e usuários em geral que querem que o Guix facilite seu direito
|
||||
de modificar seu software e compartilhar suas mudanças.
|
||||
|
||||
Execute @command{info \"(guix) Package Transformation Options\"} para mais
|
||||
informações.")))
|
||||
|
||||
(entry (commit "a13f5ead0265cf0fe11e60150547c09dfc8c45b0")
|
||||
(title
|
||||
(en "Guix System image creation is now documented")
|
||||
(de "Es gibt eine Dokumentation, wie Sie Guix-System-Abbilder („Images“) erzeugen")
|
||||
(fr "La création d'images pour Guix System est à présent documentée")
|
||||
(pt "A criação de imagens do Guix System agora está documentada"))
|
||||
(body
|
||||
(en "The Guix System image API that allows you to create customized
|
||||
system images and turn them into actual bootable images is now documented in
|
||||
the @code{Creating System Images} chapter of the Guix documentation. This
|
||||
should be particularly useful for people trying to port Guix System to new
|
||||
hardware.")
|
||||
(de "Sie können nun im Kapitel @code{Creating System Images} der
|
||||
Dokumentation nachlesen, wie Sie mit der Schnittstelle für Guix-System-Abbilder
|
||||
anpassbare, bootfähige Systemabbilder erzeugen können. Das sollte vor allem
|
||||
Personen unterstützen, die versuchen, Guix System auf neuer Hardware zum Laufen
|
||||
zu bringen.")
|
||||
(fr "L'interface de programmation d'images pour Guix System,
|
||||
permettant de créer des images personnalisées et de les transformer en images
|
||||
amorçables est désormais documentée dans le chapitre @code{Création d'images
|
||||
système}. Cette interface devrait être particulièrement utile aux personnes
|
||||
qui essaient de faire fonctionner Guix sur de nouvelles machines.")
|
||||
(pt "A API de imagens do Guix System que permite criar imagens de
|
||||
sistema customizadas e torná-las inicializáveis agora está documentada no
|
||||
capítulo @code{Creating System Images} da documentação do Guix. Isso é
|
||||
particularmente útil para pessoas tentando portar o Guix System para um novo
|
||||
hardware.")))
|
||||
(entry (commit "c8112f3bd95269ce4aca12dedbfe61bb6b37acae")
|
||||
(title
|
||||
(en "WSL system images support")
|
||||
(de "WSL-Systemabbilder werden unterstützt")
|
||||
(fr "Support pour les images système WSL")
|
||||
(pt "Suporte a imagens de sistema WSL"))
|
||||
(body
|
||||
(en "The @command{guix system image} command can now generate system
|
||||
images for the Windows Subsystem for Linux. To get started, you can for
|
||||
instance run from a Guix checkout:
|
||||
|
||||
@command{guix system image gnu/system/images/wsl2.scm},
|
||||
|
||||
and import the resulting image this way:
|
||||
|
||||
@command{wsl --import Guix ./guix ./wsl2-image.tar.gz}
|
||||
@command{wsl -d Guix}.")
|
||||
(de "Mit dem Befehl @command{guix system image} können Sie
|
||||
Systemabbilder erzeugen, die auf dem Windows-Subsystem für Linux laufen. Wenn
|
||||
Sie das ausprobieren möchten, führen Sie zum Beispiel Folgendes aus einem
|
||||
Guix-Checkout heraus aus:
|
||||
|
||||
@command{guix system image gnu/system/images/wsl2.scm},
|
||||
|
||||
Das resultierende Abbild können Sie so importieren:
|
||||
|
||||
@command{wsl --import Guix ./guix ./wsl2-image.tar.gz}
|
||||
@command{wsl -d Guix}.")
|
||||
(fr "La commande @command{guix system image} peut désormais générer
|
||||
des images système pour le Windows Subystem for Linux. Vous pouvez par
|
||||
exemple lancer la commande suivante depuis un répertoire de sources Guix :
|
||||
|
||||
@command{guix system image gnu/system/images/wsl2.scm},
|
||||
|
||||
et importer l'image obtenue de cette manière :
|
||||
|
||||
@command{wsl --import Guix ./guix ./wsl2-image.tar.gz}
|
||||
@command{wsl -d Guix}.")
|
||||
(pt "Agora o comando @command{guix system image} pode gerar imagens
|
||||
de sistema para o Subsistema do Windows para Linux. Para começar, você pode
|
||||
por exemplo rodar a partir de um checkout do repositório do Guix:
|
||||
|
||||
@command{guix system image gnu/system/images/wsl2.scm},
|
||||
|
||||
e importar a imagem resultante da seguinte maneira:
|
||||
|
||||
@command{wsl --import Guix ./guix ./wsl2-image.tar.gz}
|
||||
@command{wsl -d Guix}.")))
|
||||
(entry (commit "11a06d1e49f4d50d6789e05bbf35e2e145ff7838")
|
||||
(title
|
||||
(en "Emacs now supports native compilation")
|
||||
(de "Emacs kann Pakete nun nativ kompilieren")
|
||||
(pt "O Emacs agora suporta compilação nativa"))
|
||||
(body
|
||||
(en "Emacs can now compile packages natively. Under the default
|
||||
configuration, this means that Emacs packages will now be just-in-time (JIT)
|
||||
compiled as you use them, and the results stored in a subdirectory of your
|
||||
@code{user-emacs-directory}.
|
||||
|
||||
Furthermore, the build system for Emacs packages transparently supports native
|
||||
compilation, but note, that @code{emacs-minimal}---the default Emacs for
|
||||
building packages---has been configured without native compilation.
|
||||
To natively compile your emacs packages ahead of time, use a transformation
|
||||
like @option{--with-input=emacs-minimal=emacs}.")
|
||||
(de "Emacs kann nun native Maschinenbefehle erzeugen. Standardgemäß
|
||||
kompiliert es nun Pakete „just in time“, während Sie diese laden, und platziert
|
||||
die so erzeugten nativen Bibliotheken in einem Unterverzeichnis Ihres
|
||||
@code{user-emacs-directory}.
|
||||
|
||||
Darüber hinaus unterstützt das Erstellungssystem für Emacs-Pakete die Erzeugung
|
||||
nativer Maschinenbefehle. Beachten Sie jedoch, dass @code{emacs-minimal} –
|
||||
die Emacs-Variante, mit der normalerweise Emacs-Pakete erstellt werden –
|
||||
weiterhin keine nativen Befehle generiert. Um native Befehle für Ihre
|
||||
Emacs-Pakete schon im Voraus zu erzeugen, nutzen Sie eine Transformation, z.B.
|
||||
@option{--with-input=emacs-minimal=emacs}.")
|
||||
(pt "Agora o Emacs pode compilar pacotes nativamente. Na
|
||||
configuração padrão os pacotes do Emacs serão compilados “just-in-time” (JIT)
|
||||
conforme forem usados, e os resultados armazenados em um subdiretório de
|
||||
@code{user-emacs-directory}.
|
||||
|
||||
Além disso, o sistema de compilação para pacotes do Emacs suporta compilação
|
||||
nativa de forma transparente. Note porém que o @code{emacs-minimal} --- a
|
||||
variante padrão do Emacs para compilar pacotes --- foi configurado sem
|
||||
compilação nativa. Para pré-compilar nativamente seus pacotes do Emacs use
|
||||
uma transformação, como por exemplo
|
||||
@code{--with-input=emacs-minimal=emacs}.")))
|
||||
|
||||
(entry (commit "c188cf57f161c0c26e2d7c8516bd1ddd1492d686")
|
||||
(title
|
||||
(en "Linux-libre kernel updated to 5.19")
|
||||
(de "Linux-libre-Kernel wird auf 5.19 aktualisiert")
|
||||
(fr "Le noyau linux-libre est mis à jour vers la 5.19")
|
||||
(pt "Kernel linux-libre atualizado para 5.19"))
|
||||
(body
|
||||
(en "The default version of the linux-libre kernel has been
|
||||
updated to the 5.19 release series.")
|
||||
(de "Der standardmäßig verwendete @code{linux-libre}-Kernel basiert
|
||||
jetzt auf der 5.19-Versionsreihe.")
|
||||
(fr "La version par défaut du noyau linux-libre est mise à jour
|
||||
vers la série des 5.19.")
|
||||
(pt "A versão padrão do kernel linux-libre foi atualizada para a
|
||||
série do kernel 5.19.")))
|
||||
|
||||
(entry (commit "a15542d26df42dabdb5e2f76d150ae200230c3b0")
|
||||
(title
|
||||
(en "New @option{--whole-file} option for @command{guix style}")
|
||||
(de "Neue Option @option{--whole-file} für @command{guix style}")
|
||||
(fr "Nouvelle option @option{--whole-file} pour @command{guix style}")
|
||||
(pt "Nova opção @option{--whole-file} para @command{guix style}"))
|
||||
(body
|
||||
(en "The @command{guix style} command has a new @option{--whole-file}
|
||||
option: instead of formatting individual package definitions, this option lets
|
||||
you reformat entire Scheme files. You might want to use it to format your
|
||||
operating system configuration file, for instance.
|
||||
|
||||
Run @command{info \"(guix) Invoking guix style\"} for more info.")
|
||||
(de "Der Befehl @command{guix style} verfügt über eine neue
|
||||
Befehlszeilenoption @option{--whole-file}: Mit ihr werden keine einzelnen
|
||||
Paketdefinitionen umformatiert, sondern ganze Scheme-Dateien werden in die
|
||||
richtige Darstellungsform gebracht. Sie können damit zum Beispiel die
|
||||
Konfigurationsdatei für Ihr Betriebssystem formatieren lassen.
|
||||
|
||||
Führen Sie @command{info \"(guix.de) Aufruf von guix style\"} aus, um mehr
|
||||
Informationen zu erhalten.")
|
||||
(fr "La commande @command{guix style} a désormais une nouvelle option
|
||||
@option{--whole-file} : au lieu de mettre en forme des définitions de paquets,
|
||||
cette option permet de mettre en forme des fichiers Scheme entiers. Ça peut
|
||||
s'avérer utile par exemple pour mettre en forme son fichier de configuration
|
||||
du système d'exploitation.
|
||||
|
||||
Lancer @command{info \"(guix.fr) Invoquer guix style\"} pour plus
|
||||
d'informations.")
|
||||
(pt "O comando @command{guix style} tem uma nova opção
|
||||
@option{--whole-file}: ao invés de formatar definições de pacote
|
||||
individualmente, esta opção permite a reformatação de arquivos Scheme por
|
||||
inteiro. Você pode querer usá-la para formatar seu arquivo de configuração do
|
||||
sistema operacional, por exemplo.
|
||||
|
||||
Execute @command{info \"(guix) Invoking guix style\"} para mais informações.")))
|
||||
|
||||
(entry (commit "2ec7ab2610eb67e26dab52b671eb29e46f64ea0f")
|
||||
(title
|
||||
(en "Linux-libre kernel updated to 5.18")
|
||||
(de "Linux-libre-Kernel wird auf 5.18 aktualisiert")
|
||||
(fr "Le noyau linux-libre est mis à jour vers la 5.18"))
|
||||
(body
|
||||
(en "The default version of the linux-libre kernel has been
|
||||
updated to the 5.18 release series.")
|
||||
(de "Der standardmäßig verwendete @code{linux-libre}-Kernel basiert
|
||||
jetzt auf der 5.18-Versionsreihe.")
|
||||
(fr "La version par défaut du noyau linux-libre est mise à jour
|
||||
vers la série des 5.18.")))
|
||||
|
||||
(entry (commit "bdf422176739b473add66eb8cac9fdd8c654f794")
|
||||
(title
|
||||
(en "@option{-L} option of @command{guix refresh} repurposed")
|
||||
(de "Option @option{-L} von @command{guix refresh} wechselt Bedeutung")
|
||||
(fr "Option @option{-L} de @command{guix refresh} réutilisée"))
|
||||
(body
|
||||
(en "The @option{-L} option of @command{guix refresh} has been
|
||||
repurposed: it used to be synonymous with @option{--list-updaters}; it is now
|
||||
synonymous with @option{--load-path} as is the case with most other commands.
|
||||
|
||||
Run @command{info \"(guix) Invoking guix refresh\"} for more info.")
|
||||
(de "Die Befehlszeilenoption @option{-L} von @command{guix refresh} hat
|
||||
einen anderen Zweck bekommen: Früher war sie gleichbedeutend mit
|
||||
@option{--list-updaters}; jetzt ist sie gleichbedeutend mit
|
||||
@option{--load-path}, wie bereits beim Großteil der anderen Befehle.
|
||||
|
||||
Führen Sie @command{info \"(guix.de) Aufruf von guix refresh\"} aus, wenn Sie
|
||||
mehr wissen möchten.")
|
||||
(fr "L'option @option{-L} de @command{guix refresh} a changé de
|
||||
signification : elle était auparavant synonyme de @option{--list-updaters} ;
|
||||
elle est maintenant synonyme de @option{--load-path} comme c'est le cas pour
|
||||
la plupart des autres commandes.
|
||||
|
||||
Lancer @command{info \"(guix.fr) Invoquer guix refresh\"} pour plus
|
||||
d'informations.")))
|
||||
|
||||
(entry (commit "35c1edb20ad07250728d3bdcd0296bd0cedaf6bb")
|
||||
(title
|
||||
(en "New @command{edit} sub-commands for services")
|
||||
(de "Neue @command{edit}-Unterbefehle für Dienste")
|
||||
(fr "Nouvelles commandes @command{edit} pour les services")
|
||||
(nl "Nieuwe deelopdracht @command{edit} voor diensten"))
|
||||
(body
|
||||
(en "The new @command{guix system edit} and @command{guix home edit} commands
|
||||
allow you to view or edit service types defined for Guix System or Guix Home.
|
||||
For example, here is how you would open the definition of the OpenSSH system
|
||||
service:
|
||||
|
||||
@example
|
||||
guix system edit openssh
|
||||
@end example
|
||||
|
||||
Run @command{info \"(guix) Invoking guix system\"} or @command{info \"(guix)
|
||||
Invoking guix home\"} for more info.")
|
||||
(de "Mit den neuen Befehlen @command{guix system edit} und
|
||||
@command{guix home edit} können Sie Diensttypen für Guix System oder Guix Home
|
||||
betrachten und bearbeiten. Zum Beispiel würden Sie die Definition des
|
||||
OpenSSH-Systemdienstes wie folgt öffnen:
|
||||
|
||||
@example
|
||||
guix system edit openssh
|
||||
@end example
|
||||
|
||||
Führen Sie @command{info \"(guix.de) Aufruf von guix system\"} oder
|
||||
@command{info \"(guix.de) Aufruf von guix home\"} aus, um mehr zu erfahren.")
|
||||
(fr "Les nouvelles commandes @command{guix system edit} et
|
||||
@command{guix home edit} permettent de visualiser ou d'éditer les types de
|
||||
services définis pour Guix System ou Guix Home. Par exemple, voici comment
|
||||
ouvrir la définition du service système OpenSSH :
|
||||
|
||||
@example
|
||||
guix system edit openssh
|
||||
@end example
|
||||
|
||||
Lancer @command{info \"(guix.fr) Invoquer guix system\"} ou @command{info
|
||||
\"(guix.fr) Invoquer guix home\"} pour plus d'informations.")
|
||||
;; TODO: pas verwijzingen naar de handleiding aan wanneer ze vertaald is
|
||||
(nl "Met de nieuwe bewerkingen @command{guix system edit} en
|
||||
@command{guix home edit} kan je dienstsoorten van Guix System en Guix
|
||||
Home bekijken en bewerken. Je kan bijvoorbeeld de definitie van de
|
||||
systeemdienst OpenSSH als volgt openen:
|
||||
|
||||
@example
|
||||
guix system edit openssh
|
||||
@end example
|
||||
|
||||
Voer @command{info \"(guix) Invoking guix system\"} of @command{info
|
||||
\"(guix)Invoking guix home\"} uit voor meer informatie.")))
|
||||
|
||||
(entry (commit "903c82583e1cec4c9ff09d5895c5cc646c37b661")
|
||||
(title
|
||||
(en "New @command{guix import elm} command")
|
||||
(de "Neuer Befehl @command{guix import elm}")
|
||||
(fr "Nouvelle commande @command{guix import elm}"))
|
||||
(body
|
||||
(en "The new @command{guix import elm} command allows packagers to
|
||||
generate a package definition or given the name of a package for Elm, a
|
||||
functional programming language for the Web:
|
||||
|
||||
@example
|
||||
guix import elm elm/bytes
|
||||
@end example
|
||||
|
||||
Run @command{info \"(guix) Invoking guix import\"} for more info.
|
||||
|
||||
This comes with a new build system for Elm packages---run @command{info
|
||||
\"(guix) Build Systems\"} for details.")
|
||||
(de "Mit dem neuen Befehl @command{guix import elm} können Paketautoren
|
||||
eine Paketdefinition anhand des Namens eines Pakets für Elm, einer funktionalen
|
||||
Programmiersprache für das Web, erzeugen:
|
||||
|
||||
@example
|
||||
guix import elm elm/bytes
|
||||
@end example
|
||||
|
||||
Führen Sie @command{info \"(guix.de) Aufruf von guix import\"} aus, um mehr
|
||||
Informationen zu bekommen.
|
||||
|
||||
Dazu kommt ein neues Erstellungssystem für Elm-Pakete. Führen Sie
|
||||
@command{info \"(guix.de) Erstellungssysteme\"} aus, um mehr zu erfahren.")
|
||||
(fr "La nouvelle commande @command{guix import elm} permet de générer
|
||||
une définition de paquet reposant sur Elm, un langage de programmation
|
||||
fonctionnelle pour le Web:
|
||||
|
||||
@example
|
||||
guix import elm elm/bytes
|
||||
@end example
|
||||
|
||||
Lancer @command{info \"(guix.fr) Invoquer guix import\"} pour plus
|
||||
d'informations.
|
||||
|
||||
Cela vient avec un nouveau système de construction pour paquets Elm---lancer
|
||||
@command{info \"(guix.fr) Systèmes de construction\"} pour plus de détails.")))
|
||||
|
||||
(entry (commit "b6b2de2a0d52530bc1ee128c61580bed662ee15c")
|
||||
(title (en "Linux-libre kernel updated to 5.17")
|
||||
(de "Linux-libre-Kernel wird auf 5.17 aktualisiert")
|
||||
(fr "Le noyau linux-libre est mis à jour vers la 5.17"))
|
||||
(body
|
||||
(en "The default version of the linux-libre kernel has been
|
||||
updated to the 5.17 release series.")
|
||||
(de "Der standardmäßig verwendete @code{linux-libre}-Kernel basiert
|
||||
jetzt auf der 5.17-Versionsreihe.")
|
||||
(fr "La version par défaut du noyau linux-libre est mise à jour
|
||||
vers la série des 5.17.")))
|
||||
|
||||
(entry (commit "c42b7baf13c7633b4512e94da7445299c57b247d")
|
||||
(title
|
||||
(en "New @option{--export-manifest} option for @command{guix shell}")
|
||||
(de "Neue Option @option{--export-manifest} für @command{guix shell}")
|
||||
(fr "Nouvelle option @option{--export-manifest} de @command{guix shell}"))
|
||||
(body
|
||||
(en "If you use @command{guix shell}, you might wonder how to
|
||||
``translate'' a command line into a manifest file that you can keep under
|
||||
version control, share with others, and pass to @command{guix shell -m} and in
|
||||
fact to most @command{guix} commands. This is what the new
|
||||
@option{--export-manifest} option does.
|
||||
|
||||
For example, the command below prints a manifest for the given packages:
|
||||
|
||||
@lisp
|
||||
guix shell --export-manifest \\
|
||||
-D guile git emacs emacs-geiser emacs-geiser-guile
|
||||
@end lisp
|
||||
|
||||
Run @code{info \"(guix) Invoking guix shell\"} for more information.")
|
||||
(de "Wenn Sie @command{guix shell} benutzen, haben Sie sich vielleicht
|
||||
einmal gefragt, wie Sie eine Befehlszeile in eine Manifest-Datei „übersetzen“
|
||||
können, die Sie unter Versionskontrolle stellen können, mit anderen teilen
|
||||
können und an @command{guix shell -m} oder tatsächlich die meisten anderen
|
||||
@command{guix}-Befehle übergeben können. Die Antwort ist die neue
|
||||
Befehlszeilenoption @option{--export-manifest}.
|
||||
|
||||
Zum Beispiel gibt der folgende Befehl ein Manifest mit den genannten Paketen
|
||||
aus:
|
||||
|
||||
@lisp
|
||||
guix shell --export-manifest \\
|
||||
-D guile git emacs emacs-geiser emacs-geiser-guile
|
||||
@end lisp
|
||||
|
||||
Führen Sie @command{info \"(guix.de) Aufruf von guix shell\"} aus, um mehr
|
||||
zu erfahren.")
|
||||
(fr "Si tu utilises @command{guix shell}, tu t'es peut-être déjà
|
||||
demandé comment « traduire » une ligne de commande en un fichier manifeste que
|
||||
tu puisse garder en gestion de version, partager et passer à @command{guix
|
||||
shell -m} et autres commandes @command{guix}. C'est ce que la nouvelle option
|
||||
@option{--export-manifest} fait.
|
||||
|
||||
Par exemple, la commande ci-dessous affiche un manifeste pour les paquets
|
||||
donnés :
|
||||
|
||||
@lisp
|
||||
guix shell --export-manifest \\
|
||||
-D guile git emacs emacs-geiser emacs-geiser-guile
|
||||
@end lisp
|
||||
|
||||
Lancer @code{info \"(guix.fr) Invoquer guix shell\"} pour plus
|
||||
d'informations.")))
|
||||
|
||||
(entry (commit "094a2cfbe45c104d0da30ff9d975d052ca0c118c")
|
||||
(title
|
||||
(en "New @command{guix home container} command")
|
||||
@@ -777,7 +188,7 @@ Bezeichnungen aus Paketeingaben entfernt werden. Wenn Sie {--styling}
|
||||
weglassen, passiert das Gleiche wie wenn Sie @samp{--styling=format} angeben;
|
||||
früher war es das Gleiche wie @samp{--styling=inputs}.
|
||||
|
||||
Führen Sie @command{info \"(guix.de) Aufruf von guix style\"} aus, um mehr
|
||||
Führen Sie @command{info \"(guix) Invoking guix style\"} aus, um mehr
|
||||
Informationen zu erhalten.")
|
||||
(fr "La commande @command{guix style}, récemment introduite, peut
|
||||
désormais être utilisée pour mettre en forme des définitions de paquets
|
||||
@@ -1264,7 +675,7 @@ das Löschen, Ersetzen, Hinzufügen von Eingaben.
|
||||
|
||||
Um den Übergang zum „neuen Stil“ zu erleichtern, steht ein neuer
|
||||
Befehl @command{guix style} zur Verfügung. Führen Sie @command{info
|
||||
\"(guix.de) Aufruf von guix style\"} aus, um mehr Informationen zu
|
||||
\"(guix) Invoking guix style\"} aus, um mehr Informationen zu
|
||||
erhalten.")))
|
||||
|
||||
(entry (commit "82daab42811a2e3c7684ebdf12af75ff0fa67b99")
|
||||
|
||||
+14
-19
@@ -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.
|
||||
@@ -23,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))
|
||||
|
||||
@@ -51,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.
|
||||
@@ -111,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
|
||||
@@ -140,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"
|
||||
@@ -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 "\"))")
|
||||
|
||||
(svn-reference...
|
||||
"(svn-reference"
|
||||
n> "(url \"" p "\")"
|
||||
n> "(revision \"" p "\"))")
|
||||
|
||||
(cvs-reference...
|
||||
"(cvs-reference"
|
||||
n> "(root-directory \"" p "\")"
|
||||
n> "(module \"" p "\")"
|
||||
n> "(revision \"" p "\"))")
|
||||
|
||||
(hg-reference...
|
||||
"(hg-reference"
|
||||
n> "(url \"" p "\")"
|
||||
n> "(changeset \"" p "\"))")
|
||||
|
||||
(bzr-reference...
|
||||
"(bzr-reference"
|
||||
n> "(url \"" p "\")"
|
||||
n> "(revision \"" p "\"))")
|
||||
|
||||
(: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")")
|
||||
@@ -1,158 +0,0 @@
|
||||
-*- mode: lisp-data -*-
|
||||
|
||||
text-mode :when (and (fboundp 'git-commit-mode) (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,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
@@ -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."
|
||||
|
||||
@@ -1,624 +0,0 @@
|
||||
#!@GUILE@ \
|
||||
--no-auto-compile -s
|
||||
!#
|
||||
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2022 Ricardo Wurmus <rekado@elephly.net>
|
||||
;;; 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/>.
|
||||
|
||||
;;; 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)
|
||||
(guix ui)
|
||||
(git))
|
||||
|
||||
(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 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 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"))
|
||||
|
||||
(define-team emacs
|
||||
(team 'emacs
|
||||
#:name "Emacs team"
|
||||
#:description "The extensible, customizable text editor and its
|
||||
ecosystem."
|
||||
#:scope (list (make-regexp "^gnu/packages/emacs(-.+|)\\.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 embedded-bootstrap
|
||||
(team 'embedded-bootstrap
|
||||
#:name "Embedded / Bootstrap"))
|
||||
|
||||
(define-team rust
|
||||
(team 'rust
|
||||
#:name "Rust"
|
||||
#:scope (list (make-regexp "^gnu/packages/(crates|rust)(-.+|)\\.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 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/racket.scm")))
|
||||
|
||||
|
||||
(define-member (person "Thiago Jung Bauermann"
|
||||
"bauermann@kolabnow.com")
|
||||
embedded-bootstrap translations)
|
||||
|
||||
(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 embedded-bootstrap mentors)
|
||||
|
||||
(define-member (person "Andreas Enge"
|
||||
"andreas@enge.fr")
|
||||
science)
|
||||
|
||||
(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)
|
||||
|
||||
(define-member (person "Ricardo Wurmus"
|
||||
"rekado@elephly.net")
|
||||
r core mentors)
|
||||
|
||||
(define-member (person "Christopher Baines"
|
||||
"mail@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")
|
||||
mentors)
|
||||
|
||||
|
||||
(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."
|
||||
(format #true
|
||||
"~{--add-header=\"X-Debbugs-Cc: ~a\"~^ ~}"
|
||||
(map person-email
|
||||
(delete-duplicates (append-map team-members teams) equal?))))
|
||||
|
||||
(define* (list-members team #:optional port (prefix ""))
|
||||
"Print the members of the given TEAM."
|
||||
(define port* (or port (current-output-port)))
|
||||
(for-each
|
||||
(lambda (member)
|
||||
(format port*
|
||||
"~a~a <~a>~%"
|
||||
prefix
|
||||
(person-name member)
|
||||
(person-email member)))
|
||||
(sort
|
||||
(team-members team)
|
||||
(lambda (m1 m2) (string<? (person-name m1) (person-name m2))))))
|
||||
|
||||
(define (list-teams)
|
||||
"Print all teams, their scope and their members."
|
||||
(define port* (current-output-port))
|
||||
(define width* (%text-width))
|
||||
(for-each
|
||||
(lambda (team)
|
||||
(format port*
|
||||
"\
|
||||
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 width*
|
||||
(string-length "description: ")))))
|
||||
"<none>")
|
||||
(match (team-scope team)
|
||||
(() "")
|
||||
(scope (format #f "scope: ~{~s ~}~%" scope))))
|
||||
(list-members team port* "+ ")
|
||||
(newline))
|
||||
(sort
|
||||
(hash-map->list (lambda (key value) value) %teams)
|
||||
(lambda (team1 team2)
|
||||
(string<? (symbol->string (team-id team1))
|
||||
(symbol->string (team-id team2)))))))
|
||||
|
||||
|
||||
(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 (main . args)
|
||||
(match args
|
||||
(("cc" . team-names)
|
||||
(apply cc (map find-team team-names)))
|
||||
(("cc-members" rev-start rev-end)
|
||||
(apply cc (find-team-by-scope
|
||||
(diff-revisions rev-start rev-end))))
|
||||
(("list-teams" . args)
|
||||
(list-teams))
|
||||
(("list-members" . team-names)
|
||||
(for-each
|
||||
(lambda (team-name)
|
||||
(list-members (find-team team-name)))
|
||||
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> cc teams related to files changed between revisions
|
||||
list-teams list teams and their members
|
||||
list-members <team-name> list members belonging to <team-name>~%"))))
|
||||
|
||||
(apply main (cdr (command-line)))
|
||||
@@ -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
@@ -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
|
||||
|
||||
+35
-98
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+29
-108
@@ -7,8 +7,6 @@
|
||||
;;; 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,13 +50,10 @@
|
||||
grub-theme-color-highlight
|
||||
grub-theme-gfxmode
|
||||
|
||||
install-grub-efi-removable
|
||||
install-grub-efi-netboot
|
||||
|
||||
grub-bootloader
|
||||
grub-efi-bootloader
|
||||
grub-efi-removable-bootloader
|
||||
grub-efi32-bootloader
|
||||
grub-efi-netboot-bootloader
|
||||
grub-mkrescue-bootloader
|
||||
grub-minimal-bootloader
|
||||
@@ -374,57 +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 BTRFS-SUBVOLUME-FILE-NAME 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))
|
||||
(modules (menu-entry-multiboot-modules entry))
|
||||
(root-index 1)) ; XXX EFI will need root-index 2
|
||||
#~(format port "
|
||||
#$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 {
|
||||
multiboot ~a root=device:hd0s~a~a~a
|
||||
}~%"
|
||||
#$label
|
||||
#$kernel
|
||||
#$root-index (string-join (list #$@arguments) " " 'prefix)
|
||||
(string-join (map string-join '#$modules)
|
||||
"\n module " 'prefix))))
|
||||
(chain-loader
|
||||
#~(format port "
|
||||
menuentry ~s {
|
||||
~a
|
||||
chainloader ~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)
|
||||
@@ -626,54 +608,6 @@ 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 (install-grub-efi-netboot subdir)
|
||||
"Define a grub-efi-netboot bootloader installer for installation in SUBDIR,
|
||||
which is usually efi/Guix or efi/boot."
|
||||
@@ -800,19 +734,6 @@ considered for security aspects."
|
||||
(name 'grub-efi)
|
||||
(package grub-efi)))
|
||||
|
||||
(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 grub-efi-netboot-bootloader
|
||||
(bootloader
|
||||
(inherit grub-efi-bootloader)
|
||||
|
||||
+13
-24
@@ -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)))
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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)
|
||||
(module-ref (resolve-interface '(fibers)) 'sleep)
|
||||
(begin
|
||||
(format #f "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
-124
@@ -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 © 2019–2021 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))))))))
|
||||
|
||||
@@ -1127,7 +1058,7 @@ corresponds to the symbols listed in 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 ...)
|
||||
@@ -1136,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))))
|
||||
|
||||
@@ -1201,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)))
|
||||
|
||||
|
||||
+13
-36
@@ -5,8 +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>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
@@ -28,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)
|
||||
@@ -43,7 +40,6 @@
|
||||
convert-disk-image
|
||||
genimage
|
||||
initialize-efi-partition
|
||||
initialize-efi32-partition
|
||||
initialize-root-partition
|
||||
|
||||
make-iso9660-image))
|
||||
@@ -52,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."
|
||||
@@ -86,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
|
||||
@@ -100,18 +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))
|
||||
(if (member 'esp flags) (list "-S" "1024") '()))
|
||||
(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
|
||||
@@ -127,10 +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 "vfat")
|
||||
(make-vfat-image partition target root))
|
||||
(else
|
||||
(raise (condition
|
||||
(&message
|
||||
@@ -174,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
@@ -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
@@ -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:
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2015 David Thompson <davet@gnu.org>
|
||||
;;; Copyright © 2017-2019, 2022 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,64 +320,20 @@ 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))))))
|
||||
@@ -442,10 +378,6 @@ return the exit status."
|
||||
"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
@@ -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
-123
@@ -1,7 +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 Maxim Cournoyer <maxim.cournoyer@gmail.com>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
@@ -22,19 +21,18 @@
|
||||
#: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
|
||||
%qwerty-us-keystrokes
|
||||
marionette-type
|
||||
@@ -107,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)
|
||||
@@ -179,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))
|
||||
@@ -199,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)))
|
||||
@@ -219,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))
|
||||
@@ -278,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)
|
||||
@@ -287,87 +257,54 @@ Monitor\")."
|
||||
;; The "quit" command terminates QEMU immediately, with no output.
|
||||
(unless (string=? command "quit") (wait-for-monitor-prompt monitor)))))
|
||||
|
||||
(define* (invoke-ocrad-ocr image #:key (ocrad "ocrad"))
|
||||
"Invoke the OCRAD command on image, and return the recognized text."
|
||||
(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))
|
||||
(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-tesseract-ocr image #:key (tesseract "tesseract"))
|
||||
"Invoke the TESSERACT command on IMAGE, and return the recognized text."
|
||||
(let* ((output-basename (tmpnam))
|
||||
(output-basename* (string-append output-basename ".txt")))
|
||||
(let ((image (random-file-name)))
|
||||
(dynamic-wind
|
||||
(const #t)
|
||||
(lambda ()
|
||||
(let ((exit-val (status:exit-val
|
||||
(system* tesseract image output-basename))))
|
||||
(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"))
|
||||
"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) image))
|
||||
((string-contains ocr "tesseract")
|
||||
(values (invoke-tesseract-ocr image #:tesseract ocr) 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")
|
||||
(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))
|
||||
(_ (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.
|
||||
@@ -389,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")
|
||||
|
||||
@@ -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) ;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
@@ -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)
|
||||
|
||||
+85
-41
@@ -1,5 +1,5 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2012-2022 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,16 +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 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)
|
||||
@@ -39,10 +41,9 @@
|
||||
#: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)
|
||||
@@ -54,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)
|
||||
@@ -71,6 +71,8 @@
|
||||
image->job
|
||||
|
||||
%core-packages
|
||||
%cross-targets
|
||||
channel-source->package
|
||||
|
||||
arguments->systems
|
||||
cuirass-jobs))
|
||||
@@ -167,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)
|
||||
@@ -208,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."
|
||||
@@ -251,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)
|
||||
@@ -531,9 +577,7 @@ names."
|
||||
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
|
||||
|
||||
@@ -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)))
|
||||
+3
-25
@@ -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,8 +27,7 @@
|
||||
#: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
|
||||
@@ -40,9 +38,7 @@
|
||||
home-environment-services
|
||||
home-environment-location
|
||||
|
||||
home-environment-with-provenance
|
||||
|
||||
home-generation-base))
|
||||
home-environment-with-provenance))
|
||||
|
||||
;;; Comment:
|
||||
;;;
|
||||
@@ -96,7 +92,7 @@
|
||||
(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)))
|
||||
@@ -118,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)))))
|
||||
|
||||
+26
-93
@@ -20,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)
|
||||
@@ -34,26 +33,21 @@
|
||||
#:use-module (guix modules)
|
||||
#:use-module (srfi srfi-1)
|
||||
#: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
|
||||
|
||||
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
|
||||
|
||||
%initialize-gettext)
|
||||
@@ -171,34 +165,6 @@ packages, configuration files, activation script, and so on.")))
|
||||
configuration files that the user has declared in their
|
||||
@code{home-environment} record.")))
|
||||
|
||||
(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."
|
||||
#~(let ((shell-quote
|
||||
(lambda (value)
|
||||
;; Double-quote VALUE, leaving dollar sign as is.
|
||||
(let ((quoted (list->string
|
||||
(string-fold-right
|
||||
(lambda (chr lst)
|
||||
(case chr
|
||||
((#\" #\\)
|
||||
(append (list chr #\\) lst))
|
||||
(else (cons chr lst))))
|
||||
'()
|
||||
value))))
|
||||
(string-append "\"" quoted "\"")))))
|
||||
(string-append
|
||||
#$@(map (match-lambda
|
||||
((key . #f)
|
||||
"")
|
||||
((key . #t)
|
||||
#~(string-append "export " #$key "\n"))
|
||||
((key . value)
|
||||
#~(string-append "export " #$key "="
|
||||
(shell-quote #$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
|
||||
@@ -211,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))
|
||||
@@ -222,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\"
|
||||
@@ -260,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)
|
||||
@@ -315,10 +285,10 @@ directory containing FILES."
|
||||
(description "Files that will be put in
|
||||
@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)
|
||||
@@ -326,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)))
|
||||
@@ -334,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
|
||||
@@ -368,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")
|
||||
@@ -389,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'"))))))))
|
||||
@@ -420,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))
|
||||
@@ -430,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 #\=)))
|
||||
@@ -637,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)))))
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2022 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2022 ( <paren@disroot.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
@@ -21,7 +20,6 @@
|
||||
#: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)
|
||||
#:use-module (guix records)
|
||||
#:use-module (guix gexp)
|
||||
@@ -29,10 +27,8 @@
|
||||
#:use-module (ice-9 match)
|
||||
#:export (home-redshift-configuration
|
||||
home-redshift-configuration?
|
||||
home-redshift-service-type
|
||||
|
||||
home-dbus-configuration
|
||||
home-dbus-service-type))
|
||||
home-redshift-service-type))
|
||||
|
||||
|
||||
;;;
|
||||
@@ -95,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.")
|
||||
|
||||
@@ -165,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
|
||||
@@ -177,52 +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/dbus.log"
|
||||
(or (getenv "XDG_LOG_HOME")
|
||||
(format #f "~a/.local/var/log"
|
||||
(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.")))
|
||||
|
||||
@@ -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.")))
|
||||
+33
-58
@@ -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 © 2022 Maxim Cournoyer <maxim.cournoyer@gmail.com>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
@@ -21,7 +20,6 @@
|
||||
(define-module (gnu home services mcron)
|
||||
#:use-module (gnu packages guile-xyz)
|
||||
#:use-module (gnu home services)
|
||||
#:use-module (gnu services configuration)
|
||||
#:use-module (gnu services shepherd)
|
||||
#:use-module (gnu home services shepherd)
|
||||
#:use-module (guix records)
|
||||
@@ -55,59 +53,45 @@
|
||||
;;
|
||||
;;; Code:
|
||||
|
||||
(define list-of-gexps?
|
||||
(list-of gexp?))
|
||||
|
||||
(define-configuration/no-serialization home-mcron-configuration
|
||||
(mcron (file-like mcron) "The mcron package to use.")
|
||||
(jobs
|
||||
(list-of-gexps '())
|
||||
"This is a list of gexps (@pxref{G-Expressions}), where each gexp
|
||||
corresponds to an mcron job specification (@pxref{Syntax, mcron job
|
||||
specifications,, mcron, GNU@tie{}mcron}).")
|
||||
(log? (boolean #t) "Log messages to standard output.")
|
||||
(log-format
|
||||
(string "~1@*~a ~a: ~a~%")
|
||||
"@code{(ice-9 format)} format string for log messages. The default value
|
||||
produces messages like \"@samp{@var{pid} @var{name}:
|
||||
@var{message}\"} (@pxref{Invoking mcron, Invoking,, mcron, GNU@tie{}mcron}).
|
||||
Each message is also prefixed by a timestamp by GNU Shepherd."))
|
||||
(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 config)
|
||||
(match-record config <home-mcron-configuration>
|
||||
(mcron jobs log? log-format)
|
||||
(if (null? jobs)
|
||||
'() ;no jobs to run
|
||||
(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 (string-append #$mcron "/bin/mcron")
|
||||
#$@(if log?
|
||||
#~("--log" "--log-format" #$log-format)
|
||||
#~())
|
||||
#$@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-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-mcron))
|
||||
(define home-mcron-profile (compose list home-mcron-configuration-package))
|
||||
|
||||
(define (home-mcron-extend config jobs)
|
||||
(home-mcron-configuration
|
||||
@@ -129,12 +113,3 @@ Each message is also prefixed by a timestamp by GNU Shepherd."))
|
||||
(default-value (home-mcron-configuration))
|
||||
(description
|
||||
"Install and configure the GNU mcron cron job manager.")))
|
||||
|
||||
|
||||
;;;
|
||||
;;; Generate documentation.
|
||||
;;;
|
||||
(define (generate-doc)
|
||||
(configuration->documentation 'home-mcron-configuration))
|
||||
|
||||
;;; mcron.scm ends here
|
||||
|
||||
@@ -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_LOG_HOME")
|
||||
(format #f "~a/.local/var/log"
|
||||
(getenv "HOME")))
|
||||
"/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.")))
|
||||
@@ -25,7 +25,6 @@
|
||||
#: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)
|
||||
@@ -78,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"
|
||||
"\
|
||||
@@ -112,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)))
|
||||
|
||||
|
||||
;;;
|
||||
@@ -184,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
|
||||
@@ -203,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"
|
||||
@@ -222,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))
|
||||
'()))
|
||||
@@ -290,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)))
|
||||
@@ -422,7 +430,7 @@ alias grep='grep --color=auto'\n")
|
||||
(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 '())
|
||||
@@ -431,13 +439,13 @@ alias grep='grep --color=auto'\n")
|
||||
|
||||
(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
|
||||
@@ -480,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)
|
||||
@@ -546,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
|
||||
@@ -577,7 +586,7 @@ when typed in the shell, will automatically expand to the full text."
|
||||
serialize-fish-abbreviations))
|
||||
|
||||
(define (fish-files-service config)
|
||||
`(("fish/config.fish"
|
||||
`(("config/fish/config.fish"
|
||||
,(mixed-text-file
|
||||
"fish-config.fish"
|
||||
#~(string-append "\
|
||||
@@ -641,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
|
||||
|
||||
@@ -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.9)) ; 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,53 +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 ((log-dir (or (getenv "XDG_LOG_HOME")
|
||||
(format #f "~a/.local/var/log"
|
||||
(getenv "HOME")))))
|
||||
;; 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?
|
||||
@@ -137,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-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)
|
||||
|
||||
@@ -1,256 +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/>.
|
||||
|
||||
(define-module (gnu home services ssh)
|
||||
#:use-module (guix gexp)
|
||||
#:use-module (guix records)
|
||||
#: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 utils)
|
||||
#:select (object->camel-case-string))
|
||||
#:autoload (gnu packages base) (glibc-utf8-locales)
|
||||
#:use-module (srfi srfi-1)
|
||||
#:use-module (srfi srfi-34)
|
||||
#:use-module (srfi srfi-35)
|
||||
#:use-module (ice-9 match)
|
||||
#:export (home-openssh-configuration
|
||||
home-openssh-configuration-authorized-keys
|
||||
home-openssh-configuration-known-hosts
|
||||
home-openssh-configuration-hosts
|
||||
|
||||
openssh-host
|
||||
openssh-host-host-name
|
||||
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
|
||||
|
||||
home-openssh-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 (condition (&error)))))
|
||||
"\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 (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-configuration openssh-host
|
||||
(name
|
||||
(string)
|
||||
"Name of this host declaration.")
|
||||
(host-name
|
||||
maybe-string
|
||||
"Host name---e.g., @code{\"foo.example.org\"} or @code{\"192.168.1.2\"}.")
|
||||
(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?
|
||||
(boolean #f)
|
||||
"Whether to forward remote client connections to the local X11 graphical
|
||||
display.")
|
||||
(forward-x11-trusted?
|
||||
(boolean #f)
|
||||
"Whether remote X11 clients have full access to the original X11 graphical
|
||||
display.")
|
||||
(forward-agent?
|
||||
(boolean #f)
|
||||
"Whether the authentication agent (if any) is forwarded to the remote
|
||||
machine.")
|
||||
(compression?
|
||||
(boolean #f)
|
||||
"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\"}.")
|
||||
(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-field? field)
|
||||
(eq? (configuration-field-name field) 'name))
|
||||
|
||||
(string-append
|
||||
"Host " (openssh-host-name config) "\n"
|
||||
(string-concatenate
|
||||
(map (lambda (field)
|
||||
((configuration-field-serializer field)
|
||||
(configuration-field-name field)
|
||||
((configuration-field-getter field) config)))
|
||||
(remove openssh-host-name-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 '()))
|
||||
(known-hosts home-openssh-configuration-known-hosts ;unspec | list of file-like
|
||||
(default *unspecified*))
|
||||
(hosts home-openssh-configuration-hosts ;list of <openssh-host>
|
||||
(default '())))
|
||||
|
||||
(define (openssh-configuration->string config)
|
||||
(string-join (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 ((config (plain-file "ssh.conf"
|
||||
(openssh-configuration->string config)))
|
||||
(known-hosts (home-openssh-configuration-known-hosts config))
|
||||
(authorized-keys (file-join
|
||||
"authorized_keys"
|
||||
(home-openssh-configuration-authorized-keys config)
|
||||
"\n")))
|
||||
`((".ssh/authorized_keys" ,authorized-keys)
|
||||
,@(if (unspecified? known-hosts)
|
||||
'()
|
||||
`((".ssh/known_hosts"
|
||||
,(file-join "known_hosts" known-hosts "\n"))))
|
||||
(".ssh/config" ,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))))
|
||||
@@ -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)))
|
||||
|
||||
|
||||
+29
-37
@@ -23,7 +23,6 @@
|
||||
#:use-module (gnu packages freedesktop)
|
||||
#:use-module (gnu home services utils)
|
||||
#:use-module (guix gexp)
|
||||
#:use-module (guix modules)
|
||||
#:use-module (guix records)
|
||||
#:use-module (guix i18n)
|
||||
#:use-module (guix diagnostics)
|
||||
@@ -107,21 +106,15 @@ services more consistent."))
|
||||
|
||||
(define (ensure-xdg-base-dirs-on-activation config)
|
||||
#~(map (lambda (xdg-base-dir-variable)
|
||||
((@ (guix build utils) mkdir-p)
|
||||
((@@ (guix build utils) 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)))
|
||||
home-xdg-base-directories-configuration-fields)))
|
||||
'#$(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
|
||||
@@ -214,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)
|
||||
@@ -383,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
|
||||
@@ -428,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))))
|
||||
@@ -476,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
@@ -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)))
|
||||
|
||||
+7
-54
@@ -1,6 +1,6 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2018, 2020 Mathieu Othacehe <m.othacehe@gmail.com>
|
||||
;;; Copyright © 2019, 2020, 2022 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2019, 2020 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2019, 2020 Tobias Geerinckx-Rice <me@tobias.gr>
|
||||
;;; Copyright © 2020 Florian Pelz <pelzflorian@pelzflorian.de>
|
||||
;;;
|
||||
@@ -27,8 +27,6 @@
|
||||
#:use-module (guix utils)
|
||||
#:use-module (guix ui)
|
||||
#:use-module ((guix self) #:select (make-config.scm))
|
||||
#:use-module (guix describe)
|
||||
#:use-module (guix channels)
|
||||
#:use-module (guix packages)
|
||||
#:use-module (guix git-download)
|
||||
#:use-module (gnu installer utils)
|
||||
@@ -48,13 +46,11 @@
|
||||
#:use-module (gnu packages nano)
|
||||
#:use-module (gnu packages ncurses)
|
||||
#:use-module (gnu packages package-management)
|
||||
#:use-module (gnu packages pciutils)
|
||||
#:use-module (gnu packages tls)
|
||||
#:use-module (gnu packages xorg)
|
||||
#:use-module (gnu system locale)
|
||||
#:use-module (ice-9 match)
|
||||
#:use-module (srfi srfi-1)
|
||||
#:use-module (web uri)
|
||||
#:export (installer-program))
|
||||
|
||||
(define module-to-import?
|
||||
@@ -67,7 +63,6 @@
|
||||
(('gnu 'installer _ ...) #t)
|
||||
(('gnu 'build _ ...) #t)
|
||||
(('guix 'build _ ...) #t)
|
||||
(('guix 'read-print) #t)
|
||||
(_ #f)))
|
||||
|
||||
(define not-config?
|
||||
@@ -230,9 +225,7 @@ selected keymap."
|
||||
(id 'welcome)
|
||||
(compute (lambda _
|
||||
((installer-welcome-page current-installer)
|
||||
#$(local-file "installer/aux-files/logo.txt")
|
||||
#:pci-database
|
||||
#$(file-append pciutils "/share/hwdata/pci.ids.gz")))))
|
||||
#$(local-file "installer/aux-files/logo.txt")))))
|
||||
|
||||
;; Ask the user to select a timezone under glibc format.
|
||||
(installer-step
|
||||
@@ -318,25 +311,6 @@ selected keymap."
|
||||
((installer-final-page current-installer)
|
||||
result prev-steps))))))))
|
||||
|
||||
(define (provenance-sexp)
|
||||
"Return an sexp representing the currently-used channels, for logging
|
||||
purposes."
|
||||
(match (match (current-channels)
|
||||
(() (and=> (repository->guix-channel (dirname (current-filename)))
|
||||
list))
|
||||
(channels channels))
|
||||
(#f
|
||||
(warning (G_ "cannot determine installer provenance~%"))
|
||||
'unknown)
|
||||
((channels ...)
|
||||
(map (lambda (channel)
|
||||
(let* ((uri (string->uri (channel-url channel)))
|
||||
(url (if (or (not uri) (eq? 'file (uri-scheme uri)))
|
||||
"local checkout"
|
||||
(channel-url channel))))
|
||||
`(channel ,(channel-name channel) ,url ,(channel-commit channel))))
|
||||
channels))))
|
||||
|
||||
(define (installer-program)
|
||||
"Return a file-like object that runs the given INSTALLER."
|
||||
(define init-gettext
|
||||
@@ -383,9 +357,7 @@ purposes."
|
||||
(with-extensions (list guile-gcrypt guile-newt
|
||||
guile-parted guile-bytestructures
|
||||
guile-json-3 guile-git guile-webutils
|
||||
guile-gnutls
|
||||
guile-zlib ;for (gnu build linux-modules)
|
||||
(current-guix))
|
||||
guix gnutls)
|
||||
(with-imported-modules `(,@(source-module-closure
|
||||
`(,@modules
|
||||
(gnu services herd)
|
||||
@@ -416,12 +388,6 @@ purposes."
|
||||
(ice-9 match)
|
||||
(ice-9 textual-ports))
|
||||
|
||||
;; Enable core dump generation.
|
||||
(setrlimit 'core #f #f)
|
||||
(call-with-output-file "/proc/sys/kernel/core_pattern"
|
||||
(lambda (port)
|
||||
(format port %core-dump)))
|
||||
|
||||
;; Initialize gettext support so that installers can use
|
||||
;; (guix i18n) module.
|
||||
#$init-gettext
|
||||
@@ -451,9 +417,6 @@ purposes."
|
||||
(define current-installer newt-installer)
|
||||
(define steps (#$steps current-installer))
|
||||
|
||||
(installer-log-line "installer provenance: ~s"
|
||||
'#$(provenance-sexp))
|
||||
|
||||
(dynamic-wind
|
||||
(installer-init current-installer)
|
||||
(lambda ()
|
||||
@@ -483,21 +446,11 @@ purposes."
|
||||
key args)
|
||||
(define dump-dir
|
||||
(prepare-dump key args #:result %current-result))
|
||||
|
||||
(define user-abort?
|
||||
(match args
|
||||
(((? user-abort-error? obj)) #t)
|
||||
(_ #f)))
|
||||
|
||||
(define action
|
||||
(if user-abort?
|
||||
'dump
|
||||
((installer-exit-error current-installer)
|
||||
(get-string-all
|
||||
(open-input-file
|
||||
(string-append dump-dir
|
||||
"/installer-backtrace"))))))
|
||||
|
||||
((installer-exit-error current-installer)
|
||||
(get-string-all
|
||||
(open-input-file
|
||||
(string-append dump-dir "/installer-backtrace")))))
|
||||
(match action
|
||||
('dump
|
||||
(let* ((dump-files
|
||||
|
||||
@@ -28,17 +28,13 @@
|
||||
#:use-module (web http)
|
||||
#:use-module (web response)
|
||||
#:use-module (webutils multipart)
|
||||
#:export (%core-dump
|
||||
prepare-dump
|
||||
#:export (prepare-dump
|
||||
make-dump
|
||||
send-dump-report))
|
||||
|
||||
;; The installer crash dump type.
|
||||
(define %dump-type "installer-dump")
|
||||
|
||||
;; The core dump file.
|
||||
(define %core-dump "/tmp/installer-core-dump")
|
||||
|
||||
(define (result->list result)
|
||||
"Return the alist for the given RESULT."
|
||||
(hash-map->list (lambda (k v)
|
||||
@@ -70,10 +66,6 @@ RESULT is the installer result hash table. Returns the created directory path."
|
||||
;; syslog
|
||||
(copy-file "/var/log/messages" "syslog")
|
||||
|
||||
;; core dump
|
||||
(when (file-exists? %core-dump)
|
||||
(copy-file %core-dump "core-dump"))
|
||||
|
||||
;; dmesg
|
||||
(let ((pipe (open-pipe* OPEN_READ "dmesg")))
|
||||
(call-with-output-file "dmesg"
|
||||
|
||||
+7
-25
@@ -1,6 +1,6 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2018, 2020 Mathieu Othacehe <m.othacehe@gmail.com>
|
||||
;;; Copyright © 2019, 2020, 2022 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2019, 2020 Ludovic Courtès <ludo@gnu.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
@@ -114,8 +114,6 @@ it can interact with the rest of the system."
|
||||
;; Catch SIGINT and kill the container process.
|
||||
(sigaction SIGINT
|
||||
(lambda (signum)
|
||||
;: FIXME: Use of SIGKILL prevents the dynamic-wind exit handler of
|
||||
;; THUNK to run.
|
||||
(false-if-exception
|
||||
(kill pid SIGKILL))))
|
||||
|
||||
@@ -198,16 +196,14 @@ or #f. Return #t on success and #f on failure."
|
||||
;; the loaded cow-store locale files will prevent umounting.
|
||||
(install-locale locale)
|
||||
|
||||
;; Stop the daemon and save the database, so that it can be
|
||||
;; restored once the cow-store is umounted.
|
||||
(stop-service 'guix-daemon)
|
||||
;; Save the database, so that it can be restored once the
|
||||
;; cow-store is umounted.
|
||||
(copy-file database-file saved-database)
|
||||
|
||||
(installer-log-line "mounting copy-on-write store")
|
||||
(mount-cow-store (%installer-target-dir) backing-directory))
|
||||
(lambda ()
|
||||
;; We need to drag the guix-daemon to the container MNT
|
||||
;; namespace, so that it can operate on the cow-store.
|
||||
(stop-service 'guix-daemon)
|
||||
(start-service 'guix-daemon (list (number->string (getpid))))
|
||||
|
||||
(setvbuf (current-output-port) 'none)
|
||||
@@ -215,27 +211,13 @@ or #f. Return #t on success and #f on failure."
|
||||
|
||||
(setenv "PATH" "/run/current-system/profile/bin/")
|
||||
|
||||
(set! ret (run-command install-command #:tty? #t)))
|
||||
(set! ret (run-command install-command)))
|
||||
(lambda ()
|
||||
;; Stop guix-daemon so that it does no keep the MNT namespace
|
||||
;; Restart guix-daemon so that it does no keep the MNT namespace
|
||||
;; alive.
|
||||
(stop-service 'guix-daemon)
|
||||
|
||||
;; Restore the database and restart it. As part of restoring the
|
||||
;; database, remove the WAL and shm files in case they were left
|
||||
;; behind after guix-daemon was stopped. Failing to do so,
|
||||
;; sqlite might behave as if transactions that appear in the WAL
|
||||
;; file were committed. (See <https://www.sqlite.org/wal.html>.)
|
||||
(installer-log-line "restoring store database from '~a'"
|
||||
saved-database)
|
||||
(restart-service 'guix-daemon)
|
||||
(copy-file saved-database database-file)
|
||||
(for-each (lambda (suffix)
|
||||
(false-if-exception
|
||||
(delete-file (string-append database-file suffix))))
|
||||
'("-wal" "-shm"))
|
||||
(start-service 'guix-daemon)
|
||||
|
||||
;; Finally umount the cow-store and exit the container.
|
||||
(installer-log-line "unmounting copy-on-write store")
|
||||
(unmount-cow-store (%installer-target-dir) backing-directory)
|
||||
(assert-exit ret))))))))
|
||||
|
||||
@@ -1,90 +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
|
||||
;;;
|
||||
;;; 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 installer hardware)
|
||||
#:use-module (gnu build linux-modules)
|
||||
#:use-module (guix i18n)
|
||||
#:use-module (srfi srfi-1)
|
||||
#:use-module (srfi srfi-71)
|
||||
#:export (unsupported-pci-device?
|
||||
pci-device-description))
|
||||
|
||||
(define %unsupported-linux-modules
|
||||
;; List of Linux modules that are useless without non-free firmware.
|
||||
;;
|
||||
;; Currently only drivers for PCI devices are listed. USB devices such as
|
||||
;; "btintel" would require support to list USB devices and read the USB
|
||||
;; device ID database. Punt for now as this is usually less critical.
|
||||
;;
|
||||
;; This list is currently manually maintained based on information on
|
||||
;; non-free firmware available from
|
||||
;; <https://packages.debian.org/search?keywords=firmware&searchon=names&suite=stable§ion=all>.
|
||||
'(;; WiFi.
|
||||
"brcmfmac"
|
||||
"ipw2100"
|
||||
"ipw2200"
|
||||
"iwlwifi"
|
||||
"mwl8k"
|
||||
"rtl8188ee"
|
||||
"rtl818x_pci"
|
||||
"rtl8192ce"
|
||||
"rtl8192de"
|
||||
"rtl8192ee"
|
||||
|
||||
;; Ethernet.
|
||||
"bnx2"
|
||||
"bnx2x"
|
||||
"liquidio"
|
||||
|
||||
;; Graphics.
|
||||
"amdgpu"
|
||||
"radeon"
|
||||
|
||||
;; Multimedia.
|
||||
"ivtv"))
|
||||
|
||||
(define unsupported-pci-device?
|
||||
;; Arrange to load the module alias database only once.
|
||||
(let ((aliases (delay (known-module-aliases))))
|
||||
(lambda (device)
|
||||
"Return true if DEVICE is known to not be supported by free software."
|
||||
(any (lambda (module)
|
||||
(member module %unsupported-linux-modules))
|
||||
(matching-modules (pci-device-module-alias device)
|
||||
(force aliases))))))
|
||||
|
||||
(define (pci-device-description pci-database)
|
||||
"Return a procedure that, given a PCI device, returns a string describing
|
||||
it."
|
||||
(define (with-fallback lookup)
|
||||
(lambda (vendor-id id)
|
||||
(let ((vendor name (lookup vendor-id id)))
|
||||
(values (or vendor (number->string vendor-id 16))
|
||||
(or name (number->string id 16))))))
|
||||
|
||||
(define pci-lookup
|
||||
(with-fallback (load-pci-device-database pci-database)))
|
||||
|
||||
(lambda (device)
|
||||
(let ((vendor name (pci-lookup (pci-device-vendor device)
|
||||
(pci-device-id device))))
|
||||
(if (network-pci-device? device)
|
||||
;; TRANSLATORS: The two placeholders are the manufacturer
|
||||
;; and name of a PCI device.
|
||||
(format #f (G_ "~a ~a (networking device)")
|
||||
vendor name)
|
||||
(string-append vendor " " name)))))
|
||||
@@ -62,9 +62,6 @@
|
||||
(clear-screen))
|
||||
|
||||
(define (exit-error error)
|
||||
;; Newt may be suspended in the context of the "install-system"
|
||||
;; procedure. Resume it unconditionnally.
|
||||
(newt-resume)
|
||||
(newt-set-color COLORSET-ROOT "white" "red")
|
||||
(define action
|
||||
(run-textbox-page
|
||||
@@ -116,7 +113,11 @@ report it by email to ~a.") uploaded-name %guix-bug-report-address)
|
||||
(define command-output "")
|
||||
(define (line-accumulator line)
|
||||
(set! command-output
|
||||
(string-append/shared command-output line)))
|
||||
(string-append/shared command-output line "\n")))
|
||||
(define displayed-command
|
||||
(string-join
|
||||
(map (lambda (s) (string-append "\"" s "\"")) args)
|
||||
" "))
|
||||
(define result (run-external-command-with-line-hooks (list line-accumulator)
|
||||
args))
|
||||
(define exit-val (status:exit-val result))
|
||||
@@ -172,8 +173,8 @@ report it by email to ~a.") uploaded-name %guix-bug-report-address)
|
||||
(define (timezone-page zonetab)
|
||||
(run-timezone-page zonetab))
|
||||
|
||||
(define* (welcome-page logo #:key pci-database)
|
||||
(run-welcome-page logo #:pci-database pci-database))
|
||||
(define (welcome-page logo)
|
||||
(run-welcome-page logo))
|
||||
|
||||
(define (menu-page steps)
|
||||
(run-menu-page steps))
|
||||
|
||||
@@ -80,20 +80,16 @@ press the button to reboot.")))
|
||||
(define (run-install-failed-page)
|
||||
(match (current-clients)
|
||||
(()
|
||||
(match (ternary-window
|
||||
(match (choice-window
|
||||
(G_ "Installation failed")
|
||||
(G_ "Resume")
|
||||
(G_ "Restart the installer")
|
||||
(G_ "Report the failure")
|
||||
(G_ "The final system installation step failed. You can resume from \
|
||||
a specific step, or restart the installer."))
|
||||
(1 (abort-to-prompt 'installer-step 'abort))
|
||||
(2
|
||||
;; Keep going, the installer will be restarted later on.
|
||||
#t)
|
||||
(3 (raise
|
||||
(condition
|
||||
(&user-abort-error))))))
|
||||
#t)))
|
||||
(_
|
||||
(send-to-clients '(installation-failure))
|
||||
#t)))
|
||||
|
||||
@@ -115,11 +115,6 @@ network devices were found. Do you want to continue anyway?"))
|
||||
(define (wait-service-online)
|
||||
"Display a newt scale until connman detects an Internet access. Do
|
||||
FULL-VALUE tentatives, spaced by 1 second."
|
||||
(define (url-alive? url)
|
||||
(false-if-exception
|
||||
(= (response-code (http-request url))
|
||||
200)))
|
||||
|
||||
(define (ci-available?)
|
||||
(dynamic-wind
|
||||
(lambda ()
|
||||
@@ -127,8 +122,10 @@ FULL-VALUE tentatives, spaced by 1 second."
|
||||
(lambda _ #f))
|
||||
(alarm 3))
|
||||
(lambda ()
|
||||
(or (url-alive? "https://ci.guix.gnu.org")
|
||||
(url-alive? "https://bordeaux.guix.gnu.org")))
|
||||
(false-if-exception
|
||||
(= (response-code
|
||||
(http-request "https://ci.guix.gnu.org"))
|
||||
200)))
|
||||
(lambda ()
|
||||
(alarm 0))))
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2018 Mathieu Othacehe <m.othacehe@gmail.com>
|
||||
;;; Copyright © 2019, 2020, 2022 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2019, 2020 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2019 Tobias Geerinckx-Rice <me@tobias.gr>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
@@ -278,12 +278,12 @@ input box, such as FLAG-PASSWORD."
|
||||
(destroy-form-and-pop form)
|
||||
input))))))))
|
||||
|
||||
(define* (run-error-page text title #:key (width 40))
|
||||
"Run a page to inform the user of an error. The page is WIDTH column wide
|
||||
and contains the given TEXT to explain the error and an \"OK\" button to
|
||||
acknowledge the error. The title of the page is set to TITLE."
|
||||
(define (run-error-page text title)
|
||||
"Run a page to inform the user of an error. The page contains the given TEXT
|
||||
to explain the error and an \"OK\" button to acknowledge the error. The title
|
||||
of the page is set to TITLE."
|
||||
(let* ((text-box
|
||||
(make-reflowed-textbox -1 -1 text width
|
||||
(make-reflowed-textbox -1 -1 text 40
|
||||
#:flags FLAG-BORDER))
|
||||
(grid (make-grid 1 2))
|
||||
(ok-button (make-button -1 -1 "OK"))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2018, 2019, 2022 Mathieu Othacehe <m.othacehe@gmail.com>
|
||||
;;; Copyright © 2018, 2019 Mathieu Othacehe <m.othacehe@gmail.com>
|
||||
;;; Copyright © 2019, 2020 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2020 Tobias Geerinckx-Rice <me@tobias.gr>
|
||||
;;;
|
||||
@@ -92,31 +92,17 @@ disk. The installation device as well as the small devices are filtered.")
|
||||
(device (car result)))
|
||||
device))
|
||||
|
||||
(define (run-label-confirmation-page callback)
|
||||
(lambda (item)
|
||||
(match (current-clients)
|
||||
(()
|
||||
(and (run-confirmation-page
|
||||
(format #f (G_ "This will create a new ~a partition table, \
|
||||
all data on disk will be lost, are you sure you want to proceed?") item)
|
||||
(G_ "Format disk?")
|
||||
#:exit-button-procedure callback)
|
||||
item))
|
||||
(_ item))))
|
||||
|
||||
(define (run-label-page button-text button-callback)
|
||||
"Run a page asking the user to select a partition table label."
|
||||
;; Force the GPT label if UEFI is supported.
|
||||
(if (efi-installation?)
|
||||
((run-label-confirmation-page button-callback) "gpt")
|
||||
"gpt"
|
||||
(run-listbox-selection-page
|
||||
#:info-text (G_ "Select a new partition table type. \
|
||||
Be careful, all data on the disk will be lost.")
|
||||
#:title (G_ "Partition table")
|
||||
#:listbox-items '("msdos" "gpt")
|
||||
#:listbox-item->text identity
|
||||
#:listbox-callback-procedure
|
||||
(run-label-confirmation-page button-callback)
|
||||
#:button-text button-text
|
||||
#:button-callback-procedure button-callback)))
|
||||
|
||||
@@ -202,7 +188,7 @@ encryption of partition ~a (label: ~a).") file-name crypt-label)
|
||||
(if (string=? password confirmation)
|
||||
(user-partition
|
||||
(inherit user-part)
|
||||
(crypt-password (make-secret password)))
|
||||
(crypt-password password))
|
||||
(begin
|
||||
(run-error-page
|
||||
(G_ "Password mismatch, please try again.")
|
||||
@@ -809,13 +795,13 @@ by pressing the Exit button.~%~%")))
|
||||
(user-partitions (run-page eligible-devices))
|
||||
(user-partitions-with-pass (prompt-luks-passwords
|
||||
user-partitions))
|
||||
(form (draw-formatting-page user-partitions-with-pass)))
|
||||
(form (draw-formatting-page user-partitions)))
|
||||
;; Make sure the disks are not in use before proceeding to formatting.
|
||||
(free-parted eligible-devices)
|
||||
(format-user-partitions user-partitions-with-pass)
|
||||
(installer-log-line "formatted ~a user partitions"
|
||||
(length user-partitions-with-pass))
|
||||
(installer-log-line "user-partitions: ~a" user-partitions-with-pass)
|
||||
(installer-log-line "user-partitions: ~a" user-partitions)
|
||||
|
||||
(destroy-form-and-pop form)
|
||||
user-partitions-with-pass))
|
||||
user-partitions))
|
||||
|
||||
@@ -99,8 +99,10 @@ non-graphical system.")
|
||||
#:item->text (compose G_ system-service-name)
|
||||
#:checkbox-tree-height 5
|
||||
#:exit-button-callback-procedure
|
||||
(lambda _
|
||||
(abort-to-prompt 'installer-step 'abort)))))
|
||||
(lambda ()
|
||||
(raise
|
||||
(condition
|
||||
(&installer-step-abort)))))))
|
||||
|
||||
(define (run-network-management-page)
|
||||
"Run a page to select among several network management methods."
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
(match (current-clients)
|
||||
(()
|
||||
(case (choice-window
|
||||
(G_ "Substitute server discovery")
|
||||
(G_ "Substitute server discovery.")
|
||||
(G_ "Enable") (G_ "Disable")
|
||||
(G_ " By turning this option on, you allow Guix to fetch \
|
||||
substitutes (pre-built binaries) during installation from servers \
|
||||
|
||||
+18
-31
@@ -40,9 +40,6 @@ REAL-NAME, and HOME-DIRECTORY as the initial values in the form."
|
||||
(define (pad-label label)
|
||||
(string-pad-right label 25))
|
||||
|
||||
(define (root-account? name)
|
||||
(string=? name "root"))
|
||||
|
||||
(let* ((label-name
|
||||
(make-label -1 -1 (pad-label (G_ "Name"))))
|
||||
(label-real-name
|
||||
@@ -119,14 +116,10 @@ REAL-NAME, and HOME-DIRECTORY as the initial values in the form."
|
||||
GRID-ELEMENT-SUBGRID button-grid)
|
||||
title)
|
||||
|
||||
(let ((error-empty-field-page
|
||||
(let ((error-page
|
||||
(lambda ()
|
||||
(run-error-page (G_ "Empty inputs are not allowed.")
|
||||
(G_ "Empty input"))))
|
||||
(error-root-page
|
||||
(lambda ()
|
||||
(run-error-page (G_ "Root account is automatically created.")
|
||||
(G_ "Root account")))))
|
||||
(G_ "Empty input")))))
|
||||
(receive (exit-reason argument)
|
||||
(run-form form)
|
||||
(dynamic-wind
|
||||
@@ -139,28 +132,22 @@ REAL-NAME, and HOME-DIRECTORY as the initial values in the form."
|
||||
(real-name (entry-value entry-real-name))
|
||||
(home-directory (entry-value entry-home-directory))
|
||||
(password (entry-value entry-password)))
|
||||
(cond
|
||||
;; Empty field.
|
||||
((or (string=? name "")
|
||||
(string=? home-directory ""))
|
||||
(error-empty-field-page)
|
||||
(run-user-add-page))
|
||||
;; Reject root account.
|
||||
((root-account? name)
|
||||
(error-root-page)
|
||||
(run-user-add-page))
|
||||
(else
|
||||
(let ((password (confirm-password password)))
|
||||
(if password
|
||||
(user
|
||||
(name name)
|
||||
(real-name real-name)
|
||||
(home-directory home-directory)
|
||||
(password (make-secret password)))
|
||||
(run-user-add-page #:name name
|
||||
#:real-name real-name
|
||||
#:home-directory
|
||||
home-directory))))))))))
|
||||
(if (or (string=? name "")
|
||||
(string=? home-directory ""))
|
||||
(begin
|
||||
(error-page)
|
||||
(run-user-add-page))
|
||||
(let ((password (confirm-password password)))
|
||||
(if password
|
||||
(user
|
||||
(name name)
|
||||
(real-name real-name)
|
||||
(home-directory home-directory)
|
||||
(password (make-secret password)))
|
||||
(run-user-add-page #:name name
|
||||
#:real-name real-name
|
||||
#:home-directory
|
||||
home-directory)))))))))
|
||||
(lambda ()
|
||||
(destroy-form-and-pop form)))))))
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2018 Mathieu Othacehe <m.othacehe@gmail.com>
|
||||
;;; Copyright © 2020, 2022 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2022 Florian Pelz <pelzflorian@pelzflorian.de>
|
||||
;;; Copyright © 2020 Ludovic Courtès <ludo@gnu.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
@@ -18,11 +17,6 @@
|
||||
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
(define-module (gnu installer newt welcome)
|
||||
#:use-module ((gnu build linux-modules)
|
||||
#:select (modules-loaded
|
||||
pci-devices))
|
||||
#:use-module (gnu installer dump)
|
||||
#:use-module (gnu installer hardware)
|
||||
#:use-module (gnu installer steps)
|
||||
#:use-module (gnu installer utils)
|
||||
#:use-module (gnu installer newt page)
|
||||
@@ -32,8 +26,6 @@
|
||||
#:use-module (srfi srfi-1)
|
||||
#:use-module (srfi srfi-34)
|
||||
#:use-module (srfi srfi-35)
|
||||
#:use-module (srfi srfi-71)
|
||||
#:use-module (ice-9 format)
|
||||
#:use-module (ice-9 match)
|
||||
#:use-module (ice-9 receive)
|
||||
#:use-module (newt)
|
||||
@@ -125,52 +117,10 @@ we want this page to occupy all the screen space available."
|
||||
(lambda ()
|
||||
(destroy-form-and-pop form))))))
|
||||
|
||||
(define (check-hardware-support pci-database)
|
||||
"Warn about unsupported devices."
|
||||
(when (member "uvesafb" (modules-loaded))
|
||||
(run-error-page (G_ "\
|
||||
This may be a false alarm, but possibly your graphics hardware does not
|
||||
work well with only free software. Expect trouble. If after installation,
|
||||
the system does not boot, perhaps you will need to add nomodeset to the
|
||||
kernel arguments and need to configure the uvesafb kernel module.")
|
||||
(G_ "Pre-install warning")))
|
||||
|
||||
(let ((devices (pci-devices)))
|
||||
(match (filter unsupported-pci-device? devices)
|
||||
(() ;no unsupported device
|
||||
#t)
|
||||
(unsupported
|
||||
(run-error-page (format #f (G_ "\
|
||||
Devices not supported by free software were found on your computer:
|
||||
|
||||
~{ - ~a~%~}
|
||||
Unfortunately, it means those devices will not be usable.
|
||||
|
||||
To address it, we recommend choosing hardware that respects your freedom as a \
|
||||
user--hardware for which free drivers and firmware exist. See \"Hardware \
|
||||
Considerations\" in the manual for more information.")
|
||||
(map (pci-device-description pci-database)
|
||||
unsupported))
|
||||
(G_ "Hardware support warning")
|
||||
#:width 76)))))
|
||||
|
||||
(define* (run-welcome-page logo #:key pci-database)
|
||||
(define (run-welcome-page logo)
|
||||
"Run a welcome page with the given textual LOGO displayed at the center of
|
||||
the page. Ask the user to choose between manual installation, graphical
|
||||
installation and reboot."
|
||||
(when (file-exists? %core-dump)
|
||||
(match (choice-window
|
||||
(G_ "Previous installation failed")
|
||||
(G_ "Continue")
|
||||
(G_ "Report the failure")
|
||||
(G_ "It seems that the previous installation exited unexpectedly \
|
||||
and generated a core dump. Do you want to continue or to report the failure \
|
||||
first?"))
|
||||
(1 #t)
|
||||
(2 (raise
|
||||
(condition
|
||||
(&user-abort-error))))))
|
||||
|
||||
(run-menu-page
|
||||
(G_ "GNU Guix install")
|
||||
(G_ "Welcome to GNU Guix system installer!
|
||||
@@ -184,16 +134,14 @@ Documentation is accessible at any time by pressing Ctrl-Alt-F2.")
|
||||
#:listbox-items
|
||||
`((,(G_ "Graphical install using a terminal based interface")
|
||||
.
|
||||
,(lambda ()
|
||||
(check-hardware-support pci-database)))
|
||||
,(const #t))
|
||||
(,(G_ "Install using the shell based process")
|
||||
.
|
||||
,(lambda ()
|
||||
(check-hardware-support pci-database)
|
||||
;; Switch to TTY3, where a root shell is available for shell based
|
||||
;; install. The other root TTY's would have been ok too.
|
||||
(system* "chvt" "3")
|
||||
(run-welcome-page logo #:pci-database pci-database)))
|
||||
(run-welcome-page logo)))
|
||||
(,(G_ "Reboot")
|
||||
.
|
||||
,(lambda ()
|
||||
|
||||
+10
-94
@@ -1,8 +1,7 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2018, 2019 Mathieu Othacehe <m.othacehe@gmail.com>
|
||||
;;; Copyright © 2019, 2020, 2022 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2019, 2020 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2020 Tobias Geerinckx-Rice <me@tobias.gr>
|
||||
;;; Copyright © 2022 Josselin Poiret <dev@jpoiret.xyz>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
@@ -39,7 +38,6 @@
|
||||
#:select (%base-initrd-modules))
|
||||
#:use-module (guix build syscalls)
|
||||
#:use-module (guix build utils)
|
||||
#:use-module (guix read-print)
|
||||
#:use-module (guix records)
|
||||
#:use-module (guix utils)
|
||||
#:use-module (guix i18n)
|
||||
@@ -81,6 +79,7 @@
|
||||
efi-installation?
|
||||
default-esp-mount-point
|
||||
|
||||
with-delay-device-in-use?
|
||||
force-device-sync
|
||||
eligible-devices
|
||||
partition-user-type
|
||||
@@ -148,7 +147,7 @@
|
||||
(default #f))
|
||||
(crypt-label user-partition-crypt-label
|
||||
(default #f))
|
||||
(crypt-password user-partition-crypt-password ; <secret>
|
||||
(crypt-password user-partition-crypt-password
|
||||
(default #f))
|
||||
(fs-type user-partition-fs-type
|
||||
(default 'ext4))
|
||||
@@ -319,25 +318,6 @@ PARTED-OBJECT field equals PARTITION, return #f if not found."
|
||||
partition))
|
||||
user-partitions))
|
||||
|
||||
(define (read-partition-uuid/retry file-name)
|
||||
"Call READ-PARTITION-UUID with 5 retries spaced by 1 second. This is useful
|
||||
if the partition table is updated by the kernel at the time this function is
|
||||
called, causing the underlying /dev to be absent."
|
||||
(define max-retries 5)
|
||||
|
||||
(let loop ((retry max-retries))
|
||||
(catch #t
|
||||
(lambda ()
|
||||
(read-partition-uuid file-name))
|
||||
(lambda _
|
||||
(if (> retry 0)
|
||||
(begin
|
||||
(sleep 1)
|
||||
(loop (- retry 1)))
|
||||
(error
|
||||
(format #f (G_ "Could not open ~a after ~a retries~%.")
|
||||
file-name max-retries)))))))
|
||||
|
||||
|
||||
;;
|
||||
;; Devices
|
||||
@@ -379,44 +359,12 @@ fail. See rereadpt function in wipefs.c of util-linux for an explanation."
|
||||
(define %min-device-size
|
||||
(* 2 GIBIBYTE-SIZE)) ;2GiB
|
||||
|
||||
(define (mapped-device? device)
|
||||
"Return #true if DEVICE is a mapped device, false otherwise."
|
||||
(string-prefix? "/dev/dm-" device))
|
||||
|
||||
;; TODO: Use DM_TABLE_DEPS ioctl instead of dmsetup.
|
||||
(define (mapped-device-parent-partition device)
|
||||
"Return the parent partition path of the mapped DEVICE."
|
||||
(let* ((command `("dmsetup" "deps" ,device "-o" "devname"))
|
||||
(parent #f)
|
||||
(handler
|
||||
(lambda (input)
|
||||
;; We are parsing an output that should look like:
|
||||
;; 1 dependencies : (sda2)
|
||||
(let ((result
|
||||
(string-match "\\(([^\\)]+)\\)"
|
||||
(get-string-all input))))
|
||||
(and result
|
||||
(set! parent
|
||||
(format #f "/dev/~a"
|
||||
(match:substring result 1))))))))
|
||||
(run-external-command-with-handler handler command)
|
||||
parent))
|
||||
|
||||
(define (eligible-devices)
|
||||
"Return all the available devices except the install device and the devices
|
||||
which are smaller than %MIN-DEVICE-SIZE."
|
||||
|
||||
(define the-installer-root-partition-path
|
||||
(let ((root (installer-root-partition-path)))
|
||||
(cond
|
||||
((mapped-device? root)
|
||||
;; If the partition is a mapped device (/dev/dm-X), locate the parent
|
||||
;; partition. It is the case when Ventoy is used to host the
|
||||
;; installation image.
|
||||
(let ((parent (mapped-device-parent-partition root)))
|
||||
(installer-log-line "mapped device ~a -> ~a" parent root)
|
||||
parent))
|
||||
(else root))))
|
||||
(installer-root-partition-path))
|
||||
|
||||
(define (small-device? device)
|
||||
(let ((length (device-length device))
|
||||
@@ -880,7 +828,6 @@ cause them to cross."
|
||||
(installer-log-line "~/type: ~a" partition-type)
|
||||
(installer-log-line "~/filesystem-type: ~a"
|
||||
(filesystem-type-name filesystem-type))
|
||||
(installer-log-line "~/flags: ~a" flags)
|
||||
(installer-log-line "~/start: ~a" start-sector*)
|
||||
(installer-log-line "~/end: ~a" end-sector)
|
||||
(installer-log-line "~/start-range: [~a, ~a]"
|
||||
@@ -897,18 +844,15 @@ cause them to cross."
|
||||
(when (and partition-ok? has-name? name)
|
||||
(partition-set-name partition name))
|
||||
|
||||
;; Both partition-set-system and partition-set-flag calls can affect
|
||||
;; the partition type. Their order is important, see:
|
||||
;; https://issues.guix.gnu.org/55549.
|
||||
(partition-set-system partition filesystem-type)
|
||||
|
||||
;; Set flags if required.
|
||||
;; Set flags is required.
|
||||
(for-each (lambda (flag)
|
||||
(and (partition-is-flag-available? partition flag)
|
||||
(partition-set-flag partition flag 1)))
|
||||
flags)
|
||||
|
||||
(and partition-ok? partition))))))
|
||||
(and partition-ok?
|
||||
(partition-set-system partition filesystem-type)
|
||||
partition))))))
|
||||
|
||||
|
||||
;;
|
||||
@@ -1035,11 +979,6 @@ exists."
|
||||
(for-each
|
||||
(lambda (partition)
|
||||
(and (data-partition? partition)
|
||||
;; Do not remove logical partitions ourselves, since
|
||||
;; disk-remove-partition* will remove all the logical partitions
|
||||
;; residing on an extended partition, which would lead to a
|
||||
;; double-remove and ensuing SEGFAULT.
|
||||
(not (logical-partition? partition))
|
||||
(disk-remove-partition* disk partition)))
|
||||
non-boot-partitions)
|
||||
|
||||
@@ -1159,7 +1098,7 @@ Return #t if all the statements are valid."
|
||||
(need-formatting?
|
||||
(user-partition-need-formatting? user-partition)))
|
||||
(or need-formatting?
|
||||
(read-partition-uuid/retry file-name)
|
||||
(read-partition-uuid file-name)
|
||||
(raise
|
||||
(condition
|
||||
(&cannot-read-uuid
|
||||
@@ -1234,7 +1173,7 @@ USER-PARTITION if it is encrypted, or the plain file-name otherwise."
|
||||
"Format and open the encrypted partition pointed by USER-PARTITION."
|
||||
(let* ((file-name (user-partition-file-name user-partition))
|
||||
(label (user-partition-crypt-label user-partition))
|
||||
(password (secret-content (user-partition-crypt-password user-partition))))
|
||||
(password (user-partition-crypt-password user-partition)))
|
||||
(call-with-luks-key-file
|
||||
password
|
||||
(lambda (key-file)
|
||||
@@ -1245,20 +1184,6 @@ USER-PARTITION if it is encrypted, or the plain file-name otherwise."
|
||||
((run-command-in-installer) "cryptsetup" "open" "--type" "luks"
|
||||
"--key-file" key-file file-name label)))))
|
||||
|
||||
(define (luks-ensure-open user-partition)
|
||||
"Ensure partition pointed by USER-PARTITION is opened."
|
||||
(unless (file-exists? (user-partition-upper-file-name user-partition))
|
||||
(let* ((file-name (user-partition-file-name user-partition))
|
||||
(label (user-partition-crypt-label user-partition))
|
||||
(password (secret-content (user-partition-crypt-password user-partition))))
|
||||
(call-with-luks-key-file
|
||||
password
|
||||
(lambda (key-file)
|
||||
(installer-log-line "opening LUKS entry ~s at ~s"
|
||||
label file-name)
|
||||
((run-command-in-installer) "cryptsetup" "open" "--type" "luks"
|
||||
"--key-file" key-file file-name label))))))
|
||||
|
||||
(define (luks-close user-partition)
|
||||
"Close the encrypted partition pointed by USER-PARTITION."
|
||||
(let ((label (user-partition-crypt-label user-partition)))
|
||||
@@ -1343,8 +1268,6 @@ respective mount-points."
|
||||
(user-fs-type->mount-type fs-type))
|
||||
(file-name
|
||||
(user-partition-upper-file-name user-partition)))
|
||||
(when crypt-label
|
||||
(luks-ensure-open user-partition))
|
||||
(mkdir-p target)
|
||||
(installer-log-line "mounting ~s on ~s" file-name target)
|
||||
(mount file-name target mount-type)))
|
||||
@@ -1516,13 +1439,6 @@ USER-PARTITIONS, or return nothing."
|
||||
`((mapped-devices
|
||||
(list ,@(map user-partition->mapped-device
|
||||
encrypted-partitions)))))
|
||||
|
||||
,(vertical-space 1)
|
||||
,(let-syntax ((G_ (syntax-rules () ((_ str) str))))
|
||||
(comment (G_ "\
|
||||
;; The list of file systems that get \"mounted\". The unique
|
||||
;; file system identifiers there (\"UUIDs\") can be obtained
|
||||
;; by running 'blkid' in a terminal.\n")))
|
||||
(file-systems (cons*
|
||||
,@(user-partitions->file-systems user-partitions)
|
||||
%base-file-systems)))))
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
(partition-page installer-partition-page)
|
||||
;; procedure void -> void
|
||||
(services-page installer-services-page)
|
||||
;; procedure (logo #:pci-database) -> void
|
||||
;; procedure (logo) -> void
|
||||
(welcome-page installer-welcome-page)
|
||||
;; procedure (menu-proc) -> void
|
||||
(parameters-menu installer-parameters-menu)
|
||||
|
||||
+10
-40
@@ -1,6 +1,6 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2018 Mathieu Othacehe <m.othacehe@gmail.com>
|
||||
;;; Copyright © 2019, 2022 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2019 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
|
||||
;;; Copyright © 2021 Tobias Geerinckx-Rice <me@tobias.gr>
|
||||
;;; Copyright © 2021 Leo Famulari <leo@famulari.name>
|
||||
@@ -22,7 +22,6 @@
|
||||
|
||||
(define-module (gnu installer services)
|
||||
#:use-module (guix records)
|
||||
#:use-module (guix read-print)
|
||||
#:use-module (srfi srfi-1)
|
||||
#:export (system-service?
|
||||
system-service-name
|
||||
@@ -36,11 +35,6 @@
|
||||
%system-services
|
||||
system-services->configuration))
|
||||
|
||||
(define-syntax-rule (G_ str)
|
||||
;; In this file, translatable strings are annotated with 'G_' so xgettext
|
||||
;; catches them, but translation happens later on at run time.
|
||||
str)
|
||||
|
||||
(define-record-type* <system-service>
|
||||
system-service make-system-service
|
||||
system-service?
|
||||
@@ -58,7 +52,9 @@
|
||||
((_ fields ...)
|
||||
(system-service
|
||||
(type 'desktop)
|
||||
fields ...)))))
|
||||
fields ...))))
|
||||
(G_ (syntax-rules () ;for xgettext
|
||||
((_ str) str))))
|
||||
(list
|
||||
;; This is the list of desktop environments supported as services.
|
||||
(desktop-environment
|
||||
@@ -98,12 +94,7 @@
|
||||
(system-service
|
||||
(name (G_ "OpenSSH secure shell daemon (sshd)"))
|
||||
(type 'networking)
|
||||
(snippet `(,(vertical-space 1)
|
||||
,(comment
|
||||
(G_ "\
|
||||
;; To configure OpenSSH, pass an 'openssh-configuration'
|
||||
;; record as a second argument to 'service' below.\n"))
|
||||
(service openssh-service-type))))
|
||||
(snippet '((service openssh-service-type))))
|
||||
(system-service
|
||||
(name (G_ "Tor anonymous network router"))
|
||||
(type 'networking)
|
||||
@@ -158,45 +149,24 @@
|
||||
(desktop? (find desktop-system-service? services))
|
||||
(base (if desktop?
|
||||
'%desktop-services
|
||||
'%base-services))
|
||||
(service-heading (list (vertical-space 1)
|
||||
(comment (G_ "\
|
||||
;; Below is the list of system services. To search for available
|
||||
;; services, run 'guix system search KEYWORD' in a terminal.\n"))))
|
||||
(package-heading (list (vertical-space 1)
|
||||
(comment (G_ "\
|
||||
;; Packages installed system-wide. Users can also install packages
|
||||
;; under their own account: use 'guix search KEYWORD' to search
|
||||
;; for packages and 'guix install PACKAGE' to install a package.\n")))))
|
||||
|
||||
'%base-services)))
|
||||
(if (null? snippets)
|
||||
`(,@(if (null? packages)
|
||||
'()
|
||||
`(,@package-heading
|
||||
(packages (append (list ,@packages)
|
||||
`((packages (append (list ,@packages)
|
||||
%base-packages))))
|
||||
|
||||
,@service-heading
|
||||
(services ,base))
|
||||
`(,@(if (null? packages)
|
||||
'()
|
||||
`(,@package-heading
|
||||
(packages (append (list ,@packages)
|
||||
`((packages (append (list ,@packages)
|
||||
%base-packages))))
|
||||
|
||||
,@service-heading
|
||||
(services (append (list ,@snippets
|
||||
|
||||
,@(if desktop?
|
||||
;; XXX: Assume 'keyboard-layout' is in
|
||||
;; scope.
|
||||
`((set-xorg-configuration
|
||||
'((set-xorg-configuration
|
||||
(xorg-configuration
|
||||
(keyboard-layout keyboard-layout))))
|
||||
'()))
|
||||
|
||||
,(vertical-space 1)
|
||||
,(comment (G_ "\
|
||||
;; This is the default list of services we
|
||||
;; are appending to.\n"))
|
||||
,base))))))
|
||||
,base))))))
|
||||
|
||||
+11
-29
@@ -1,6 +1,6 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2018, 2019 Mathieu Othacehe <m.othacehe@gmail.com>
|
||||
;;; Copyright © 2020-2022 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2020, 2021 Ludovic Courtès <ludo@gnu.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
@@ -21,17 +21,14 @@
|
||||
#:use-module (guix records)
|
||||
#:use-module (guix build utils)
|
||||
#:use-module (guix i18n)
|
||||
#:use-module (guix read-print)
|
||||
#:use-module (gnu installer utils)
|
||||
#:use-module (ice-9 match)
|
||||
#:use-module (ice-9 pretty-print)
|
||||
#:use-module (srfi srfi-1)
|
||||
#:use-module (srfi srfi-34)
|
||||
#:use-module (srfi srfi-35)
|
||||
#:use-module (rnrs io ports)
|
||||
#:export (&user-abort-error
|
||||
user-abort-error?
|
||||
|
||||
<installer-step>
|
||||
#:export (<installer-step>
|
||||
installer-step
|
||||
make-installer-step
|
||||
installer-step?
|
||||
@@ -53,9 +50,6 @@
|
||||
|
||||
%current-result))
|
||||
|
||||
(define-condition-type &user-abort-error &error
|
||||
user-abort-error?)
|
||||
|
||||
;; Hash table storing the step results. Use it only for logging and debug
|
||||
;; purposes.
|
||||
(define %current-result (make-hash-table))
|
||||
@@ -230,14 +224,10 @@ found in RESULTS."
|
||||
(conf-formatter result-step)
|
||||
'())))
|
||||
steps))
|
||||
(modules `(,(vertical-space 1)
|
||||
,(comment (G_ "\
|
||||
;; Indicate which modules to import to access the variables
|
||||
;; used in this configuration.\n"))
|
||||
(use-modules (gnu))
|
||||
(modules '((use-modules (gnu))
|
||||
(use-service-modules cups desktop networking ssh xorg))))
|
||||
`(,@modules
|
||||
,(vertical-space 1)
|
||||
()
|
||||
(operating-system ,@configuration))))
|
||||
|
||||
(define* (configuration->file configuration
|
||||
@@ -251,22 +241,14 @@ found in RESULTS."
|
||||
;; length below 60 characters.
|
||||
(display (G_ "\
|
||||
;; This is an operating system configuration generated
|
||||
;; by the graphical installer.
|
||||
;;
|
||||
;; Once installation is complete, you can learn and modify
|
||||
;; this file to tweak the system configuration, and pass it
|
||||
;; to the 'guix system reconfigure' command to effect your
|
||||
;; changes.\n")
|
||||
;; by the graphical installer.\n")
|
||||
port)
|
||||
(newline port)
|
||||
(pretty-print-with-comments/splice port configuration
|
||||
#:max-width 75
|
||||
#:format-comment
|
||||
(lambda (c indent)
|
||||
;; Localize C.
|
||||
(comment (G_ (comment->string c))
|
||||
(comment-margin? c))))
|
||||
|
||||
(for-each (lambda (part)
|
||||
(if (null? part)
|
||||
(newline port)
|
||||
(pretty-print part port)))
|
||||
configuration)
|
||||
(flush-output-port port))))
|
||||
|
||||
;;; Local Variables:
|
||||
|
||||
@@ -280,10 +280,6 @@ instrumented for further testing."
|
||||
exp)))
|
||||
|
||||
(let ((content (call-with-input-file file read-expressions)))
|
||||
;; XXX: Remove the file before re-writing it, to be sure there are no
|
||||
;; leftovers. We shouldn't have to do that as CALL-WITH-OUTPUT-FILE uses
|
||||
;; the O_TRUNC flag by default.
|
||||
(delete-file file)
|
||||
(call-with-output-file file
|
||||
(lambda (port)
|
||||
(format port "\
|
||||
|
||||
+17
-8
@@ -17,13 +17,16 @@
|
||||
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
(define-module (gnu installer user)
|
||||
#:use-module (gnu installer utils)
|
||||
#:use-module (guix records)
|
||||
#:use-module (guix read-print)
|
||||
#:use-module (srfi srfi-1)
|
||||
#:use-module (srfi srfi-9)
|
||||
#:use-module (srfi srfi-9 gnu)
|
||||
#:export (<user>
|
||||
#:export (<secret>
|
||||
secret?
|
||||
make-secret
|
||||
secret-content
|
||||
|
||||
<user>
|
||||
user
|
||||
make-user
|
||||
user-name
|
||||
@@ -34,6 +37,16 @@
|
||||
|
||||
users->configuration))
|
||||
|
||||
(define-record-type <secret>
|
||||
(make-secret content)
|
||||
secret?
|
||||
(content secret-content))
|
||||
|
||||
(set-record-type-printer!
|
||||
<secret>
|
||||
(lambda (secret port)
|
||||
(format port "<secret>")))
|
||||
|
||||
(define-record-type* <user>
|
||||
user make-user
|
||||
user?
|
||||
@@ -56,11 +69,7 @@
|
||||
(supplementary-groups '("wheel" "netdev"
|
||||
"audio" "video"))))
|
||||
|
||||
(define-syntax-rule (G_ str) str)
|
||||
|
||||
`(,(vertical-space 1)
|
||||
,(comment (G_ ";; The list of user accounts ('root' is implicit).\n"))
|
||||
(users (cons*
|
||||
`((users (cons*
|
||||
,@(filter-map (lambda (user)
|
||||
;; Do not emit a 'user-account' form for "root".
|
||||
(and (not (string=? (user-name user) "root"))
|
||||
|
||||
+21
-72
@@ -1,6 +1,6 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2018, 2020 Mathieu Othacehe <m.othacehe@gmail.com>
|
||||
;;; Copyright © 2019, 2020, 2022 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2019, 2020 Ludovic Courtès <ludo@gnu.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
@@ -20,12 +20,9 @@
|
||||
(define-module (gnu installer utils)
|
||||
#:use-module (gnu services herd)
|
||||
#:use-module (guix utils)
|
||||
#:use-module ((guix build syscalls) #:select (openpty login-tty))
|
||||
#:use-module (guix build utils)
|
||||
#:use-module (guix i18n)
|
||||
#:use-module (srfi srfi-1)
|
||||
#:use-module (srfi srfi-9)
|
||||
#:use-module (srfi srfi-9 gnu)
|
||||
#:use-module (srfi srfi-19)
|
||||
#:use-module (srfi srfi-34)
|
||||
#:use-module (srfi srfi-35)
|
||||
@@ -36,17 +33,11 @@
|
||||
#:use-module (ice-9 regex)
|
||||
#:use-module (ice-9 format)
|
||||
#:use-module (ice-9 textual-ports)
|
||||
#:export (<secret>
|
||||
secret?
|
||||
make-secret
|
||||
secret-content
|
||||
|
||||
read-lines
|
||||
#:export (read-lines
|
||||
read-all
|
||||
nearest-exact-integer
|
||||
read-percentage
|
||||
run-external-command-with-handler
|
||||
run-external-command-with-handler/tty
|
||||
run-external-command-with-line-hooks
|
||||
run-command
|
||||
run-command-in-installer
|
||||
@@ -67,16 +58,6 @@
|
||||
|
||||
with-silent-shepherd))
|
||||
|
||||
(define-record-type <secret>
|
||||
(make-secret content)
|
||||
secret?
|
||||
(content secret-content))
|
||||
|
||||
(set-record-type-printer!
|
||||
<secret>
|
||||
(lambda (secret port)
|
||||
(format port "<secret>")))
|
||||
|
||||
(define* (read-lines #:optional (port (current-input-port)))
|
||||
"Read lines from PORT and return them as a list."
|
||||
(let loop ((line (read-line port))
|
||||
@@ -126,58 +107,26 @@ the child process as returned by waitpid."
|
||||
(close-port input)
|
||||
(close-pipe dummy-pipe)))
|
||||
|
||||
(define (run-external-command-with-handler/tty handler command)
|
||||
"Run command specified by the list COMMAND in a child operating in a
|
||||
pseudoterminal with output handler HANDLER. HANDLER is a procedure taking an
|
||||
input port, to which the command will write its standard output and error.
|
||||
Returns the integer status value of the child process as returned by waitpid."
|
||||
(define-values (controller inferior)
|
||||
(openpty))
|
||||
|
||||
(match (primitive-fork)
|
||||
(0
|
||||
(catch #t
|
||||
(lambda ()
|
||||
(close-fdes controller)
|
||||
(login-tty inferior)
|
||||
(apply execlp (car command) command))
|
||||
(lambda _
|
||||
(primitive-exit 127))))
|
||||
(pid
|
||||
(close-fdes inferior)
|
||||
(let* ((port (fdopen controller "r0"))
|
||||
(result (false-if-exception
|
||||
(handler port))))
|
||||
(close-port port)
|
||||
(cdr (waitpid pid))))))
|
||||
|
||||
(define* (run-external-command-with-line-hooks line-hooks command
|
||||
#:key (tty? #false))
|
||||
(define (run-external-command-with-line-hooks line-hooks command)
|
||||
"Run command specified by the list COMMAND in a child, processing each
|
||||
output line with the procedures in LINE-HOOKS. If TTY is set to #true, the
|
||||
COMMAND will be run in a pseudoterminal. Returns the integer status value of
|
||||
the child process as returned by waitpid."
|
||||
output line with the procedures in LINE-HOOKS. Returns the integer status
|
||||
value of the child process as returned by waitpid."
|
||||
(define (handler input)
|
||||
(and
|
||||
;; Lines for progress bars etc. end in \r; treat is as a line ending so
|
||||
;; those lines are printed right away.
|
||||
(and=> (read-delimited "\r\n" input 'concat)
|
||||
(and=> (get-line input)
|
||||
(lambda (line)
|
||||
(if (eof-object? line)
|
||||
#f
|
||||
(begin (for-each (lambda (f) (f line))
|
||||
(append line-hooks
|
||||
%default-installer-line-hooks))
|
||||
%default-installer-line-hooks))
|
||||
#t))))
|
||||
(handler input)))
|
||||
(if tty?
|
||||
(run-external-command-with-handler/tty handler command)
|
||||
(run-external-command-with-handler handler command)))
|
||||
(run-external-command-with-handler handler command))
|
||||
|
||||
(define* (run-command command #:key (tty? #f))
|
||||
(define* (run-command command)
|
||||
"Run COMMAND, a list of strings. Return true if COMMAND exited
|
||||
successfully, #f otherwise. If TTY is set to #true, the COMMAND will be run
|
||||
in a pseudoterminal."
|
||||
successfully, #f otherwise."
|
||||
(define (pause)
|
||||
(format #t (G_ "Press Enter to continue.~%"))
|
||||
(send-to-clients '(pause))
|
||||
@@ -188,8 +137,8 @@ in a pseudoterminal."
|
||||
|
||||
(installer-log-line "running command ~s" command)
|
||||
(define result (run-external-command-with-line-hooks
|
||||
(list display) command
|
||||
#:tty? tty?))
|
||||
(list %display-line-hook)
|
||||
command))
|
||||
(define exit-val (status:exit-val result))
|
||||
(define term-sig (status:term-sig result))
|
||||
(define stop-sig (status:stop-sig result))
|
||||
@@ -266,10 +215,7 @@ values."
|
||||
(or port (%make-void-port "w")))))
|
||||
|
||||
(define (%syslog-line-hook line)
|
||||
(let ((line (if (string-suffix? "\r" line)
|
||||
(string-append (string-drop-right line 1) "\n")
|
||||
line)))
|
||||
(format (syslog-port) "installer[~d]: ~a" (getpid) line)))
|
||||
(format (syslog-port) "installer[~d]: ~a~%" (getpid) line))
|
||||
|
||||
(define-syntax syslog
|
||||
(lambda (s)
|
||||
@@ -298,7 +244,11 @@ values."
|
||||
port)))
|
||||
|
||||
(define (%installer-log-line-hook line)
|
||||
(display line (installer-log-port)))
|
||||
(format (installer-log-port) "~a~%" line))
|
||||
|
||||
(define (%display-line-hook line)
|
||||
(display line)
|
||||
(newline))
|
||||
|
||||
(define %default-installer-line-hooks
|
||||
(list %syslog-line-hook
|
||||
@@ -310,10 +260,9 @@ values."
|
||||
(syntax-case s ()
|
||||
((_ fmt args ...)
|
||||
(string? (syntax->datum #'fmt))
|
||||
(with-syntax ((fmt (string-append (syntax->datum #'fmt) "\n")))
|
||||
#'(let ((formatted (format #f fmt args ...)))
|
||||
(for-each (lambda (f) (f formatted))
|
||||
%default-installer-line-hooks)))))))
|
||||
#'(let ((formatted (format #f fmt args ...)))
|
||||
(for-each (lambda (f) (f formatted))
|
||||
%default-installer-line-hooks))))))
|
||||
|
||||
|
||||
;;;
|
||||
|
||||
+153
-201
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,6 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2019 Jakob L. Kreuze <zerodaysfordays@sdf.org>
|
||||
;;; Copyright © 2020 Brice Waegeneire <brice@waegenei.re>
|
||||
;;; Copyright © 2022 Matthew James Kraai <kraai@ftbfs.org>
|
||||
;;; Copyright © 2022 Ricardo Wurmus <rekado@elephly.net>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
@@ -23,7 +21,6 @@
|
||||
#:use-module (gnu machine ssh)
|
||||
#:use-module (gnu machine)
|
||||
#:use-module (gnu services)
|
||||
#:use-module (gnu services base)
|
||||
#:use-module (gnu services networking)
|
||||
#:use-module (gnu system)
|
||||
#:use-module (gnu system pam)
|
||||
@@ -36,9 +33,7 @@
|
||||
#:use-module (guix records)
|
||||
#:use-module (guix ssh)
|
||||
#:use-module (guix store)
|
||||
#:use-module (ice-9 format)
|
||||
#:use-module (ice-9 iconv)
|
||||
#:use-module (ice-9 string-fun)
|
||||
#:use-module (json)
|
||||
#:use-module (rnrs bytevectors)
|
||||
#:use-module (srfi srfi-1)
|
||||
@@ -192,66 +187,18 @@ an environment type of 'digital-ocean-environment-type'."
|
||||
;;; System deployment.
|
||||
;;;
|
||||
|
||||
;; XXX Copied from (gnu services base)
|
||||
(define* (ip+netmask->cidr ip netmask #:optional (family AF_INET))
|
||||
"Return the CIDR notation (a string) for @var{ip} and @var{netmask}, two
|
||||
@var{family} address strings, where @var{family} is @code{AF_INET} or
|
||||
@code{AF_INET6}."
|
||||
(let* ((netmask (inet-pton family netmask))
|
||||
(bits (logcount netmask)))
|
||||
(string-append ip "/" (number->string bits))))
|
||||
|
||||
;; The following script was adapted from the guide available at
|
||||
;; <https://wiki.pantherx.org/Installation-digital-ocean/>.
|
||||
(define (guix-infect network)
|
||||
"Given NETWORK, an alist describing the Droplet's public IPv4 network
|
||||
interface, return a Bash script that will install the Guix system."
|
||||
(define os
|
||||
`(operating-system
|
||||
(host-name "gnu-bootstrap")
|
||||
(timezone "Etc/UTC")
|
||||
(bootloader (bootloader-configuration
|
||||
(bootloader grub-bootloader)
|
||||
(targets '("/dev/vda"))
|
||||
(terminal-outputs '(console))))
|
||||
(file-systems (cons (file-system
|
||||
(mount-point "/")
|
||||
(device "/dev/vda1")
|
||||
(type "ext4"))
|
||||
%base-file-systems))
|
||||
(services
|
||||
(append (list (service static-networking-service-type
|
||||
(list (static-networking
|
||||
(addresses
|
||||
(list (network-address
|
||||
(device "eth0")
|
||||
(value ,(ip+netmask->cidr
|
||||
(assoc-ref network "ip_address")
|
||||
(assoc-ref network "netmask"))))))
|
||||
(routes
|
||||
(list (network-route
|
||||
(destination "default")
|
||||
(gateway ,(assoc-ref network "gateway")))))
|
||||
(name-servers '("84.200.69.80" "84.200.70.40")))))
|
||||
(simple-service 'guile-load-path-in-global-env
|
||||
session-environment-service-type
|
||||
`(("GUILE_LOAD_PATH"
|
||||
. "/run/current-system/profile/share/guile/site/3.0")
|
||||
("GUILE_LOAD_COMPILED_PATH"
|
||||
. ,(string-append "/run/current-system/profile/lib/guile/3.0/site-ccache:"
|
||||
"/run/current-system/profile/share/guile/site/3.0"))))
|
||||
(service openssh-service-type
|
||||
(openssh-configuration
|
||||
(log-level 'debug)
|
||||
(permit-root-login 'prohibit-password))))
|
||||
%base-services))))
|
||||
(format #f "#!/bin/bash
|
||||
|
||||
apt-get update
|
||||
apt-get install xz-utils -y
|
||||
wget -nv https://ci.guix.gnu.org/search/latest/archive?query=spec:tarball+status:success+system:x86_64-linux+guix-binary.tar.xz -O guix-binary-nightly.x86_64-linux.tar.xz
|
||||
wget https://ftp.gnu.org/gnu/guix/guix-binary-1.0.1.x86_64-linux.tar.xz
|
||||
cd /tmp
|
||||
tar --warning=no-timestamp -xf ~~/guix-binary-nightly.x86_64-linux.tar.xz
|
||||
tar --warning=no-timestamp -xf ~~/guix-binary-1.0.1.x86_64-linux.tar.xz
|
||||
mv var/guix /var/ && mv gnu /
|
||||
mkdir -p ~~root/.config/guix
|
||||
ln -sf /var/guix/profiles/per-user/root/current-guix ~~root/.config/guix/current
|
||||
@@ -281,9 +228,37 @@ export GUIX_LOCPATH=\"$HOME/.guix-profile/lib/locale\"
|
||||
guix package -i openssl
|
||||
cat > /etc/bootstrap-config.scm << EOF
|
||||
(use-modules (gnu))
|
||||
(use-service-modules base networking ssh)
|
||||
(use-service-modules networking ssh)
|
||||
|
||||
~a
|
||||
(operating-system
|
||||
(host-name \"gnu-bootstrap\")
|
||||
(timezone \"Etc/UTC\")
|
||||
(bootloader (bootloader-configuration
|
||||
(bootloader grub-bootloader)
|
||||
(targets '(\"/dev/vda\"))
|
||||
(terminal-outputs '(console))))
|
||||
(file-systems (cons (file-system
|
||||
(mount-point \"/\")
|
||||
(device \"/dev/vda1\")
|
||||
(type \"ext4\"))
|
||||
%base-file-systems))
|
||||
(services
|
||||
(append (list (static-networking-service \"eth0\" \"~a\"
|
||||
#:netmask \"~a\"
|
||||
#:gateway \"~a\"
|
||||
#:name-servers '(\"84.200.69.80\" \"84.200.70.40\"))
|
||||
(simple-service 'guile-load-path-in-global-env
|
||||
session-environment-service-type
|
||||
\\`((\"GUILE_LOAD_PATH\"
|
||||
. \"/run/current-system/profile/share/guile/site/2.2\")
|
||||
(\"GUILE_LOAD_COMPILED_PATH\"
|
||||
. ,(string-append \"/run/current-system/profile/lib/guile/2.2/site-ccache:\"
|
||||
\"/run/current-system/profile/share/guile/site/2.2\"))))
|
||||
(service openssh-service-type
|
||||
(openssh-configuration
|
||||
(log-level 'debug)
|
||||
(permit-root-login 'prohibit-password))))
|
||||
%base-services)))
|
||||
EOF
|
||||
# guix pull
|
||||
guix system build /etc/bootstrap-config.scm
|
||||
@@ -292,9 +267,9 @@ mv /etc /old-etc
|
||||
mkdir /etc
|
||||
cp -r /old-etc/{passwd,group,shadow,gshadow,mtab,guix,bootstrap-config.scm} /etc/
|
||||
guix system reconfigure /etc/bootstrap-config.scm"
|
||||
;; Escape the bare backtick to avoid having it interpreted by Bash.
|
||||
(string-replace-substring
|
||||
(format #f "~y" os) "`" "\\`")))
|
||||
(assoc-ref network "ip_address")
|
||||
(assoc-ref network "netmask")
|
||||
(assoc-ref network "gateway")))
|
||||
|
||||
(define (machine-wait-until-available machine)
|
||||
"Block until the initial Debian image has been installed on the droplet
|
||||
@@ -325,26 +300,18 @@ named DROPLET-NAME."
|
||||
configuration for the public IPv4 network described by the alist NETWORK."
|
||||
(operating-system
|
||||
(inherit (machine-operating-system target))
|
||||
(services (cons* (service static-networking-service-type
|
||||
(list (static-networking
|
||||
(addresses
|
||||
(list (network-address
|
||||
(device "eth0")
|
||||
(value (ip+netmask->cidr
|
||||
(assoc-ref network "ip_address")
|
||||
(assoc-ref network "netmask"))))))
|
||||
(routes
|
||||
(list (network-route
|
||||
(destination "default")
|
||||
(gateway (assoc-ref network "gateway")))))
|
||||
(name-servers '("84.200.69.80" "84.200.70.40")))))
|
||||
(services (cons* (static-networking-service "eth0"
|
||||
(assoc-ref network "ip_address")
|
||||
#:netmask (assoc-ref network "netmask")
|
||||
#:gateway (assoc-ref network "gateway")
|
||||
#:name-servers '("84.200.69.80" "84.200.70.40"))
|
||||
(simple-service 'guile-load-path-in-global-env
|
||||
session-environment-service-type
|
||||
`(("GUILE_LOAD_PATH"
|
||||
. "/run/current-system/profile/share/guile/site/3.0")
|
||||
. "/run/current-system/profile/share/guile/site/2.2")
|
||||
("GUILE_LOAD_COMPILED_PATH"
|
||||
. ,(string-append "/run/current-system/profile/lib/guile/3.0/site-ccache:"
|
||||
"/run/current-system/profile/share/guile/site/3.0"))))
|
||||
. ,(string-append "/run/current-system/profile/lib/guile/2.2/site-ccache:"
|
||||
"/run/current-system/profile/share/guile/site/2.2"))))
|
||||
(operating-system-user-services
|
||||
(machine-operating-system target))))))
|
||||
|
||||
@@ -440,7 +407,7 @@ environment type of 'digital-ocean-environment-type'."
|
||||
(raise (condition
|
||||
(&message
|
||||
(message (G_ "No Digital Ocean access token was provided. This \
|
||||
may be fixed by setting the environment variable GUIX_DIGITAL_OCEAN_TOKEN to \
|
||||
may be fixed by setting the environment variable GUIX_DIGITAL_OCAEN_TOKEN to \
|
||||
one procured from https://cloud.digitalocean.com/account/api/tokens.")))))))
|
||||
|
||||
(define (maybe-raise-unsupported-configuration-error machine)
|
||||
|
||||
+43
-83
@@ -42,7 +42,6 @@
|
||||
#:use-module ((guix inferior)
|
||||
#:select (inferior-exception?
|
||||
inferior-exception-arguments))
|
||||
#:use-module ((guix platform) #:select (systems))
|
||||
#:use-module (gcrypt pk-crypto)
|
||||
#:use-module (ice-9 format)
|
||||
#:use-module (ice-9 match)
|
||||
@@ -87,8 +86,7 @@
|
||||
machine-ssh-configuration?
|
||||
this-machine-ssh-configuration
|
||||
(host-name machine-ssh-configuration-host-name) ; string
|
||||
(system machine-ssh-configuration-system ; string
|
||||
(sanitize validate-system-type))
|
||||
(system machine-ssh-configuration-system) ; string
|
||||
(build-locally? machine-ssh-configuration-build-locally? ; boolean
|
||||
(default #t))
|
||||
(authorize? machine-ssh-configuration-authorize? ; boolean
|
||||
@@ -111,32 +109,6 @@
|
||||
(host-key machine-ssh-configuration-host-key ; #f | string
|
||||
(default #f)))
|
||||
|
||||
(define-with-syntax-properties (validate-system-type (value properties))
|
||||
;; Raise an error if VALUE is not a valid system type.
|
||||
(unless (string? value)
|
||||
(raise (make-compound-condition
|
||||
(condition
|
||||
(&error-location
|
||||
(location (source-properties->location properties))))
|
||||
(formatted-message
|
||||
(G_ "~a: invalid system type; must be a string")
|
||||
value))))
|
||||
(unless (member value (systems))
|
||||
(raise (apply make-compound-condition
|
||||
(condition
|
||||
(&error-location
|
||||
(location (source-properties->location properties))))
|
||||
(formatted-message (G_ "~a: unknown system type") value)
|
||||
(let ((closest (string-closest value (systems)
|
||||
#:threshold 5)))
|
||||
(if closest
|
||||
(list (condition
|
||||
(&fix-hint
|
||||
(hint (format #f (G_ "Did you mean @code{~a}?")
|
||||
closest)))))
|
||||
'())))))
|
||||
value)
|
||||
|
||||
(define (open-machine-ssh-session config)
|
||||
"Open an SSH session for CONFIG, a <machine-ssh-configuration> record."
|
||||
(let ((host-name (machine-ssh-configuration-host-name config))
|
||||
@@ -367,13 +339,9 @@ by MACHINE."
|
||||
"Raise a '&message' error condition if it is clear that deploying MACHINE's
|
||||
'system' declaration would fail."
|
||||
(define assertions
|
||||
(parameterize ((%current-system
|
||||
(machine-ssh-configuration-system
|
||||
(machine-configuration machine)))
|
||||
(%current-target-system #f))
|
||||
(append (machine-check-file-system-availability machine)
|
||||
(machine-check-initrd-modules machine)
|
||||
(list (machine-check-forward-update machine)))))
|
||||
(append (machine-check-file-system-availability machine)
|
||||
(machine-check-initrd-modules machine)
|
||||
(list (machine-check-forward-update machine))))
|
||||
|
||||
(define aggregate-exp
|
||||
;; Gather all the expressions so that a single round-trip is enough to
|
||||
@@ -485,16 +453,12 @@ the 'should-roll-back' field set to SHOULD-ROLL-BACK?"
|
||||
(define (deploy-managed-host machine)
|
||||
"Internal implementation of 'deploy-machine' for MACHINE instances with an
|
||||
environment type of 'managed-host."
|
||||
(define config (machine-configuration machine))
|
||||
(define host (machine-ssh-configuration-host-name config))
|
||||
(define system (machine-ssh-configuration-system config))
|
||||
|
||||
(maybe-raise-unsupported-configuration-error machine)
|
||||
(when (machine-ssh-configuration-authorize?
|
||||
(machine-configuration machine))
|
||||
(unless (file-exists? %public-key-file)
|
||||
(raise (formatted-message (G_ "no signing key '~a'. \
|
||||
Have you run 'guix archive --generate-key'?")
|
||||
have you run 'guix archive --generate-key?'")
|
||||
%public-key-file)))
|
||||
(remote-authorize-signing-key (call-with-input-file %public-key-file
|
||||
(lambda (port)
|
||||
@@ -502,54 +466,50 @@ Have you run 'guix archive --generate-key'?")
|
||||
(get-string-all port))))
|
||||
(machine-ssh-session machine)
|
||||
(machine-become-command machine)))
|
||||
|
||||
(mlet %store-monad ((_ (check-deployment-sanity machine))
|
||||
(boot-parameters (machine-boot-parameters machine)))
|
||||
;; Make sure code that check %CURRENT-SYSTEM, such as
|
||||
;; %BASE-INITRD-MODULES, gets to see the right value.
|
||||
(parameterize ((%current-system system)
|
||||
(%current-target-system #f))
|
||||
(let* ((os (machine-operating-system machine))
|
||||
(eval (cut machine-remote-eval machine <>))
|
||||
(menu-entries (map boot-parameters->menu-entry boot-parameters))
|
||||
(bootloader-configuration (operating-system-bootloader os))
|
||||
(bootcfg (operating-system-bootcfg os menu-entries)))
|
||||
(define-syntax-rule (eval/error-handling condition handler ...)
|
||||
;; Return a wrapper around EVAL such that HANDLER is evaluated if an
|
||||
;; exception is raised.
|
||||
(lambda (exp)
|
||||
(lambda (store)
|
||||
(guard (condition ((inferior-exception? condition)
|
||||
(values (begin handler ...) store)))
|
||||
(values (run-with-store store (eval exp)
|
||||
#:system system)
|
||||
store)))))
|
||||
(let* ((os (machine-operating-system machine))
|
||||
(host (machine-ssh-configuration-host-name
|
||||
(machine-configuration machine)))
|
||||
(eval (cut machine-remote-eval machine <>))
|
||||
(menu-entries (map boot-parameters->menu-entry boot-parameters))
|
||||
(bootloader-configuration (operating-system-bootloader os))
|
||||
(bootcfg (operating-system-bootcfg os menu-entries)))
|
||||
(define-syntax-rule (eval/error-handling condition handler ...)
|
||||
;; Return a wrapper around EVAL such that HANDLER is evaluated if an
|
||||
;; exception is raised.
|
||||
(lambda (exp)
|
||||
(lambda (store)
|
||||
(guard (condition ((inferior-exception? condition)
|
||||
(values (begin handler ...) store)))
|
||||
(values (run-with-store store (eval exp))
|
||||
store)))))
|
||||
|
||||
(mbegin %store-monad
|
||||
(with-roll-back #f
|
||||
(switch-to-system (eval/error-handling c
|
||||
(raise (formatted-message
|
||||
(G_ "\
|
||||
(mbegin %store-monad
|
||||
(with-roll-back #f
|
||||
(switch-to-system (eval/error-handling c
|
||||
(raise (formatted-message
|
||||
(G_ "\
|
||||
failed to switch systems while deploying '~a':~%~{~s ~}")
|
||||
host
|
||||
(inferior-exception-arguments c))))
|
||||
os))
|
||||
(with-roll-back #t
|
||||
(mbegin %store-monad
|
||||
(upgrade-shepherd-services (eval/error-handling c
|
||||
(warning (G_ "\
|
||||
host
|
||||
(inferior-exception-arguments c))))
|
||||
os))
|
||||
(with-roll-back #t
|
||||
(mbegin %store-monad
|
||||
(upgrade-shepherd-services (eval/error-handling c
|
||||
(warning (G_ "\
|
||||
an error occurred while upgrading services on '~a':~%~{~s ~}~%")
|
||||
host
|
||||
(inferior-exception-arguments
|
||||
c)))
|
||||
os)
|
||||
(install-bootloader (eval/error-handling c
|
||||
(raise (formatted-message
|
||||
(G_ "\
|
||||
host
|
||||
(inferior-exception-arguments
|
||||
c)))
|
||||
os)
|
||||
(install-bootloader (eval/error-handling c
|
||||
(raise (formatted-message
|
||||
(G_ "\
|
||||
failed to install bootloader on '~a':~%~{~s ~}~%")
|
||||
host
|
||||
(inferior-exception-arguments c))))
|
||||
bootloader-configuration bootcfg))))))))
|
||||
host
|
||||
(inferior-exception-arguments c))))
|
||||
bootloader-configuration bootcfg)))))))
|
||||
|
||||
|
||||
;;;
|
||||
|
||||
+13
-40
@@ -4,7 +4,6 @@
|
||||
;;; Copyright © 2014 Eric Bavier <bavier@member.fsf.org>
|
||||
;;; Copyright © 2016, 2017 Alex Kost <alezost@gmail.com>
|
||||
;;; Copyright © 2016 Mathieu Lirzin <mthl@gnu.org>
|
||||
;;; Copyright © 2022 Antero Mejr <antero@mailbox.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
@@ -40,11 +39,11 @@
|
||||
#:use-module (ice-9 binary-ports)
|
||||
#:autoload (system base compile) (compile)
|
||||
#:use-module (srfi srfi-1)
|
||||
#:use-module (srfi srfi-11)
|
||||
#:use-module (srfi srfi-26)
|
||||
#:use-module (srfi srfi-34)
|
||||
#:use-module (srfi srfi-35)
|
||||
#:use-module (srfi srfi-39)
|
||||
#:use-module (srfi srfi-71)
|
||||
#:export (search-patch
|
||||
search-patches
|
||||
search-auxiliary-file
|
||||
@@ -66,9 +65,6 @@
|
||||
specification->package+output
|
||||
specification->location
|
||||
specifications->manifest
|
||||
specifications->packages
|
||||
|
||||
package-unique-version-prefix
|
||||
|
||||
generate-package-cache))
|
||||
|
||||
@@ -143,10 +139,13 @@ flags."
|
||||
;; Search path for package modules. Each item must be either a directory
|
||||
;; name or a pair whose car is a directory and whose cdr is a sub-directory
|
||||
;; to narrow the search.
|
||||
(let* ((not-colon (char-set-complement (char-set #\:)))
|
||||
(environment (string-tokenize (or (getenv "GUIX_PACKAGE_PATH") "")
|
||||
not-colon))
|
||||
(channels-scm channels-go (package-path-entries)))
|
||||
(let*-values (((not-colon)
|
||||
(char-set-complement (char-set #\:)))
|
||||
((environment)
|
||||
(string-tokenize (or (getenv "GUIX_PACKAGE_PATH") "")
|
||||
not-colon))
|
||||
((channels-scm channels-go)
|
||||
(package-path-entries)))
|
||||
;; Automatically add channels and items from $GUIX_PACKAGE_PATH to Guile's
|
||||
;; search path. For historical reasons, $GUIX_PACKAGE_PATH goes to the
|
||||
;; front; channels go to the back so that they don't override Guix' own
|
||||
@@ -499,13 +498,13 @@ return its return value."
|
||||
"Return a package matching SPEC. SPEC may be a package name, or a package
|
||||
name followed by an at-sign and a version number. If the version number is not
|
||||
present, return the preferred newest version."
|
||||
(let ((name version (package-name->name+version spec)))
|
||||
(let-values (((name version) (package-name->name+version spec)))
|
||||
(%find-package spec name version)))
|
||||
|
||||
(define (specification->location spec)
|
||||
"Return the location of the highest-numbered package matching SPEC, a
|
||||
specification such as \"guile@2\" or \"emacs\"."
|
||||
(let ((name version (package-name->name+version spec)))
|
||||
(let-values (((name version) (package-name->name+version spec)))
|
||||
(match (find-package-locations name version)
|
||||
(()
|
||||
(if version
|
||||
@@ -540,8 +539,8 @@ version; if SPEC does not specify an output, return OUTPUT.
|
||||
|
||||
When OUTPUT is false and SPEC does not specify any output, return #f as the
|
||||
output."
|
||||
(let ((name version sub-drv
|
||||
(package-specification->name+version+output spec output)))
|
||||
(let-values (((name version sub-drv)
|
||||
(package-specification->name+version+output spec output)))
|
||||
(match (%find-package spec name version)
|
||||
(#f
|
||||
(values #f #f))
|
||||
@@ -553,36 +552,10 @@ output."
|
||||
(package-full-name package)
|
||||
sub-drv))))))
|
||||
|
||||
(define (specifications->packages specs)
|
||||
"Given SPECS, a list of specifications such as \"emacs@25.2\" or
|
||||
\"guile:debug\", return a list of package/output tuples."
|
||||
;; This procedure exists so users of 'guix home' don't have to write out the
|
||||
;; (map (compose list specification->package+output)... boilerplate.
|
||||
(map (compose list specification->package+output) specs))
|
||||
|
||||
(define (specifications->manifest specs)
|
||||
"Given SPECS, a list of specifications such as \"emacs@25.2\" or
|
||||
\"guile:debug\", return a profile manifest."
|
||||
;; This procedure exists mostly so users of 'guix package -m' don't have to
|
||||
;; fiddle with multiple-value returns.
|
||||
(packages->manifest
|
||||
(specifications->packages specs)))
|
||||
|
||||
(define (package-unique-version-prefix name version)
|
||||
"Search among all the versions of package NAME that are available, and
|
||||
return the shortest unambiguous version prefix to designate VERSION. If only
|
||||
one version of the package is available, return the empty string."
|
||||
(match (map package-version (find-packages-by-name name))
|
||||
((_)
|
||||
;; A single version of NAME is available, so do not specify the version
|
||||
;; number, even if the available version doesn't match VERSION.
|
||||
"")
|
||||
(versions
|
||||
;; If VERSION is the latest version, don't specify any version.
|
||||
;; Otherwise return the shortest unique version prefix. Note that this
|
||||
;; is based on the currently available packages so the result may vary
|
||||
;; over time.
|
||||
(if (every (cut version>? version <>)
|
||||
(delete version versions))
|
||||
""
|
||||
(version-unique-prefix version versions)))))
|
||||
(map (compose list specification->package+output) specs)))
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2017 Nikita <nikita@n0.is>
|
||||
;;; Copyright © 2017 Stefan Reichör <stefan@xsteve.at>
|
||||
;;; Copyright © 2018, 2021, 2022 Tobias Geerinckx-Rice <me@tobias.gr>
|
||||
;;; Copyright © 2018, 2021 Tobias Geerinckx-Rice <me@tobias.gr>
|
||||
;;; Copyright © 2019 Andrew Miloradovsky <andrew@interpretmath.pw>
|
||||
;;; Copyright © 2020 Efraim Flashner <efraim@flashner.co.il>
|
||||
;;; Copyright © 2022 Hunter Jozwiak <hunter.t.joz@gmail.com>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
@@ -29,7 +28,6 @@
|
||||
#:use-module (guix git-download)
|
||||
#:use-module (guix build-system gnu)
|
||||
#:use-module (guix build-system glib-or-gtk)
|
||||
#:use-module (guix build-system meson)
|
||||
#:use-module (gnu packages)
|
||||
#:use-module (gnu packages lisp)
|
||||
#:use-module (gnu packages ocaml)
|
||||
@@ -91,14 +89,14 @@ terminals.")
|
||||
(define-public brltty
|
||||
(package
|
||||
(name "brltty")
|
||||
(version "6.5")
|
||||
(version "6.4")
|
||||
(source
|
||||
(origin
|
||||
(method url-fetch)
|
||||
(uri
|
||||
(string-append "https://brltty.app/archive/brltty-" version ".tar.gz"))
|
||||
(sha256
|
||||
(base32 "1h62xzd5k0aaq2k4v3w93rizxnb8psvkxrlx62wr08ybwpspgp7z"))))
|
||||
(base32 "0zybi9i9izv25g0wphl0snddrhb6xl5879y4pkpjpnxq61wm9gry"))))
|
||||
(build-system glib-or-gtk-build-system)
|
||||
(arguments
|
||||
`(#:tests? #f ; No target
|
||||
@@ -318,34 +316,3 @@ works with every X Window System based GUI (depends only on libX11); or as an
|
||||
assistant for graphic designers, who need to select individual pixels.")
|
||||
;; Licensed either under Expat or GPLv2+.
|
||||
(license (list license:expat license:gpl2+))))
|
||||
|
||||
(define-public espeakup
|
||||
(package
|
||||
(name "espeakup")
|
||||
(version "0.90")
|
||||
(source (origin
|
||||
(method git-fetch)
|
||||
(uri (git-reference
|
||||
(url "https://github.com/linux-speakup/espeakup")
|
||||
(commit (string-append "v" version))))
|
||||
(file-name (git-file-name name version))
|
||||
(sha256
|
||||
(base32
|
||||
"0lmjwafvfxy07zn18v3dzjwwpnid2xffgvy2dzlwkbns8gb60ds2"))))
|
||||
(build-system meson-build-system)
|
||||
(native-inputs (list pkg-config))
|
||||
(inputs (list espeak-ng alsa-lib))
|
||||
(license license:gpl3+)
|
||||
(synopsis "Bridge for espeak and speakup")
|
||||
(description
|
||||
"Espeakup is a bridge between the speakup driver implemented in
|
||||
the Linux kernel and the espeak-ng text to speech synthesizer.
|
||||
In order for this package to work, you need to have the following
|
||||
kernel modules built:
|
||||
@itemize @bullet
|
||||
@item
|
||||
CONFIG_SPEAKUP=m
|
||||
@item
|
||||
CONFIG_SPEAKUP_SOFT=m
|
||||
@end itemize")
|
||||
(home-page "ttps://github.com/linux-speakup/espeakup")))
|
||||
|
||||
@@ -149,3 +149,32 @@ Ada system. Being an interpreter, it does not implement most representation
|
||||
clauses, and thus does not support systems programming close to the machine
|
||||
level.")
|
||||
(license license:gpl2+)))
|
||||
|
||||
(define-public python2-langkit
|
||||
(let ((commit "fe0bc8bf60dbd2937759810df76ac420d99fc15f")
|
||||
(revision "0"))
|
||||
(package
|
||||
(name "python2-langkit")
|
||||
(version (git-version "0.0.0" revision commit))
|
||||
(source (origin
|
||||
(method git-fetch)
|
||||
(uri (git-reference
|
||||
(url "https://github.com/AdaCore/langkit")
|
||||
(commit commit)))
|
||||
(sha256
|
||||
(base32
|
||||
"1abqgw2p8pb1pm54my5kkbbixfhc6l0bwajdv1xlzyrh31xki3wx"))
|
||||
(file-name (string-append name "-" version "-checkout"))))
|
||||
(build-system python-build-system)
|
||||
(propagated-inputs
|
||||
(list python2-docutils python2-enum34 python2-funcy python2-mako))
|
||||
(arguments
|
||||
`(#:python ,python-2
|
||||
#:tests? #f)) ; Tests would requite gprbuild (Ada).
|
||||
(synopsis "Semantic analysis tool generator in Python")
|
||||
(description "@code{Langkit} is a tool whose purpose is to make it easy
|
||||
to create syntactic and semantic analysis engines. Write a language
|
||||
specification in our Python DSL and Langkit will generate for you an
|
||||
Ada library with bindings for the C and Python programming languages.")
|
||||
(home-page "https://github.com/AdaCore/langkit/")
|
||||
(license license:gpl3+)))) ; and gcc runtime library exception
|
||||
|
||||
+302
-1087
File diff suppressed because it is too large
Load Diff
@@ -76,9 +76,7 @@ scripts.")
|
||||
"0gcincjvpll2qmlc906jx6mfq97s87mgi0zby0753ki0rr2ch0s8"))))
|
||||
(build-system gnu-build-system)
|
||||
(arguments
|
||||
'(;; FIXME: Some tests require network access
|
||||
#:tests? #f
|
||||
#:phases
|
||||
'(#:phases
|
||||
(modify-phases %standard-phases
|
||||
(add-before 'check 'filter-live-tests
|
||||
(lambda _
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user