1
0
forked from tribes/guix

Compare commits

..

4 Commits

Author SHA1 Message Date
Mathieu Othacehe aa34d4d28d ci: Update to the last version.
* gnu/ci.scm: Update to the master version.
2021-06-14 08:58:41 +02:00
Leo Famulari 6110751b53 nls: Mention Libera Chat in the translations.
* po/doc/guix-manual.de.po, po/doc/guix-manual.es.po, po/doc/guix-manual.fa.po,
po/doc/guix-manual.fr.po, po/doc/guix-manual.it.po, po/doc/guix-manual.ko.po,
po/doc/guix-manual.pt_BR.po, po/doc/guix-manual.ru.po, po/doc/guix-manual.sk.po,
po/doc/guix-manual.zh_CN.po: Point users to Libera Chat.
2021-05-20 16:57:35 -04:00
Tobias Geerinckx-Rice a8509d8d43 The #guix channel is hosted by Libera Chat.
* README (Contact): Update network name.
* ROADMAP: Likewise.
* doc/contributing.texi (Contributing): Likewise.
* doc/guix.texi (After System Installation): Likewise.
2021-05-20 16:57:28 -04:00
Leo Famulari 0961807915 doc: Clarify further the distinction between the web-based manuals.
As discussed on #guix IRC, several of us struggle to reliably choose the
right option based on the old labels:

https://logs.guix.gnu.org/guix/2021-04-20.log#182137

* doc/build.scm (html-manual-indexes): Try to distinguish between the
two options more clearly.
2021-05-12 15:00:06 -04:00
2236 changed files with 708751 additions and 1661350 deletions
+26 -60
View File
@@ -6,33 +6,39 @@
(sentence-end-double-space . t)
;; For use with 'bug-reference-prog-mode'.
(bug-reference-url-format . "http://bugs.gnu.org/%s")
(bug-reference-bug-regexp
. "\\(<https?://\\bugs\\.gnu\\.org/\\([0-9]+\\)>\\)")
(bug-reference-url-format . "https://bugs.gnu.org/%s")
(eval . (add-to-list 'completion-ignored-extensions ".go"))
. "<https?://\\(debbugs\\|bugs\\)\\.gnu\\.org/\\([0-9]+\\)>")
;; Emacs-Guix
(eval . (setq-local guix-directory
(locate-dominating-file default-directory
".dir-locals.el")))
;; YASnippet
(eval . (with-eval-after-load
'yasnippet
(let ((guix-yasnippets
(expand-file-name
"etc/snippets/yas"
(locate-dominating-file default-directory
".dir-locals.el"))))
(unless (member guix-yasnippets yas-snippet-dirs)
(add-to-list 'yas-snippet-dirs guix-yasnippets)
(yas-reload-all)))))
;; Geiser
;; This allows automatically setting the `geiser-guile-load-path'
;; variable when using various Guix checkouts (e.g., via git worktrees).
(geiser-repl-per-project-p . t)))
(eval . (let ((root-dir-unexpanded (locate-dominating-file
default-directory ".dir-locals.el")))
;; While Guix should in theory always have a .dir-locals.el
;; (we are reading this file, after all) there seems to be a
;; strange problem where this code "escapes" to some other buffers,
;; at least vc-mode. See:
;; https://lists.gnu.org/archive/html/guix-devel/2020-11/msg00296.html
;; Upstream report: <https://bugs.gnu.org/44698>
;; Hence the following "when", which might otherwise be unnecessary;
;; it prevents causing an error when root-dir-unexpanded is nil.
(when root-dir-unexpanded
(let* ((root-dir (expand-file-name root-dir-unexpanded))
;; Workaround for bug https://issues.guix.gnu.org/43818.
(root-dir* (directory-file-name root-dir)))
(unless (boundp 'geiser-guile-load-path)
(defvar geiser-guile-load-path '()))
(make-local-variable 'geiser-guile-load-path)
(require 'cl-lib)
(cl-pushnew root-dir* geiser-guile-load-path
:test #'string-equal)))))))
(c-mode . ((c-file-style . "gnu")))
(scheme-mode
@@ -41,24 +47,15 @@
(eval . (put 'eval-when 'scheme-indent-function 1))
(eval . (put 'call-with-prompt 'scheme-indent-function 1))
(eval . (put 'test-assert 'scheme-indent-function 1))
(eval . (put 'test-assertm 'scheme-indent-function 2))
(eval . (put 'test-assertm 'scheme-indent-function 1))
(eval . (put 'test-equalm 'scheme-indent-function 1))
(eval . (put 'test-equal 'scheme-indent-function 1))
(eval . (put 'test-eq 'scheme-indent-function 1))
(eval . (put 'call-with-input-string 'scheme-indent-function 1))
(eval . (put 'call-with-port 'scheme-indent-function 1))
(eval . (put 'guard 'scheme-indent-function 1))
(eval . (put 'lambda* 'scheme-indent-function 1))
(eval . (put 'substitute* 'scheme-indent-function 1))
(eval . (put 'match-record 'scheme-indent-function 3))
(eval . (put 'match-record-lambda 'scheme-indent-function 2))
;; TODO: Contribute these to Emacs' scheme-mode.
(eval . (put 'let-keywords 'scheme-indent-function 3))
;; 'modify-inputs' and its keywords.
(eval . (put 'modify-inputs 'scheme-indent-function 1))
(eval . (put 'replace 'scheme-indent-function 1))
(eval . (put 'match-record 'scheme-indent-function 2))
;; 'modify-phases' and its keywords.
(eval . (put 'modify-phases 'scheme-indent-function 1))
@@ -115,16 +112,13 @@
(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))
(eval . (put 'let-system 'scheme-indent-function 1))
(eval . (put 'with-build-variables 'scheme-indent-function 2))
(eval . (put 'with-database 'scheme-indent-function 2))
(eval . (put 'call-with-database 'scheme-indent-function 1))
@@ -146,39 +140,11 @@
(eval . (put 'with-paginated-output-port 'scheme-indent-function 1))
(eval . (put 'with-shepherd-action 'scheme-indent-function 3))
(eval . (put 'with-http-server 'scheme-indent-function 1))
;; This notably allows '(' in Paredit to not insert a space when the
;; preceding symbol is one of these.
(eval . (modify-syntax-entry ?~ "'"))
(eval . (modify-syntax-entry ?$ "'"))
(eval . (modify-syntax-entry ?+ "'"))
;; Emacs 28 changed the behavior of 'lisp-fill-paragraph', which causes the
;; first line of package descriptions to extrude past 'fill-column', and
;; somehow that is deemed more correct upstream (see:
;; https://issues.guix.gnu.org/56197).
(eval . (progn
(require 'lisp-mode)
(defun emacs27-lisp-fill-paragraph (&optional justify)
(interactive "P")
(or (fill-comment-paragraph justify)
(let ((paragraph-start
(concat paragraph-start
"\\|\\s-*\\([(;\"]\\|\\s-:\\|`(\\|#'(\\)"))
(paragraph-separate
(concat paragraph-separate "\\|\\s-*\".*[,\\.]$"))
(fill-column (if (and (integerp emacs-lisp-docstring-fill-column)
(derived-mode-p 'emacs-lisp-mode))
emacs-lisp-docstring-fill-column
fill-column)))
(fill-paragraph justify))
;; Never return nil.
t))
(setq-local fill-paragraph-function #'emacs27-lisp-fill-paragraph)))))
(eval . (modify-syntax-entry ?+ "'"))))
(emacs-lisp-mode . ((indent-tabs-mode . nil)))
(texinfo-mode . ((indent-tabs-mode . nil)
(fill-column . 72))))
-16
View File
@@ -1,16 +0,0 @@
root = true
[*.{c,h,cpp,hpp,el,scm,ac,am,m4,po}{,.in}]
end_of_line = lf
insert_final_newline = true
charset = utf-8
trim_trailing_whitespace = true
[*.{c,h,cpp,hpp,ac,am,m4,el,scm}{,.in}]
max_line_length = 85
[*.{c,h,cpp,hpp,ac,m4,el,scm}{,.in}]
indent_style = space
[*.{c,h,cpp,hpp}{,.in}]
indent_size = 4
-3
View File
@@ -1,3 +0,0 @@
*.scm diff=scheme
*.scm.in diff=scheme
*.texi diff=texinfo
-6
View File
@@ -68,14 +68,12 @@
/doc/version.texi
/doc/version-*.texi
/etc/committer.scm
/etc/teams.scm
/etc/gnu-store.mount
/etc/guix-daemon.cil
/etc/guix-daemon.conf
/etc/guix-daemon.service
/etc/guix-publish.conf
/etc/guix-publish.service
/etc/guix-gc.service
/etc/init.d/guix-daemon
/etc/openrc/guix-daemon
/guix-*
@@ -134,7 +132,6 @@
/pre-inst-env
/release-*
/scripts/guix
/t-*/
/test-env
/test-tmp
/tests/*.trs
@@ -146,7 +143,6 @@ Makefile
Makefile.in
config.cache
stamp-h[0-9]
.am[0-9]*/
.dirstamp
.deps
tmp
@@ -158,5 +154,3 @@ tmp
/gnu/packages/bootstrap
/gnu/packages/aux-files/guile-guile-launcher.o
/guile
.DS_Store
.mumi/current-issue
+53 -24
View File
@@ -4,20 +4,36 @@
(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"))
("2A39 3FFF 68F4 EF7A 3D29 12AF 6F51 20A0 22FB B2D5"
(name "ajgrf"))
("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"
(name "arunisaac"))
(;; primary: "3B12 9196 AE30 0C3C 0E90 A26F A715 5567 3271 9948"
"9A2B 401E D001 0650 1584 BAAC 8BC4 F447 6E8A 8E00"
(name "atheia"))
(;; primary: "BE62 7373 8E61 6D6D 1B3A 08E8 A21A 0202 4881 6103"
"39B3 3C8D 9448 0D2D DCC2 A498 8B44 A0CD C7B9 56F2"
(name "bandali"))
(;; primary: "34FF 38BC D151 25A6 E340 A0B5 3453 2F9F AFCA 8B8E"
"A3A4 B419 0074 087C A7DE 5698 BC45 CA67 E2F8 D007"
"A0C5 E352 2EF8 EF5C 64CD B7F0 FD73 CAC7 19D3 2566"
(name "bavier"))
("45CC 63B8 5258 C9D5 5F34 B239 D37D 0EA7 CECC 3912"
(name "biscuolo"))
("7988 3B9F 7D6A 4DBF 3719 0367 2506 A96C CF63 0B21"
(name "boskovits"))
("E82A C026 95D6 FF02 43CA 1E5C F6C5 2DD1 BA27 CB87"
(name "brettgilio"))
(;; primary: "8929 BBC5 73CD 9206 3DDD 979D 3D36 CAA0 116F 0F99"
"1C9B F005 1A1A 6A44 5257 599A A949 03A1 66A1 8FAE"
(name "bricewge"))
(;; primary: "0401 7A2A 6D9A 0CCD C81D 8EC2 96AB 007F 1A7E D999"
"09CD D25B 5244 A376 78F6 EEA8 0CC5 2153 1979 91A5"
(name "carl"))
@@ -30,52 +46,63 @@
(;; 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)"))
("53C4 1E6E 41AA FE55 335A CA5E 446A 2ED4 D940 BF14"
(name "daviwil"))
("A28B F40C 3E55 1372 662D 14F7 41AA E7DC CA3D 8351"
(name "efraim"))
(;; primary: "2453 02B1 BAB1 F867 FDCA 96BC 8F3F 861F 82EB 7A9A"
"CBC5 9C66 EC27 B971 7940 6B3E 6BE8 208A DF21 FE3F"
(name "glv"))
(;; primary: "220F 98D9 5E86 204C 0036 DA7B 6DEC 4360 408B 4185"
"F4C2 D1DF 3FDE EA63 D1D3 0776 ACC6 6D09 CA52 8292"
(name "hako"))
("2219 43F4 9E9F 276F 9499 3382 BF28 6CB6 593E 5FFD"
(name "hoebjo"))
("B943 509D 633E 80DD 27FC 4EED 634A 8DFF D3F6 31DF"
(name "htgoebel"))
("7440 26BA 7CA3 C668 E940 1D53 0B43 1E98 3705 6942"
(name "ipetkov"))
(;; primary: "66A5 6D9C 9A98 BE7F 719A B401 2652 5665 AE72 7D37"
"0325 78A6 8298 94E7 2AA2 66F5 D415 BF25 3B51 5976"
(name "iyzsong"))
("1A85 8392 E331 EAFD B8C2 7FFB F3C1 A0D9 C1D6 5273"
(name "janneke"))
("3B1D 7F19 E36B B60C 0F5B 2CA9 A52A A2B4 77B6 DD35"
(name "jgart"))
(;; primary: "1BA4 08C5 8BF2 0EA7 3179 635A 865D C0A3 DED9 B5D0"
"E31D 9DDE EBA5 4A14 8A20 4550 DA45 97F9 47B4 1025"
(name "jlicht"))
("8141 6036 E81A 5CF7 8F80 1071 ECFC 8398 8B4E 4B9F"
(name "jonsger"))
("3924 8CD8 41C6 3CC3 36DC AF2F 505E 40B9 1617 1A8A"
(name "jpoiret"))
("83B6 703A DCCA 3B69 4BCE 2DA6 E6A5 EE3C 1946 7A0D"
(name "kkebreau"))
("017D 74E2 7F58 5696 3801 781D F663 943E 08D8 092A"
(name "lbraun"))
("CA4F 8CF4 37D7 478F DA05 5FD4 4213 7701 1A37 8446"
(name "lbraun (professional)"))
("ACC2 3BA0 59F7 CCF4 08F0 43AD 442A 84B8 C70E 2F87"
(name "lilyp"))
(name "leoprikler"))
("45E5 75FA 53EA 8BD6 1BCE 0B4E 3ADC 75F0 13D6 78F9"
(name "leungbk"))
(;; primary: "4F71 6F9A 8FA2 C80E F1B5 E1BA 5E35 F231 DE1A C5E0"
"B051 5948 F1E7 D3C1 B980 38A0 2646 FA30 BACA 7F08"
(name "lfam"))
("148B CB8B D80B FB16 B1DE 0E91 45A8 B1E8 6BCD 10A6"
(name "lle_bout"))
("8887 84C4 1459 ACCB 83E7 E84C 634C 6E89 79FA BEC2"
(name "m1gu3l"))
("CBF5 9755 CBE7 E7EF EF18 3FB1 DD40 9A15 D822 469D"
(name "marusich"))
("BBB0 2DDF 2CEA F6A8 0D1D E643 A2A0 6DF2 A33A 54FA"
(name "mbakke"))
("D919 0965 CE03 199E AF28 B3BE 7CEF 2984 7562 C516"
(name "mhw"))
("B845 5B7F FAD5 E8E9 5DEF 4296 637B 0B13 8065 B68A"
(name "monego"))
("4008 6A7E 0252 9B60 31FB 8607 8354 7635 3176 9CA6"
(name "mothacehe"))
(;; primary: "F5BC 5534 C36F 0087 B39D 36EF 1C9D C4FE B9DB 7C4B"
"F5DA 2032 4B87 3D0B 7A38 7672 0DB0 FF88 4F55 6D79"
(name "nckx"))
("E576 BFB2 CF6E B13D F571 33B9 E315 A758 4613 1564"
(name "niedzejkob"))
("ED0E F1C8 E126 BA83 1B48 5FE9 DA00 B4F0 48E9 2F2D"
(name "ngz"))
("CEF4 CB91 4856 BA38 0A20 A7E2 3008 88CB 39C6 3817"
@@ -83,11 +110,15 @@
(;; primary: "41CA 12EA DE0C F33F 6885 A58F 5719 6E37 E00B 77FD"
"72D5 3D81 8CB6 F4A1 7258 374C A8FC 9E44 7F4F 7D54"
(name "planglois"))
(;; primary: "7E9F 5BF6 1680 4367 127B 7A87 F9E6 9FB8 5A75 54F1"
"A420 7B56 C255 109F 2CB3 157E 4990 97AE 5EA8 15D9"
(name "podiki"))
(;; primary: "B68B DF22 73F9 DA0E 63C1 8A32 515B F416 9242 D600"
"C699 ED09 E51B CE89 FD1D A078 AAC7 E891 896B 568A"
(name "pgarlick"))
("3A86 380E 58A8 B942 8D39 60E1 327C 1EF3 8DF5 4C32"
(name "phant0mas"))
("CD2D 5EAA A98C CB37 DA91 D6B0 5F58 1664 7F8B E551"
(name "raghavgururajan"))
("74D6 A930 F44B 9B84 9EA5 5606 C166 AA49 5F7F 189C"
(name "reepca"))
("BCA6 89B6 3655 3801 C3C6 2150 197A 5888 235F ACAC"
(name "rekado"))
(;; From commit cc51c03ff867d4633505354819c6d88af88bf919 (March 2020).
@@ -107,6 +138,4 @@
(name "vagrantc"))
(;; primary: "C955 CC5D C048 7FB1 7966 40A9 199A F6A3 67E9 4ABB"
"7238 7123 8EAC EB63 4548 5857 167F 8EA5 001A FA9C"
(name "wigust"))
("705A 29B7 01EE 410E B6F9 236E 92F1 D22C 608E E7E5"
(name "zimoun"))))
(name "wigust"))))
+4 -13
View File
@@ -15,7 +15,6 @@ Ben Woodcroft <donttrustben@gmail.com>
Ben Woodcroft <donttrustben@gmail.com> <b.woodcroft@uq.edu.au>
Ben Woodcroft <donttrustben@gmail.com> <donttrustben near gmail.com>
Brett Gilio <brettg@gnu.org> <brettg@posteo.net>
Christine Lemmer-Webber <cwebber@dustycloud.org>
Claes Wallin (韋嘉誠) <claes.wallin@greatsinodevelopment.com>
Cyprien Nicolas <cyprien@nicolas.tf> <c.nicolas+gitorious@gmail.com>
Daniel Pimentel <d4n1@d4n1.org> <d4n1@member.fsf.org>
@@ -25,8 +24,8 @@ David Thompson <davet@gnu.org> <dthompson2@worcester.edu>
David Thompson <davet@gnu.org> <dthompson@member.fsf.org>
David Thompson <davet@gnu.org> <dthompson@vistahigherlearning.com>
Deck Pickard <deck.r.pickard@gmail.com> <nebu@kipple>
Eric Bavier <bavier@posteo.net> <ericbavier@gmail.com>
Eric Bavier <bavier@posteo.net> <bavier@member.fsf.org>
Eric Bavier <bavier@member.fsf.org> <ericbavier@gmail.com>
Eric Bavier <bavier@member.fsf.org> <bavier@posteo.net>
Eric Dvorsak <eric@dvorsak.fr> <yenda1@gmail.com>
George Clemmer <myglc2@gmail.com>
ison <ison@airmail.cc> <ison111@protonmail.com>
@@ -39,23 +38,16 @@ Joshua Grant <tadni@riseup.net> <gzg@riseup.net>
Joshua Grant <tadni@riseup.net> <jgrant@parenthetical.io>
Joshua Grant <tadni@riseup.net> <tadnimi@gmail.com>
Joshua Grant <tadni@riseup.net> <youlysses@riseup.net>
Juliana Sims <juli@incana.org> <jtsims@protonmail.com>
Kei Kebreau <kkebreau@posteo.net>
Kei Kebreau <kei@openmailbox.org> <kkebreau@posteo.net>
Leo Famulari <leo@famulari.name> <lfamular@gmail.com>
Liliana Marie Prikler <liliana.prikler@gmail.com>
Liliana Marie Prikler <liliana.prikler@gmail.com> Leo Prikler <leo.prikler@student.tugraz.at>
Ludovic Courtès <ludo@gnu.org> <ludovic.courtes@inria.fr>
Marek Benc <dusxmt@gmx.com> <merkur32@gmail.com>
Marius Bakke <marius@gnu.org> <mbakke@fastmail.com>
Marius Bakke <marius@gnu.org> <m.bakke@warwick.ac.uk>
Marius Bakke <marius@gnu.org> <marius.bakke@usit.uio.no>
Marius Bakke <marius@gnu.org> <mbakke@berlin.guixsd.org>
Marius Bakke <mbakke@fastmail.com> <m.bakke@warwick.ac.uk>
Mathieu Lirzin <mthl@gnu.org> <mthl@openmailbox.org>
Mathieu Lirzin <mthl@gnu.org> <mathieu.lirzin@openmailbox.org>
Mathieu Othacehe <m.othacehe@gmail.com>
Mathieu Othacehe <mathieu.othacehe@parrot.com>
Mathieu Othacehe <othacehe@gnu.org>
Matthew James Kraai <kraai@ftbfs.org>
Nikita Karetnikov <nikita@karetnikov.org> <nikita.karetnikov@gmail.com>
nikita <nikita@n0.is>
nikita <nikita@n0.is> ng0 <ng0@n0.is>
@@ -92,4 +84,3 @@ Thomas Danckaert <thomas.danckaert@gmail.com> <post@thomasdanckaert.be>
Tobias Geerinckx-Rice <me@tobias.gr> <tobias.geerinckx.rice@gmail.com>
Tomáš Čech <sleep_walker@gnu.org> <sleep_walker@suse.cz>
Vincent Legoll <vincent.legoll@gmail.com> <vincent.legoll@idgrilles.fr>
Zheng Junjie <873216071@qq.com> Z572 <873216071@qq.com>
-3
View File
@@ -1,3 +0,0 @@
((debbugs-host . "debbugs.gnu.org")
(patch-email-address . "guix-patches@gnu.org")
(mumi-host . "issues.guix.gnu.org"))
-10
View File
@@ -1,10 +0,0 @@
# This config file allows for Patchwork integration with
# https://patches.guix-patches.cbaines.net/.
[settings]
project: guix-patches
patchwork_url: https://patches.guix-patches.cbaines.net
add_signoff: False
# TODO: enable check_patch
check_patch: False
ignore_bad_tags: True
+66 -91
View File
@@ -1,103 +1,78 @@
Important: to avoid polarizing/hurtful discussions in our public spaces, any
matter pertaining to our use of this Code of Conduct should be brought
privately to the Guix maintainers at guix-maintainers@gnu.org. Failure to do
so will be considered as a violation of this Code of Conduct.
Contributor Covenant Code of Conduct
Note: In the sequel, "project" refers to GNU Guix, and "project
maintainer(s)" refers to maintainer(s) of GNU Guix.
Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, caste, color, religion, or sexual
identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
education, socio-economic status, nationality, personal appearance, race,
religion, or sexual identity and orientation.
Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the overall
community
Examples of behavior that contributes to creating a positive environment
include:
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or advances of
any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others private information, such as a physical or email address,
without their explicit permission
* Publishing others private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
guix-maintainers@gnu.org.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
1. Correction
Community Impact: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
Consequence: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
2. Warning
Community Impact: A violation through a single incident or series of
actions.
Consequence: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or permanent
ban.
3. Temporary Ban
Community Impact: A serious violation of community standards, including
sustained inappropriate behavior.
Consequence: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
4. Permanent Ban
Community Impact: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
Consequence: A permanent ban from any sort of public interaction within the
community.
Attribution
This Code of Conduct is adapted from the Contributor Covenant,
version 2.1, available at
https://www.contributor-covenant.org/version/2/1/code_of_conduct.html.
Community Impact Guidelines were inspired by
Mozillas code of conduct enforcement ladder.
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at guix-maintainers@gnu.org. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the projects leadership.
Attribution
This Code of Conduct is adapted from the Contributor Covenant, version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
+66 -283
View File
@@ -1,5 +1,5 @@
# GNU Guix --- Functional package management for GNU
# Copyright © 2012-2023 Ludovic Courtès <ludo@gnu.org>
# Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo@gnu.org>
# Copyright © 2013 Andreas Enge <andreas@enge.fr>
# Copyright © 2015, 2017 Alex Kost <alezost@gmail.com>
# Copyright © 2016, 2018 Mathieu Lirzin <mthl@gnu.org>
@@ -7,16 +7,14 @@
# Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
# Copyright © 2017 Leo Famulari <leo@famulari.name>
# Copyright © 2017 Ricardo Wurmus <rekado@elephly.net>
# Copyright © 2017, 2020, 2023 Janneke Nieuwenhuizen <janneke@gnu.org>
# Copyright © 2017, 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
# Copyright © 2017 Arun Isaac <arunisaac@systemreboot.net>
# Copyright © 2018 Nikita <nikita@n0.is>
# Copyright © 2018 Julien Lepiller <julien@lepiller.eu>
# Copyright © 2018 Oleg Pykhalov <go.wigust@gmail.com>
# Copyright © 2018 Alex Vong <alexvong1995@gmail.com>
# Copyright © 2019 Efraim Flashner <efraim@flashner.co.il>
# Copyright © 2020, 2021, 2023 Maxim Cournoyer <maxim.cournoyer@gmail.com>
# Copyright © 2021 Chris Marusich <cmmarusich@gmail.com>
# Copyright © 2021 Andrew Tropin <andrew@trop.in>
#
# This file is part of GNU Guix.
#
@@ -82,7 +80,6 @@ MODULES = \
guix/base64.scm \
guix/ci.scm \
guix/cpio.scm \
guix/cpu.scm \
guix/deprecation.scm \
guix/docker.scm \
guix/records.scm \
@@ -100,7 +97,6 @@ MODULES = \
guix/bzr-download.scm \
guix/git-download.scm \
guix/hg-download.scm \
guix/hash.scm \
guix/swh.scm \
guix/monads.scm \
guix/monad-repl.scm \
@@ -112,7 +108,6 @@ MODULES = \
guix/derivations.scm \
guix/grafts.scm \
guix/repl.scm \
guix/rpm.scm \
guix/transformations.scm \
guix/inferior.scm \
guix/describe.scm \
@@ -131,34 +126,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/agda.scm \
guix/build-system/android-ndk.scm \
guix/build-system/ant.scm \
guix/build-system/cargo.scm \
guix/build-system/channel.scm \
guix/build-system/chicken.scm \
guix/build-system/clojure.scm \
guix/build-system/cmake.scm \
guix/build-system/dub.scm \
guix/build-system/dune.scm \
guix/build-system/elm.scm \
guix/build-system/emacs.scm \
guix/build-system/font.scm \
guix/build-system/go.scm \
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 \
guix/build-system/copy.scm \
guix/build-system/glib-or-gtk.scm \
@@ -170,7 +152,6 @@ MODULES = \
guix/build-system/maven.scm \
guix/build-system/node.scm \
guix/build-system/perl.scm \
guix/build-system/pyproject.scm \
guix/build-system/python.scm \
guix/build-system/renpy.scm \
guix/build-system/ocaml.scm \
@@ -178,11 +159,9 @@ MODULES = \
guix/build-system/waf.scm \
guix/build-system/r.scm \
guix/build-system/rakudo.scm \
guix/build-system/rebar.scm \
guix/build-system/ruby.scm \
guix/build-system/scons.scm \
guix/build-system/texlive.scm \
guix/build-system/tree-sitter.scm \
guix/build-system/trivial.scm \
guix/ftp-client.scm \
guix/http-client.scm \
@@ -197,7 +176,6 @@ MODULES = \
guix/diagnostics.scm \
guix/ui.scm \
guix/status.scm \
guix/build/agda-build-system.scm \
guix/build/android-ndk-build-system.scm \
guix/build/ant-build-system.scm \
guix/build/download.scm \
@@ -208,7 +186,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 \
@@ -226,33 +203,28 @@ MODULES = \
guix/build/gnu-dist.scm \
guix/build/guile-build-system.scm \
guix/build/maven-build-system.scm \
guix/build/minetest-build-system.scm \
guix/build/node-build-system.scm \
guix/build/perl-build-system.scm \
guix/build/pyproject-build-system.scm \
guix/build/python-build-system.scm \
guix/build/ocaml-build-system.scm \
guix/build/qt-build-system.scm \
guix/build/r-build-system.scm \
guix/build/renpy-build-system.scm \
guix/build/rakudo-build-system.scm \
guix/build/rebar-build-system.scm \
guix/build/ruby-build-system.scm \
guix/build/scons-build-system.scm \
guix/build/texlive-build-system.scm \
guix/build/tree-sitter-build-system.scm \
guix/build/waf-build-system.scm \
guix/build/haskell-build-system.scm \
guix/build/julia-build-system.scm \
guix/build/kconfig.scm \
guix/build/linux-module-build-system.scm \
guix/build/store-copy.scm \
guix/build/json.scm \
guix/build/pack.scm \
guix/build/utils.scm \
guix/build/union.scm \
guix/build/profiles.scm \
guix/build/compile.scm \
guix/build/rpath.scm \
guix/build/cvs.scm \
guix/build/svn.scm \
guix/build/syscalls.scm \
@@ -263,7 +235,6 @@ MODULES = \
guix/build/emacs-utils.scm \
guix/build/java-utils.scm \
guix/build/lisp-utils.scm \
guix/build/meson-configuration.scm \
guix/build/maven/java.scm \
guix/build/maven/plugin.scm \
guix/build/maven/pom.scm \
@@ -277,26 +248,20 @@ MODULES = \
guix/import/cpan.scm \
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 \
guix/import/github.scm \
guix/import/gnome.scm \
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 \
guix/import/minetest.scm \
guix/import/opam.scm \
guix/import/print.scm \
guix/import/pypi.scm \
guix/import/stackage.scm \
guix/import/test.scm \
guix/import/texlive.scm \
guix/import/utils.scm \
guix/scripts.scm \
@@ -306,7 +271,6 @@ MODULES = \
guix/scripts/archive.scm \
guix/scripts/import.scm \
guix/scripts/package.scm \
guix/scripts/locate.scm \
guix/scripts/install.scm \
guix/scripts/remove.scm \
guix/scripts/upgrade.scm \
@@ -322,35 +286,24 @@ MODULES = \
guix/scripts/refresh.scm \
guix/scripts/repl.scm \
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/home.scm \
guix/scripts/home/edit.scm \
guix/scripts/home/import.scm \
guix/scripts/system/reconfigure.scm \
guix/scripts/lint.scm \
guix/scripts/challenge.scm \
guix/scripts/import/crate.scm \
guix/scripts/import/cpan.scm \
guix/scripts/import/cran.scm \
guix/scripts/import/egg.scm \
guix/scripts/import/elm.scm \
guix/scripts/import/elpa.scm \
guix/scripts/import/gem.scm \
guix/scripts/import/gnu.scm \
guix/scripts/import/go.scm \
guix/scripts/import/hackage.scm \
guix/scripts/import/hexpm.scm \
guix/scripts/import/json.scm \
guix/scripts/import/minetest.scm \
guix/scripts/import/opam.scm \
guix/scripts/import/pypi.scm \
guix/scripts/import/stackage.scm \
guix/scripts/import/texlive.scm \
guix/scripts/environment.scm \
guix/scripts/shell.scm \
guix/scripts/publish.scm \
guix/scripts/edit.scm \
guix/scripts/size.scm \
@@ -410,18 +363,10 @@ AUX_FILES = \
gnu/packages/aux-files/chromium/master-preferences.json \
gnu/packages/aux-files/emacs/guix-emacs.el \
gnu/packages/aux-files/guix.vim \
gnu/packages/aux-files/linux-libre/6.4-arm.conf \
gnu/packages/aux-files/linux-libre/6.4-arm64.conf \
gnu/packages/aux-files/linux-libre/6.4-i686.conf \
gnu/packages/aux-files/linux-libre/6.4-x86_64.conf \
gnu/packages/aux-files/linux-libre/6.1-arm.conf \
gnu/packages/aux-files/linux-libre/6.1-arm64.conf \
gnu/packages/aux-files/linux-libre/6.1-i686.conf \
gnu/packages/aux-files/linux-libre/6.1-x86_64.conf \
gnu/packages/aux-files/linux-libre/5.15-arm.conf \
gnu/packages/aux-files/linux-libre/5.15-arm64.conf \
gnu/packages/aux-files/linux-libre/5.15-i686.conf \
gnu/packages/aux-files/linux-libre/5.15-x86_64.conf \
gnu/packages/aux-files/linux-libre/5.11-arm.conf \
gnu/packages/aux-files/linux-libre/5.11-arm64.conf \
gnu/packages/aux-files/linux-libre/5.11-i686.conf \
gnu/packages/aux-files/linux-libre/5.11-x86_64.conf \
gnu/packages/aux-files/linux-libre/5.10-arm.conf \
gnu/packages/aux-files/linux-libre/5.10-arm64.conf \
gnu/packages/aux-files/linux-libre/5.10-i686.conf \
@@ -437,13 +382,12 @@ AUX_FILES = \
gnu/packages/aux-files/linux-libre/4.14-arm.conf \
gnu/packages/aux-files/linux-libre/4.14-i686.conf \
gnu/packages/aux-files/linux-libre/4.14-x86_64.conf \
gnu/packages/aux-files/linux-libre/4.9-i686.conf \
gnu/packages/aux-files/linux-libre/4.9-x86_64.conf \
gnu/packages/aux-files/linux-libre/4.4-i686.conf \
gnu/packages/aux-files/linux-libre/4.4-x86_64.conf \
gnu/packages/aux-files/pack-audit.c \
gnu/packages/aux-files/python/sanity-check.py \
gnu/packages/aux-files/python/sitecustomize.py \
gnu/packages/aux-files/renpy/renpy.in \
gnu/packages/aux-files/run-in-namespace.c \
gnu/packages/aux-files/xml/patch-catalog-xml.xsl \
gnu/packages/aux-files/xml/docbook-xml/catalog-4.1.2.xml
gnu/packages/aux-files/run-in-namespace.c
# Templates, examples.
EXAMPLES = \
@@ -454,9 +398,6 @@ EXAMPLES = \
gnu/system/examples/desktop.tmpl \
gnu/system/examples/lightweight-desktop.tmpl \
gnu/system/examples/docker-image.tmpl \
gnu/system/examples/plasma.tmpl \
gnu/system/examples/raspberry-pi-64.tmpl \
gnu/system/examples/raspberry-pi-64-nfs-root.tmpl \
gnu/system/examples/vm-image.tmpl
GOBJECTS = $(MODULES:%.scm=%.go) guix/config.go $(dist_noinst_DATA:%.scm=%.go)
@@ -494,7 +435,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 \
@@ -509,8 +449,6 @@ SCM_TESTS = \
tests/debug-link.scm \
tests/derivations.scm \
tests/discovery.scm \
tests/egg.scm \
tests/elm.scm \
tests/elpa.scm \
tests/file-systems.scm \
tests/gem.scm \
@@ -519,19 +457,14 @@ SCM_TESTS = \
tests/git-authenticate.scm \
tests/glob.scm \
tests/gnu-maintenance.scm \
tests/go.scm \
tests/grafts.scm \
tests/graph.scm \
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 \
tests/import-utils.scm \
tests/inferior.scm \
tests/lint.scm \
tests/minetest.scm \
tests/modules.scm \
tests/monads.scm \
tests/nar.scm \
@@ -546,19 +479,12 @@ SCM_TESTS = \
tests/profiles.scm \
tests/publish.scm \
tests/pypi.scm \
tests/read-print.scm \
tests/records.scm \
tests/rpm.scm \
tests/scripts.scm \
tests/search-paths.scm \
tests/services.scm \
tests/services/file-sharing.scm \
tests/services/configuration.scm \
tests/services/lightdm.scm \
tests/services/linux.scm \
tests/services/pam-mount.scm \
tests/services/telephony.scm \
tests/services/vpn.scm \
tests/sets.scm \
tests/size.scm \
tests/status.scm \
@@ -570,7 +496,6 @@ SCM_TESTS = \
tests/swh.scm \
tests/syscalls.scm \
tests/system.scm \
tests/style.scm \
tests/texlive.scm \
tests/transformations.scm \
tests/ui.scm \
@@ -580,12 +505,6 @@ SCM_TESTS = \
tests/uuid.scm \
tests/workers.scm
if HAVE_GUILE_LIB
SCM_TESTS += tests/go.scm
else
EXTRA_DIST += tests/go.scm
endif
if BUILD_DAEMON_OFFLOAD
SCM_TESTS += tests/offload.scm
else
@@ -599,24 +518,17 @@ SH_TESTS = \
tests/guix-gc.sh \
tests/guix-git-authenticate.sh \
tests/guix-hash.sh \
tests/guix-locate.sh \
tests/guix-pack.sh \
tests/guix-pack-localstatedir.sh \
tests/guix-pack-relocatable.sh \
tests/guix-package.sh \
tests/guix-package-aliases.sh \
tests/guix-package-net.sh \
tests/guix-style.sh \
tests/guix-system.sh \
tests/guix-home.sh \
tests/guix-archive.sh \
tests/guix-authenticate.sh \
tests/guix-environment.sh \
tests/guix-environment-container.sh \
tests/guix-refresh.sh \
tests/guix-shell.sh \
tests/guix-shell-export-manifest.sh \
tests/guix-time-machine.sh \
tests/guix-graph.sh \
tests/guix-describe.sh \
tests/guix-repl.sh \
@@ -667,8 +579,7 @@ check-system: $(GOBJECTS)
dist_pkgdata_DATA = \
etc/substitutes/berlin.guix.gnu.org.pub \
etc/substitutes/ci.guix.gnu.org.pub \
etc/substitutes/ci.guix.info.pub \
etc/substitutes/bordeaux.guix.gnu.org.pub
etc/substitutes/ci.guix.info.pub
# Bash completion file.
dist_bashcompletion_DATA = etc/completion/bash/guix \
@@ -684,50 +595,43 @@ 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 \
CODE-OF-CONDUCT \
.dir-locals.el \
.guix-authorizations \
.guix-channel \
scripts/guix.in \
etc/guix-install.sh \
etc/news.scm \
etc/release-manifest.scm \
etc/system-tests.scm \
etc/historical-authorizations \
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/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/config.rpath \
build-aux/convert-xref.scm \
build-aux/generate-authors.scm \
build-aux/test-driver.scm \
build-aux/update-NEWS.scm \
build-aux/update-guix-package.scm \
doc/build.scm \
etc/disarchive-manifest.scm \
etc/guix-install.sh \
etc/historical-authorizations \
etc/news.scm \
etc/hurd-manifest.scm \
etc/kernels-manifest.scm \
etc/release-manifest.scm \
etc/source-manifest.scm \
etc/system-tests.scm \
etc/time-travel-manifest.scm \
scripts/guix.in \
tests/cve-sample.json \
tests/keys/civodul.pub \
tests/keys/dsa.pub \
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 \
build-aux/update-NEWS.scm \
tests/test.drv \
tests/signing-key.pub \
tests/signing-key.sec \
tests/cve-sample.json \
tests/civodul.key \
tests/rsa.key \
tests/dsa.key \
tests/ed25519.key \
tests/ed25519.sec \
tests/ed25519bis.key \
tests/ed25519bis.sec \
build-aux/config.rpath \
bootstrap \
doc/build.scm \
$(TESTS)
if !BUILD_DAEMON_OFFLOAD
@@ -751,110 +655,15 @@ CLEANFILES = \
# the whole thing. Likewise, set 'XDG_CACHE_HOME' to avoid loading possibly
# stale files from ~/.cache/guile/ccache.
%.go: make-go ; @:
make-go: make-core-go make-packages-go make-system-go make-cli-go
# Define a rule to build a subset of the .go files.
define guile-compilation-rule
$(1): $(2)
$(AM_V_at)echo "Compiling Scheme modules..." ; \
unset GUILE_LOAD_COMPILED_PATH ; \
XDG_CACHE_HOME=/nowhere \
host=$(host) srcdir="$(top_srcdir)" \
$(top_builddir)/pre-inst-env \
$(GUILE) -L "$(top_builddir)" -L "$(top_srcdir)" \
--no-auto-compile \
-s "$(top_srcdir)"/build-aux/compile-all.scm \
--total $(words $(MODULES)) \
--completed $(3) \
$$(filter %.scm,$$^)
endef
# Split compilation in several steps, each of which building a subset of
# $(MODULES). The main goal is to reduce peak memory consumption, as reported
# in <https://issues.guix.gnu.org/48963>. Each 'eval' call below creates a
# 'make-*-go' phony target that builds the corresponding subset.
first_fifth := \
gnu/packages/a% gnu/packages/b% gnu/packages/c%
second_fifth := \
gnu/packages/d% gnu/packages/e% gnu/packages/f%
third_fifth := \
gnu/packages/g% gnu/packages/h% gnu/packages/i%
fourth_fifth := \
gnu/packages/j% gnu/packages/k% gnu/packages/l% gnu/packages/m% \
gnu/packages/n% gnu/packages/o%
MODULES_CORE := guix.scm $(filter-out guix/scripts/%,$(filter guix/%,$(MODULES)))
MODULES_PACKAGES1 := $(filter $(first_fifth),$(MODULES))
MODULES_PACKAGES2 := $(filter $(second_fifth),$(MODULES))
MODULES_PACKAGES3 := $(filter $(third_fifth),$(MODULES))
MODULES_PACKAGES4 := $(filter $(fourth_fifth),$(MODULES))
MODULES_PACKAGES5 := $(filter-out $(first_fifth) $(second_fifth) \
$(third_fifth) $(fourth_fifth), \
$(filter gnu/packages/%,$(MODULES)))
MODULES_PACKAGES := $(MODULES_PACKAGES1) $(MODULES_PACKAGES2) \
$(MODULES_PACKAGES3) $(MODULES_PACKAGES4) \
$(MODULES_PACKAGES5)
MODULES_SYSTEM := gnu.scm $(filter-out gnu/packages/%,$(filter gnu/%,$(MODULES)))
MODULES_CLI := $(filter guix/scripts/%,$(MODULES))
MODULES_PO := guix/build/po.scm
$(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, \
$(words $(MODULES_CORE))))
.PHONY: make-packages1-go
$(eval $(call guile-compilation-rule,make-packages2-go, \
$(MODULES_PACKAGES2) make-core-go make-packages1-go, \
$(words $(MODULES_CORE) $(MODULES_PACKAGES1))))
.PHONY: make-packages2-go
$(eval $(call guile-compilation-rule,make-packages3-go, \
$(MODULES_PACKAGES3) make-core-go make-packages1-go make-packages2-go, \
$(words $(MODULES_CORE) $(MODULES_PACKAGES1) $(MODULES_PACKAGES2))))
.PHONY: make-packages3-go
$(eval $(call guile-compilation-rule,make-packages4-go, \
$(MODULES_PACKAGES4) make-core-go make-packages1-go make-packages2-go \
make-packages3-go, \
$(words $(MODULES_CORE) $(MODULES_PACKAGES1) $(MODULES_PACKAGES2) \
$(MODULES_PACKAGES3))))
.PHONY: make-packages4-go
$(eval $(call guile-compilation-rule,make-packages5-go, \
$(MODULES_PACKAGES5) make-core-go make-packages1-go make-packages2-go \
make-packages3-go make-packages4-go, \
$(words $(MODULES_CORE) $(MODULES_PACKAGES1) $(MODULES_PACKAGES2) \
$(MODULES_PACKAGES3) $(MODULES_PACKAGES4))))
.PHONY: make-packages5-go
make-packages-go: make-packages1-go make-packages2-go \
make-packages3-go make-packages4-go make-packages5-go
.PHONY: make-packages-go
$(eval $(call guile-compilation-rule,make-system-go, \
$(MODULES_SYSTEM) make-packages-go make-core-go, \
$(words $(MODULES_CORE) $(MODULES_PACKAGES))))
.PHONY: make-system-go
$(eval $(call guile-compilation-rule,make-cli-go, \
$(MODULES_CLI) make-system-go make-packages-go make-core-go, \
$(words $(MODULES_CORE) $(MODULES_PACKAGES) $(MODULES_SYSTEM))))
.PHONY: make-cli-go
$(eval $(call guile-compilation-rule,guix/build/po.go, \
$(MODULES_PO), \
0))
make-go: $(MODULES) guix/config.scm $(dist_noinst_DATA)
$(AM_V_at)echo "Compiling Scheme modules..." ; \
unset GUILE_LOAD_COMPILED_PATH ; \
XDG_CACHE_HOME=/nowhere \
host=$(host) srcdir="$(top_srcdir)" \
$(top_builddir)/pre-inst-env \
$(GUILE) -L "$(top_builddir)" -L "$(top_srcdir)" \
--no-auto-compile \
-s "$(top_srcdir)"/build-aux/compile-all.scm $^
SUFFIXES = .go
@@ -1055,21 +864,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 produced Guix installation image for $$system" >&2 ; \
exit 1 ; \
fi ; \
cp "$$image" "$(releasedir)/$(GUIX_SYSTEM_IMAGE_BASE).$$system.iso.tmp" ; \
@@ -1078,14 +891,13 @@ 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 \
--system=$$system --fallback \
gnu/system/examples/vm-image.tmpl` ; \
if [ ! -f "$$image" ] ; then \
echo "failed to produce Guix VM image for $$system" >&2 ; \
echo "failed to produced Guix VM image for $$system" >&2 ; \
exit 1 ; \
fi ; \
cp "$$image" "$(releasedir)/$(GUIX_SYSTEM_VM_IMAGE_BASE).$$system.qcow2"; \
@@ -1125,12 +937,10 @@ assert-no-store-file-names:
exit 1 ; \
fi
# Make sure important substitutes are available. Check only the primary
# server so that '--display-missing' doesn't print two lists.
# Make sure important substitutes are available.
assert-binaries-available: $(GOBJECTS)
$(AM_V_at)$(top_builddir)/pre-inst-env \
guix weather -m "$(top_srcdir)/etc/release-manifest.scm" \
--substitute-urls="https://ci.guix.gnu.org" \
--display-missing
# Make sure the final inputs don't refer to bootstrap tools.
@@ -1156,19 +966,6 @@ cuirass-jobs: $(GOBJECTS)
.PHONY: clean-go make-go as-derivation authenticate
.PHONY: update-guix-package update-NEWS cuirass-jobs release
# Git auto-configuration.
.git/hooks/pre-push: etc/git/pre-push
$(AM_V_at)if test -d .git; then \
cp etc/git/pre-push .git/hooks/pre-push; \
fi
.git/config: etc/git/gitconfig
$(AM_V_at)if command -v git >/dev/null && test -d .git; then \
git config --add include.path ../etc/git/gitconfig; \
fi
nodist_noinst_DATA = .git/hooks/pre-push .git/config
# Downloading up-to-date PO files.
WEBLATE_REPO = https://framagit.org/tyreunom/guix-translations
@@ -1179,35 +976,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
+3 -172
View File
@@ -2,10 +2,8 @@
#+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>
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
@@ -13,177 +11,10 @@ Copyright © 2022 Mathieu Othacehe <othacehe@gnu.org>
Please send Guix bug reports to bug-guix@gnu.org.
* Changes in 1.5.0 (since 1.4.0)
** Package management
*** New rpm format for the guix pack command
* Changes in 1.4.0 (since 1.3.0)
** Package management
*** New guix home command, for home environment management
*** New guix shell command, the successor to guix environment
*** New guix system edit command, to edit services
*** New deb format for the guix pack command
*** New guix import minetest command, to import Minetest extensions
*** New guix import elm command, to import Elm packages
*** New guix import egg command, to import CHICKEN egg packages
*** New guix import hexpm command, to import Erlang and Elixir packages
*** New 'guix style' command, to auto-format package definitions
*** guix import texlive rewritten to use the TLPDB as its source
*** guix import elpa now supports the non-GNU ELPA repository
*** guix import pypi can now import a specific version
*** guix import cran can now import a specific version
*** New updater (see guix refresh): generic-git
*** guix graph has a new --max-depth option
*** guix deploy has a new --execute option
*** guix shell has a new --emulate-fhs option
*** guix shell has a new --symlink option
*** --with-commit option now accepts strings returned by git describe
*** --with-source option now applied recursively
*** Align tabular data output by commands like guix package --list-available
*** Improved guix import go importer via a new PEG parser
*** Improved Software Heritage downloader
*** New 'web.archive.org download fall-back
*** Various performance enhancements
*** New --tune package transformation option
*** guix refresh -L option is repurposed to load-path modification
*** guix system image supersedes the docker-image sub-command
** Distribution
*** The installation script can now enable local substitute servers discovery
*** The installation script can now customize the Bash prompt for Guix
*** More control over boot-time file system checks and repairs
*** XFS file systems can be created by the installer and mounted by label/UUID
*** New interface for declaring swap space
*** GNOME is now at version 42
*** TeX Live is now at version 2021
*** Multiple TeX Live trees can now be used via GUIX_TEXMF
*** Python modules are searched in GUIX_PYTHONPATH instead of PYTHONPATH
*** Python is now faster thanks to being built with optimizations
*** The Rust bootstrap now starts from 1.54 instead of 1.19
*** Most Python 2 packages have been removed
*** Guix now makes use of parallel xz compression
*** Faster shared libraries discovery via a per-package dynamic linker cache
*** Package inputs can now be plain package lists
*** A package origin can now be a single file rather than an archive
*** New sanity-check phase to detect Python packaging problems at build time
*** Fetching sources can now fall-back to use Disarchive
*** Improved CI and infrastructure
*** Multiple cross-compilation tooling addition and fixes
*** Many Qt 6 modules are now packaged
*** Configuring setuid programs is now more flexible
*** Add support for the XFS file system
*** Add partial support for LUKS2 headers when using GRUB
*** GDM now supports Wayland
*** Guix System static networking support is improved
*** The installer final configuration is prettified
*** The installer external command handling is improved
*** The installer now has a crash dump upload mechanism
*** Emacs now supports native compilation
*** GRUB bootloader now supports chain-loading
*** The GNU Shepherd was upgraded to 0.9.3
*** The init RAM disk honors more arguments—e.g. root and rootflags
*** guix system image can now generate WSL images
*** The mcron task scheduler logs now contain the jobs exit statuses
*** Chromium extensions are now built in a deterministic fashion
*** The rsync service lets you specify individual “modules”
*** New services
anonip, bitmask, fail2ban, gitile, greetd, jami, lightdm, log-cleanup,
nar-herder, opendht, rasdaemon, samba, seatd, strongswan, wsdd
*** 5311 new packages
*** 6573 package updates
Noteworthy updates:
bash 5.1.8, binutils 2.37, clojure 1.11.1, cups 2.3.3op2, emacs 28.2,
enlightenment 0.25.4, gcc-toolchain 12.2.0, gdb 12.1, ghc 8.10.7,
gimp 2.10.32, glibc 2.33, gnome 42.4, gnupg 2.2.32, go 1.19.1, guile 3.0.8,
icecat 102.5.0-guix0-preview1, icedtea 3.19.0, inkscape 1.2.1, julia 1.6.7,
libreoffice 7.4.3.2, linux-libre 6.0.10, ocaml 4.14.0, octave 7.2.0,
openjdk 18, perl 5.34.0, python2 2.7.18, python 3.9.9, racket 8.7,
rust 1.60.0, r 4.2.2, sbcl 2.2.10, shepherd 0.9.3, xorg-server 21.1.4
** Programming interfaces
*** Package input fields can now be plain package lists
*** G-expressions can now be used in build phases
*** New modify-inputs macro to ease customizing a list of package inputs
*** New this-package-input and this-package-native-input macros
*** Build phases are no longer required to return a boolean
*** (guix records) now supports “field sanitizers”
*** Various improvements to the helpers in (gnu service configuration)
*** texlive-union is now deprecated in favor of texlive-updmap.cfg
*** New (guix cpu) module
*** New (guix least-authority) module
*** New (guix platform) module
*** New (guix read-print) module
It provides a comment-preserving reader and a comment-preserving
pretty-printer smarter than (ice-9 pretty-print).
*** New channel-build-system
This build system lets you build Guix instances from channel specifications,
similar to how 'guix time-machine' would do it, as regular packages.
*** New pyproject-build-system
This is an extension of python-build-system with support for PEP-517 and
pyproject.toml files. It may eventually get merged back into
python-build-system.
*** New elm-build-system
*** New rebar-build-system
** Noteworthy bug fixes
*** Fall back to Software Heritage when cloning a channel
(<https://issues.guix.gnu.org/44187>)
*** --with-patch can be used on packages with non-origin sources
(<https://issues.guix.gnu.org/49697>)
*** Fix pathological profile building performance in the presence of grafts
(<https://issues.guix.gnu.org/49439>)
*** Deduplication phase of the garbage collector is now faster
(<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
*** POWER9 (powerpc64le-linux) is now supported as a technology preview
*** New --export-manifest and --export-channels options of guix package
*** New --profile option for guix environment
+1 -1
View File
@@ -43,7 +43,7 @@ infrastructure help:
Alen Skondro <askondro@gmail.com>
Jan Synáček <jan.synacek@gmail.com>
Matthias Wachs <wachs@net.in.tum.de>
Christine Lemmer-Webber <cwebber@dustycloud.org>
Christopher Allan Webber <cwebber@dustycloud.org>
Philip Woods <elzairthesorcerer@gmail.com>
GNU Guix also includes non-software works. Thanks to the following
+4 -2
View File
@@ -5,7 +5,8 @@ set -e -x
# Generate stubs for translations.
langs=`find po/doc -type f -name 'guix-manual*.po' \
| sed -e 's,.*/guix-manual\.,,;s,\.po$,,'`
| sed -e 's,guix-manual\.,,' \
| xargs -n 1 -I{} basename {} .po`
for lang in ${langs}; do
if [ ! -e "doc/guix.${lang}.texi" ]; then
echo "@setfilename guix.${lang}.info" > "doc/guix.${lang}.texi"
@@ -15,7 +16,8 @@ for lang in ${langs}; do
fi
done
langs=`find po/doc -type f -name 'guix-cookbook*.po' \
| sed -e 's,.*/guix-cookbook\.,,;s,\.po$,,'`
| sed -e 's,guix-cookbook\.,,' \
| xargs -n 1 -I{} basename {} .po`
for lang in ${langs}; do
if [ ! -e "doc/guix-cookbook.${lang}.texi" ]; then
echo "@setfilename guix-cookbook.${lang}.info" > "doc/guix-cookbook.${lang}.texi"
+1 -2
View File
@@ -250,7 +250,6 @@ interface (FFI) of Guile.")
(match-lambda
(('guix 'config) #f)
(('guix 'channels) #f)
(('guix 'build 'download) #f) ;autoloaded by (guix download)
(('guix _ ...) #t)
(('gnu _ ...) #t)
(_ #f)))
@@ -494,7 +493,7 @@ files."
(message (format #f "You found a bug: the program '~a'
failed to compute the derivation for Guix (version: ~s; system: ~s;
host version: ~s; pull-version: ~s).
Please report the COMPLETE output above by email to <~a>.~%"
Please report it by email to <~a>.~%"
(derivation->output-path build)
version system %guix-version pull-version
%guix-bug-report-address))))))))))))
+24 -31
View File
@@ -1,6 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2016 Taylan Ulrich Bayırlı/Kammer <taylanbayirli@gmail.com>
;;; Copyright © 2016, 2017, 2019, 2020, 2021 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2016, 2017, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -98,36 +98,26 @@ to 'make'."
(exit 1)))
(match (command-line)
((_ "--total" (= string->number grand-total)
"--completed" (= string->number processed)
. files)
;; GRAND-TOTAL is the total number of .scm files in the project; PROCESSED
;; is the total number of .scm files already compiled in previous
;; invocations of this script.
((_ . files)
(catch #t
(lambda ()
(let* ((to-build (filter file-needs-compilation? files))
(processed (+ processed
(- (length files) (length to-build)))))
(compile-files srcdir (getcwd) to-build
#:workers (parallel-job-count*)
#:host host
#:report-load (lambda (file total completed)
(when file
(format #t "[~3d%] LOAD ~a~%"
(% (+ 1 completed
(* 2 processed))
(* 2 grand-total))
file)
(force-output)))
#:report-compilation (lambda (file total completed)
(when file
(format #t "[~3d%] GUILEC ~a~%"
(% (+ total completed 1
(* 2 processed))
(* 2 grand-total))
(scm->go file))
(force-output))))))
(compile-files srcdir (getcwd)
(filter file-needs-compilation? files)
#:workers (parallel-job-count*)
#:host host
#:report-load (lambda (file total completed)
(when file
(format #t "[~3d%] LOAD ~a~%"
(% (+ 1 completed) (* 2 total))
file)
(force-output)))
#:report-compilation (lambda (file total completed)
(when file
(format #t "[~3d%] GUILEC ~a~%"
(% (+ total completed 1)
(* 2 total))
(scm->go file))
(force-output)))))
(lambda _
(primitive-exit 1))
(lambda args
@@ -142,8 +132,11 @@ to 'make'."
(false-if-exception
(module-ref ui 'report-load-error)))))
(if report
(report (or (and=> (current-load-port) port-filename) "?.scm")
args frame)
;; In Guile <= 2.2.5, 'current-load-port' was not exported.
(let ((load-port ((module-ref (resolve-module '(ice-9 ports))
'current-load-port))))
(report (or (and=> load-port port-filename) "?.scm")
args frame))
(begin
(print-exception (current-error-port) frame
(car args) (cdr args))
-26
View File
@@ -1,26 +0,0 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2021 Julien Lepiller <julien@lepiller.eu>
;;;
;;; 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/>.
;; Translate cross-references in a translated .texi manual.
(use-modules (guix build po)
(ice-9 match))
(match (command-line)
((program texi pofile)
(translate-cross-references texi pofile)))
+23 -30
View File
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2016-2018, 2020, 2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2016, 2017, 2018, 2020 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2017 Jan Nieuwenhuizen <janneke@gnu.org>
;;; Copyright © 2021 Mathieu Othacehe <othacehe@gnu.org>
;;;
@@ -78,35 +78,28 @@
;; up the evaluation speed as the evaluations can be performed
;; concurrently. It also decreases the amount of memory needed per
;; evaluation process.
;;
;; Fork inferior processes upfront before we have created any
;; threads.
(let ((inferiors (map (lambda _
(open-inferior (derivation->output-path derivation)))
%cuirass-supported-systems)))
(n-par-for-each
(min (length %cuirass-supported-systems)
(current-processor-count))
(lambda (system inferior)
(with-store store
(let ((channels (map channel-instance->sexp instances)))
(inferior-eval '(use-modules (gnu ci)) inferior)
(let ((jobs
(inferior-eval-with-store
inferior store
`(lambda (store)
(cuirass-jobs store
'((subset . all)
(systems . ,(list system))
(channels . ,channels))))))
(file
(string-append directory "/jobs-" system ".scm")))
(close-inferior inferior)
(call-with-output-file file
(lambda (port)
(write jobs port)))))))
%cuirass-supported-systems
inferiors)))))))
(n-par-for-each
(/ (current-processor-count) 2)
(lambda (system)
(with-store store
(let ((inferior
(open-inferior (derivation->output-path derivation)))
(channels (map channel-instance->sexp instances)))
(inferior-eval '(use-modules (gnu ci)) inferior)
(let ((jobs
(inferior-eval-with-store
inferior store
`(lambda (store)
(cuirass-jobs store
'((subset . all)
(systems . ,(list system))
(channels . ,channels))))))
(file
(string-append directory "/jobs-" system ".scm")))
(call-with-output-file file
(lambda (port)
(write jobs port)))))))
%cuirass-supported-systems))))))
(x
(format (current-error-port) "Wrong command: ~a~%." x)
(exit 1)))
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2020, 2023 Janneke Nieuwenhuizen <janneke@gnu.org>
;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -31,7 +31,7 @@
(srfi srfi-1))
(use-package-modules
base bootloaders commencement compression file gawk gdb gettext guile
base commencement compression file gawk gdb gettext guile
hurd less m4 package-management python ssh version-control)
(define (input->package input)
@@ -64,14 +64,11 @@
;; development packages
gcc-toolchain gdb-minimal git-minimal gnu-make
gettext-minimal python-minimal
;; ourselves!
(package-without-tests guix)
;; system
grub-minimal grub
;; guix environment guix --without-tests=python-minimal --without-tests=gettext-minimal
(package-without-tests gettext-minimal)
(package-without-tests python-minimal)
(append
guix-dependencies
%base-packages/hurd)))
(delete guile-3.0 %base-packages/hurd))))
+3 -3
View File
@@ -73,9 +73,9 @@ then
# Copy the keys so that the secret key has the right permissions (the
# daemon errors out when this is not the case.)
mkdir -p "$GUIX_CONFIGURATION_DIRECTORY"
cp "@abs_top_srcdir@/tests/keys/signing-key.sec" \
"@abs_top_srcdir@/tests/keys/signing-key.pub" \
"$GUIX_CONFIGURATION_DIRECTORY"
cp "@abs_top_srcdir@/tests/signing-key.sec" \
"@abs_top_srcdir@/tests/signing-key.pub" \
"$GUIX_CONFIGURATION_DIRECTORY"
chmod 400 "$GUIX_CONFIGURATION_DIRECTORY/signing-key.sec"
fi
+12 -1
View File
@@ -94,6 +94,17 @@ if test "x$guix_build_daemon" = "xyes"; then
AC_CHECK_FUNCS([lutimes lchown posix_fallocate sched_setaffinity \
statvfs nanosleep strsignal statx])
dnl Check whether the store optimiser can optimise symlinks.
AC_MSG_CHECKING([whether it is possible to create a link to a symlink])
ln -s bla tmp_link
if ln tmp_link tmp_link2 2> /dev/null; then
AC_MSG_RESULT(yes)
AC_DEFINE(CAN_LINK_SYMLINK, 1, [Whether link() works on symlinks.])
else
AC_MSG_RESULT(no)
fi
rm -f tmp_link tmp_link2
dnl Check for <locale>.
AC_LANG_PUSH(C++)
AC_CHECK_HEADERS([locale])
@@ -106,7 +117,7 @@ if test "x$guix_build_daemon" = "xyes"; then
dnl Determine the appropriate default list of substitute URLs (GnuTLS
dnl is required so we can default to 'https'.)
guix_substitute_urls="https://ci.guix.gnu.org https://bordeaux.guix.gnu.org"
guix_substitute_urls="https://ci.guix.gnu.org"
AC_MSG_CHECKING([for default substitute URLs])
AC_MSG_RESULT([$guix_substitute_urls])
+5 -5
View File
@@ -8,7 +8,7 @@ AC_INIT([GNU Guix],
[https://www.gnu.org/software/guix/])
AC_CONFIG_AUX_DIR([build-aux])
AM_INIT_AUTOMAKE([1.14 gnu tar-ustar silent-rules subdir-objects \
AM_INIT_AUTOMAKE([1.14 gnu silent-rules subdir-objects \
color-tests parallel-tests -Woverride -Wno-portability])
# Enable silent rules by default.
@@ -96,14 +96,15 @@ m4_pattern_forbid([^GUIX_])
dnl Search for 'guile' and 'guild'. This macro defines
dnl 'GUILE_EFFECTIVE_VERSION'.
GUILE_PKG([3.0])
GUILE_PKG([3.0 2.2])
GUILE_PROGS
if test "x$GUILD" = "x"; then
AC_MSG_ERROR(['guild' binary not found; please check your Guile installation.])
fi
dnl (guix ui), notably, requires 'default-optimization-level' added in 3.0.3.
PKG_CHECK_MODULES([GUILE], [guile-3.0 >= 3.0.3])
if test "x$GUILE_EFFECTIVE_VERSION" = "x2.2"; then
PKG_CHECK_MODULES([GUILE], [guile-2.2 >= 2.2.6])
fi
dnl Get CFLAGS and LDFLAGS for libguile.
GUILE_FLAGS
@@ -274,7 +275,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])
+224 -435
View File
@@ -1,7 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2019-2023 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2019, 2020 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2020 Björn Höfling <bjoern.hoefling@bjoernhoefling.de>
;;; Copyright © 2022 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -31,7 +30,6 @@
(guix gexp)
(guix git)
(guix git-download)
(guix profiles)
(guix utils)
(git)
(gnu packages base)
@@ -64,19 +62,11 @@
(or (getenv "GUIX_MANUAL")
"guix"))
(define %manual-languages
;; Available translations for the 'guix-manual' text domain.
'("de" "en" "es" "fr" "pt_BR" "ru" "zh_CN"))
(define %cookbook-languages
;; Available translations for the 'guix-cookbook' text domain.
'("de" "en" "fr" "sk"))
(define %languages
;; Available translations for the document being built.
;; The cookbook is not translated in the same languages as the manual
(if (string=? %manual "guix-cookbook")
%cookbook-languages
%manual-languages))
'("de" "en" "fr")
'("de" "en" "es" "fr" "ru" "zh_CN")))
(define (texinfo-manual-images source)
"Return a directory containing all the images used by the user manual, taken
@@ -284,9 +274,6 @@ actual file name."
(loop rest))
((('strong _ ...) _ ...)
#t)
((('span ('@ ('class "category")) ;raw Texinfo 6.8
(? string-or-entity?) ...) rest ...)
#t)
((('span ('@ ('class "symbol-definition-category"))
(? string-or-entity?) ...) rest ...)
#t)
@@ -314,9 +301,8 @@ actual file name."
(define (html-files directory)
;; Return the list of HTML files under DIRECTORY.
(map (cut string-append directory "/" <>)
(or (scandir #$manual (lambda (file)
(string-suffix? ".html" file)))
'())))
(scandir #$manual (lambda (file)
(string-suffix? ".html" file)))))
(define anchors
(sort (concatenate
@@ -453,7 +439,6 @@ its <pre class=\"lisp\"> blocks (as produced by 'makeinfo --html')."
("rarr" "→")
("hellip" "…")
("rsquo" "")
("nbsp" " ")
(e (pk 'unknown-entity e) (primitive-exit 2))))
(define (concatenate-snippets pieces)
@@ -510,16 +495,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 ...)
@@ -620,175 +599,6 @@ its <pre class=\"lisp\"> blocks (as produced by 'makeinfo --html')."
(computed-file name build))
(define* (stylized-html source input
#:key
(languages %languages)
(manual %manual)
(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."
(define build
(with-extensions (list guile-lib)
(with-imported-modules `((guix build utils)
((localization)
=> ,(localization-helper-module
source languages)))
#~(begin
(use-modules (htmlprag)
(localization)
(guix build utils)
(srfi srfi-1)
(ice-9 match)
(ice-9 threads))
(define* (menu-dropdown #:key (label "Item") (url "#") (items '()))
;; Return an SHTML <li> element representing a dropdown for the
;; navbar. LABEL is the text of the dropdown menu, and ITEMS is
;; the list of items in this menu.
(define id "visible-dropdown")
`(li
(@ (class "navbar-menu-item dropdown dropdown-btn"))
(input (@ (class "navbar-menu-hidden-input")
(type "radio")
(name "dropdown")
(id ,id)))
(label (@ (for ,id)) ,label)
(label (@ (for "all-dropdowns-hidden")) ,label)
(div
(@ (class "navbar-submenu")
(id "navbar-submenu"))
(div (@ (class "navbar-submenu-triangle"))
" ")
(ul ,@items))))
(define (menu-item label url)
;; Return an SHTML <li> element for a menu item with the given
;; LABEL and URL.
`(li (a (@ (class "navbar-menu-item")
(href ,url))
,label)))
(define* (navigation-bar menus #:key split-node?)
;; Return the navigation bar showing all of MENUS.
`(header (@ (class "navbar"))
(h1 (a (@ (class "branding")
(href ,(if split-node? ".." "#")))))
(nav (@ (class "navbar-menu"))
(input (@ (class "navbar-menu-hidden-input")
(type "radio")
(name "dropdown")
(id "all-dropdowns-hidden")))
(ul ,@menus))
;; This is the button that shows up on small screen in
;; lieu of the drop-down button.
(a (@ (class "navbar-menu-btn")
(href ,(if split-node? "../.." ".."))))))
(define* (base-language-url code manual
#:key split-node?)
;; Return the base URL of MANUAL for language CODE.
(if split-node?
(string-append "../../" (normalize code) "/html_node")
(string-append "../" (normalize code) "/" manual
(if (string=? code "en")
""
(string-append "." code))
".html")))
(define (language-menu-items file)
;; Return the language menu items to be inserted in FILE.
(define split-node?
(string-contains file "/html_node/"))
(append
(map (lambda (code)
(menu-item (language-code->native-name code)
(base-language-url code #$manual
#:split-node?
split-node?)))
'#$%languages)
(list
(menu-item "⊕"
(if (string=? #$manual "guix-cookbook")
"https://translate.fedoraproject.org/projects/guix/documentation-cookbook/"
"https://translate.fedoraproject.org/projects/guix/documentation-manual/")))))
(define (stylized-html sxml file)
;; Return SXML, which was read from FILE, with additional
;; styling.
(define split-node?
(string-contains file "/html_node/"))
(let loop ((sxml sxml))
(match sxml
(('*TOP* decl body ...)
`(*TOP* ,decl ,@(map loop body)))
(('head elements ...)
;; Add reference to our own manual CSS, which provides
;; support for the language menu.
`(head ,@elements
(link (@ (rel "stylesheet")
(type "text/css")
(href #$manual-css-url)))))
(('body ('@ attributes ...) elements ...)
`(body (@ ,@attributes)
,(navigation-bar
;; TODO: Add "Contribute" menu, to report
;; errors, etc.
(list (menu-dropdown
#:label
`(img (@ (alt "Language")
(src "/static/base/img/language-picker.svg")))
#:items
(language-menu-items file)))
#:split-node? split-node?)
,@elements))
((tag ('@ attributes ...) body ...)
`(,tag (@ ,@attributes) ,@(map loop body)))
((tag body ...)
`(,tag ,@(map loop body)))
((? string? str)
str))))
(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))
(base (string-drop file (string-length #$input)))
(target (string-append #$output base)))
(mkdir-p (dirname target))
(call-with-output-file target
(lambda (port)
(write-shtml-as-html processed port)))))
;; Install a UTF-8 locale so we can process UTF-8 files.
(setenv "GUIX_LOCPATH"
#+(file-append glibc-utf8-locales "/lib/locale"))
(setlocale LC_ALL "en_US.utf8")
(setenv "LC_ALL" "en_US.utf8")
(setvbuf (current-error-port) 'line)
(n-par-for-each (parallel-job-count)
(lambda (file)
(if (string-suffix? ".html" file)
(process-html file)
;; Copy FILE as is to #$output.
(let* ((base (string-drop file (string-length #$input)))
(target (string-append #$output base)))
(mkdir-p (dirname target))
(if (eq? 'symlink (stat:type (lstat file)))
(symlink (readlink file) target)
(copy-file file target)))))
(find-files #$input))))))
(computed-file "stylized-html-manual" build))
(define* (html-manual source #:key (languages %languages)
(version "0.0")
(manual %manual)
@@ -879,11 +689,9 @@ makeinfo OPTIONS."
(filter (compose file-exists? language->texi-file-name)
'#$languages)))))
(let* ((name (string-append manual "-html-manual"))
(manual* (computed-file name build #:local-build? #f)))
(syntax-highlighted-html (stylized-html source manual*
#:languages languages
#:manual manual)
(let* ((name (string-append manual "-html-manual"))
(manual (computed-file name build)))
(syntax-highlighted-html manual
#:mono-node-indexes mono-node-indexes
#:split-node-indexes split-node-indexes
#:name (string-append name "-highlighted"))))
@@ -901,19 +709,14 @@ makeinfo OPTIONS."
#:languages languages
#:date date))
(define texinfo-profile
(profile
(content (packages->manifest
;; texi2dvi requires various command line tools.
(list coreutils
diffutils
gawk
grep
sed
tar
texinfo
(texlive-updmap.cfg
(list texlive-epsf texlive-texinfo)))))))
;; FIXME: This union works, except for the table of contents of non-English
;; manuals, which contains escape sequences like "^^ca^^fe" instead of
;; accented letters.
;;
;; (define texlive
;; (texlive-union (list texlive-tex-texinfo
;; texlive-generic-epsf
;; texlive-fonts-ec)))
(define build
(with-imported-modules '((guix build utils))
@@ -930,12 +733,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)
@@ -982,11 +794,9 @@ PDF for language '~a'!~%~%"
opts))))
'#$languages))))
(computed-file (string-append manual "-pdf-manual") build
#:local-build? #f))
(computed-file (string-append manual "-pdf-manual") build))
(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
@@ -1013,102 +823,6 @@ from SOURCE."
(computed-file "guix-manual-po" build))
(define* (localization-helper-module source
#:optional (languages %languages))
"Return a file-like object for use as the (localization) module. SOURCE
must be the Guix top-level source directory, from which PO files are taken."
(define content
(with-extensions (list guile-json-3)
#~(begin
(define-module (localization)
#:use-module (json)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-19)
#:use-module (ice-9 match)
#:use-module (ice-9 popen)
#:export (normalize
with-language
translate
language-code->name
language-code->native-name
seconds->string))
(define (normalize language) ;XXX: deduplicate
;; Normalize LANGUAGE. For instance, "zh_CN" becomes "zh-cn".
(string-map (match-lambda
(#\_ #\-)
(chr chr))
(string-downcase language)))
(define-syntax-rule (with-language language exp ...)
(let ((lang (getenv "LANGUAGE")))
(dynamic-wind
(lambda ()
(setenv "LANGUAGE" language)
(setlocale LC_MESSAGES))
(lambda () exp ...)
(lambda ()
(if lang
(setenv "LANGUAGE" lang)
(unsetenv "LANGUAGE"))
(setlocale LC_MESSAGES)))))
;; (put 'with-language 'scheme-indent-function 1)
(define* (translate str language
#:key (domain "guix-manual"))
(define exp
`(begin
(bindtextdomain "guix-manual"
#+(guix-manual-text-domain source))
(bindtextdomain "iso_639-3" ;language names
#+(file-append iso-codes
"/share/locale"))
(setenv "LANGUAGE" ,language)
(write (gettext ,str ,domain))))
;; Since the 'gettext' function caches msgid translations,
;; regardless of $LANGUAGE, we have to spawn a new process each
;; time we want to translate to a different language. Bah!
(let* ((pipe (open-pipe* OPEN_READ
#+(file-append guile-3.0
"/bin/guile")
"-c" (object->string exp)))
(str (read pipe)))
(close-pipe pipe)
str))
(define %iso639-languages
(vector->list
(assoc-ref (call-with-input-file
#+(file-append iso-codes
"/share/iso-codes/json/iso_639-3.json")
json->scm)
"639-3")))
(define (language-code->name code)
"Return the full name of a language from its ISO-639-3 code."
(let ((code (match (string-index code #\_)
(#f code)
(index (string-take code index)))))
(any (lambda (language)
(and (string=? (or (assoc-ref language "alpha_2")
(assoc-ref language "alpha_3"))
code)
(assoc-ref language "name")))
%iso639-languages)))
(define (language-code->native-name code)
"Return the name of language CODE in that language."
(translate (language-code->name code) code
#:domain "iso_639-3"))
(define (seconds->string seconds language)
(let* ((time (make-time time-utc 0 seconds))
(date (time-utc->date time)))
(with-language language (date->string date "~e ~B ~Y")))))))
(scheme-file "localization.scm" content))
(define* (html-manual-indexes source
#:key (languages %languages)
(version "0.0")
@@ -1118,132 +832,207 @@ must be the Guix top-level source directory, from which PO files are taken."
"GNU Guix Cookbook"))
(date 1))
(define build
(with-imported-modules `((guix build utils)
((localization)
=> ,(localization-helper-module
source languages)))
#~(begin
(use-modules (guix build utils)
(localization)
(sxml simple)
(srfi srfi-1))
(with-extensions (list guile-json-3)
(with-imported-modules '((guix build utils))
#~(begin
(use-modules (guix build utils)
(json)
(ice-9 match)
(ice-9 popen)
(sxml simple)
(srfi srfi-1)
(srfi srfi-19))
(define (guix-url path)
(string-append #$%web-site-url path))
(define (normalize language) ;XXX: deduplicate
;; Normalize LANGUAGE. For instance, "zh_CN" becomes "zh-cn".
(string-map (match-lambda
(#\_ #\-)
(chr chr))
(string-downcase language)))
(define (sxml-index language title body)
;; FIXME: Avoid duplicating styling info from guix-artwork.git.
`(html (@ (lang ,language))
(head
(title ,(string-append title " — GNU Guix"))
(meta (@ (charset "UTF-8")))
(meta (@ (name "viewport") (content "width=device-width, initial-scale=1.0")))
;; Menu prefetch.
(link (@ (rel "prefetch") (href ,(guix-url "menu/index.html"))))
;; Base CSS.
(link (@ (rel "stylesheet") (href ,(guix-url "static/base/css/elements.css"))))
(link (@ (rel "stylesheet") (href ,(guix-url "static/base/css/common.css"))))
(link (@ (rel "stylesheet") (href ,(guix-url "static/base/css/messages.css"))))
(link (@ (rel "stylesheet") (href ,(guix-url "static/base/css/navbar.css"))))
(link (@ (rel "stylesheet") (href ,(guix-url "static/base/css/breadcrumbs.css"))))
(link (@ (rel "stylesheet") (href ,(guix-url "static/base/css/buttons.css"))))
(link (@ (rel "stylesheet") (href ,(guix-url "static/base/css/footer.css"))))
(define-syntax-rule (with-language language exp ...)
(let ((lang (getenv "LANGUAGE")))
(dynamic-wind
(lambda ()
(setenv "LANGUAGE" language)
(setlocale LC_MESSAGES))
(lambda () exp ...)
(lambda ()
(if lang
(setenv "LANGUAGE" lang)
(unsetenv "LANGUAGE"))
(setlocale LC_MESSAGES)))))
(link (@ (rel "stylesheet") (href ,(guix-url "static/base/css/page.css"))))
(link (@ (rel "stylesheet") (href ,(guix-url "static/base/css/post.css")))))
(body
(header (@ (class "navbar"))
(h1 (a (@ (class "branding")
(href #$%web-site-url)))
(span (@ (class "a11y-offset"))
"Guix"))
(nav (@ (class "menu"))))
(nav (@ (class "breadcrumbs"))
(a (@ (class "crumb")
(href #$%web-site-url))
"Home"))
,body
(footer))))
;; (put 'with-language 'scheme-indent-function 1)
(define* (translate str language
#:key (domain "guix-manual"))
(define exp
`(begin
(bindtextdomain "guix-manual"
#+(guix-manual-text-domain
source
languages))
(bindtextdomain "iso_639-3" ;language names
#+(file-append iso-codes
"/share/locale"))
(write (gettext ,str ,domain))))
(define (language-index language)
(define title
(translate #$title language))
(with-language language
;; Since the 'gettext' function caches msgid translations,
;; regardless of $LANGUAGE, we have to spawn a new process each
;; time we want to translate to a different language. Bah!
(let* ((pipe (open-pipe* OPEN_READ
#+(file-append guile-2.2
"/bin/guile")
"-c" (object->string exp)))
(str (read pipe)))
(close-pipe pipe)
str)))
(sxml-index
language title
`(main
(article
(@ (class "page centered-block limit-width"))
(h2 ,title)
(p (@ (class "post-metadata centered-text"))
#$version " — "
,(seconds->string #$date language))
(define (seconds->string seconds language)
(let* ((time (make-time time-utc 0 seconds))
(date (time-utc->date time)))
(with-language language (date->string date "~e ~B ~Y"))))
(div
(ul
(li (a (@ (href "html_node"))
"HTML, with a separate page per node"))
(li (a (@ (href
,(string-append
#$manual
(if (string=? language
"en")
""
(string-append "."
language))
".html")))
"HTML, entirely on one page"))
,@(if (member language '("ru" "zh_CN"))
'()
`((li (a (@ (href ,(string-append
#$manual
(if (string=? language "en")
""
(string-append "."
language))
".pdf"))))
"PDF")))))))))
(define (guix-url path)
(string-append #$%web-site-url path))
(define (top-level-index languages)
(define title #$title)
(sxml-index
"en" title
`(main
(article
(@ (class "page centered-block limit-width"))
(h2 ,title)
(div
"This document is available in the following
(define (sxml-index language title body)
;; FIXME: Avoid duplicating styling info from guix-artwork.git.
`(html (@ (lang ,language))
(head
(title ,(string-append title " — GNU Guix"))
(meta (@ (charset "UTF-8")))
(meta (@ (name "viewport") (content "width=device-width, initial-scale=1.0")))
;; Menu prefetch.
(link (@ (rel "prefetch") (href ,(guix-url "menu/index.html"))))
;; Base CSS.
(link (@ (rel "stylesheet") (href ,(guix-url "static/base/css/elements.css"))))
(link (@ (rel "stylesheet") (href ,(guix-url "static/base/css/common.css"))))
(link (@ (rel "stylesheet") (href ,(guix-url "static/base/css/messages.css"))))
(link (@ (rel "stylesheet") (href ,(guix-url "static/base/css/navbar.css"))))
(link (@ (rel "stylesheet") (href ,(guix-url "static/base/css/breadcrumbs.css"))))
(link (@ (rel "stylesheet") (href ,(guix-url "static/base/css/buttons.css"))))
(link (@ (rel "stylesheet") (href ,(guix-url "static/base/css/footer.css"))))
(link (@ (rel "stylesheet") (href ,(guix-url "static/base/css/page.css"))))
(link (@ (rel "stylesheet") (href ,(guix-url "static/base/css/post.css")))))
(body
(header (@ (class "navbar"))
(h1 (a (@ (class "branding")
(href #$%web-site-url)))
(span (@ (class "a11y-offset"))
"Guix"))
(nav (@ (class "menu"))))
(nav (@ (class "breadcrumbs"))
(a (@ (class "crumb")
(href #$%web-site-url))
"Home"))
,body
(footer))))
(define (language-index language)
(define title
(translate #$title language))
(sxml-index
language title
`(main
(article
(@ (class "page centered-block limit-width"))
(h2 ,title)
(p (@ (class "post-metadata centered-text"))
#$version " — "
,(seconds->string #$date language))
(div
(ul
(li (a (@ (href "html_node"))
"HTML, with a separate page per node"))
(li (a (@ (href
,(string-append
#$manual
(if (string=? language
"en")
""
(string-append "."
language))
".html")))
"HTML, entirely on one page"))
,@(if (member language '("ru" "zh_CN"))
'()
`((li (a (@ (href ,(string-append
#$manual
(if (string=? language "en")
""
(string-append "."
language))
".pdf"))))
"PDF")))))))))
(define %iso639-languages
(vector->list
(assoc-ref (call-with-input-file
#+(file-append iso-codes
"/share/iso-codes/json/iso_639-3.json")
json->scm)
"639-3")))
(define (language-code->name code)
"Return the full name of a language from its ISO-639-3 code."
(let ((code (match (string-index code #\_)
(#f code)
(index (string-take code index)))))
(any (lambda (language)
(and (string=? (or (assoc-ref language "alpha_2")
(assoc-ref language "alpha_3"))
code)
(assoc-ref language "name")))
%iso639-languages)))
(define (top-level-index languages)
(define title #$title)
(sxml-index
"en" title
`(main
(article
(@ (class "page centered-block limit-width"))
(h2 ,title)
(div
"This document is available in the following
languages:\n"
(ul
,@(map (lambda (language)
`(li (a (@ (href ,(normalize language)))
,(language-code->native-name language))))
languages)))))))
(ul
,@(map (lambda (language)
`(li (a (@ (href ,(normalize language)))
,(translate
(language-code->name language)
language
#:domain "iso_639-3"))))
languages)))))))
(define (write-html file sxml)
(call-with-output-file file
(lambda (port)
(display "<!DOCTYPE html>\n" port)
(sxml->xml sxml port))))
(define (write-html file sxml)
(call-with-output-file file
(lambda (port)
(display "<!DOCTYPE html>\n" port)
(sxml->xml sxml port))))
(setenv "GUIX_LOCPATH"
#+(file-append glibc-utf8-locales "/lib/locale"))
(setenv "LC_ALL" "en_US.utf8")
(setlocale LC_ALL "en_US.utf8")
(setenv "GUIX_LOCPATH"
#+(file-append glibc-utf8-locales "/lib/locale"))
(setenv "LC_ALL" "en_US.utf8")
(setlocale LC_ALL "en_US.utf8")
(for-each (lambda (language)
(define directory
(string-append #$output "/"
(normalize language)))
(for-each (lambda (language)
(define directory
(string-append #$output "/"
(normalize language)))
(mkdir-p directory)
(write-html (string-append directory "/index.html")
(language-index language)))
'#$languages)
(mkdir-p directory)
(write-html (string-append directory "/index.html")
(language-index language)))
'#$languages)
(write-html (string-append #$output "/index.html")
(top-level-index '#$languages)))))
(write-html (string-append #$output "/index.html")
(top-level-index '#$languages))))))
(computed-file "html-indexes" build))
+168 -1122
View File
File diff suppressed because it is too large Load Diff
+5 -4
View File
@@ -6,7 +6,8 @@
;; Augment the package definition of GDB with the build tools
;; needed when developing GDB (and which are not needed when
;; simply installing it.)
(package
(inherit gdb)
(native-inputs (modify-inputs (package-native-inputs gdb)
(prepend autoconf-2.69 automake texinfo))))
(package (inherit gdb)
(native-inputs `(("autoconf" ,autoconf-2.64)
("automake" ,automake)
("texinfo" ,texinfo)
,@(package-native-inputs gdb))))
+175 -1862
View File
File diff suppressed because it is too large Load Diff
+2837 -14357
View File
File diff suppressed because it is too large Load Diff
-25
View File
@@ -1,25 +0,0 @@
(use-modules (gnu home)
(gnu home services)
(gnu home services shells)
(gnu services)
(gnu packages admin)
(guix gexp))
(home-environment
(packages (list htop))
(services
(list
(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")))))
(simple-service 'test-config
home-xdg-configuration-files-service-type
(list `("test.conf"
,(plain-file "tmp-file.txt"
"the content of
~/.config/test.conf")))))))
+27 -58
View File
@@ -1,9 +1,9 @@
# htmlxref.cnf - reference file for free Texinfo manuals on the web.
# Modified by Ludovic Courtès <ludo@gnu.org> for the GNU Guix manual.
htmlxrefversion=2022-12-18.15; # UTC
htmlxrefversion=2020-01-11.22; # UTC
# Copyright 2010-2020, 2022 Free Software Foundation, Inc.
# Copyright 2010, 2011, 2012, 2013, 2014, 2015, 2019, 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
@@ -110,10 +110,6 @@ cpio node ${GS}/cpio/manual/html_node/
cssc node ${GS}/cssc/manual/
CUIRASS = ${GS}/guix/cuirass/manual
cuirass mono ${CUIRASS}/cuirass.html
cuirass node ${CUIRASS}/html_node/
CVS = ${GS}/trans-coord/manual
cvs mono ${CVS}/cvs/cvs.html
cvs node ${CVS}/cvs/html_node/
@@ -122,8 +118,6 @@ ddd mono ${GS}/ddd/manual/html_mono/ddd.html
ddrescue mono ${GS}/ddrescue/manual/ddrescue_manual.html
dejagnu node ${GS}/dejagnu/manual/
DICO = https://puszcza.gnu.org.ua/software/dico/manual
dico mono ${DICO}/dico.html
dico chapter ${DICO}/html_chapter/
@@ -133,9 +127,6 @@ dico node ${DICO}/html_node/
diffutils mono ${GS}/diffutils/manual/diffutils
diffutils node ${GS}/diffutils/manual/html_node/
dmd mono ${GS}/dmd/manual/dmd
dmd node ${GS}/dmd/manual/html_node/
ed mono ${GS}/ed/manual/ed_manual.html
EMACS = ${GS}/emacs/manual
@@ -190,9 +181,6 @@ emacs node ${EMACS}/html_node/emacs/
idlwave mono ${EMACS}/html_mono/idlwave.html
idlwave node ${EMACS}/html_node/idlwave/
#
info mono ${EMACS}/html_mono/info.html
info node ${EMACS}/html_node/info/
#
message mono ${EMACS}/html_mono/message.html
message node ${EMACS}/html_node/message/
#
@@ -271,7 +259,7 @@ gcc node ${GCC}/gcc/
gcj node ${GCC}/gcj/
gfortran node ${GCC}/gfortran/
gnat_rm node ${GCC}/gnat_rm/
gnat_ugn node ${GCC}/gnat_ugn/
gnat_ugn_unw node ${GCC}/gnat_ugn_unw/
libgomp node ${GCC}/libgomp/
libstdc++ node ${GCC}/libstdc++/
#
@@ -291,6 +279,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
@@ -298,11 +288,6 @@ gettext node ${GS}/gettext/manual/html_node/
gforth node https://www.complang.tuwien.ac.at/forth/gforth/Docs-html/
# Also found at:
# https://mirrors.edge.kernel.org/pub/software/scm/git/docs/user-manual.html
# https://git.github.io/htmldocs/user-manual.html
git mono https://git-scm.com/docs/user-manual
global mono ${GS}/global/manual/global.html
gmediaserver node ${GS}/gmediaserver/manual/
@@ -350,8 +335,8 @@ GNUSTANDARDS = ${G}/prep
standards mono ${GNUSTANDARDS}/standards/standards.html
standards node ${GNUSTANDARDS}/standards/html_node/
gnutls mono ${GS}/gnutls/manual/gnutls.html
gnutls node ${GS}/gnutls/manual/html_node/
gnutls mono http://gnutls.org/manual/gnutls.html
gnutls node http://gnutls.org/manual/html_node/
gnutls-guile mono http://gnutls.org/manual/gnutls-guile.html
gnutls-guile node http://gnutls.org/manual/gnutls-guile/
@@ -409,37 +394,21 @@ GUILE_GNOME = ${GS}/guile-gnome/docs
guile-gtk node ${GS}/guile-gtk/docs/guile-gtk/
guile-netlink mono https://git.lepiller.eu/guile-netlink/manual/manual.html
guile-rpc mono ${GS}/guile-rpc/manual/guile-rpc.html
guile-rpc node ${GS}/guile-rpc/manual/html_node/
GUIX_ROOT = https://guix.gnu.org
GUIX = ${GUIX_ROOT}/manual
guix.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
guix.zh_CN node ${GUIX}/zh-cn/html_node/
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.de node ${GUIX_COOKBOOK}/de/html_node/
guix-cookbook.fr mono ${GUIX_COOKBOOK}/fr/guix-cookbook.fr.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/
guix.de mono ${GS}/guix/manual/de/guix.de.html
guix.de node ${GS}/guix/manual/de/html_node/
guix.es mono ${GS}/guix/manual/es/guix.es.html
guix.es node ${GS}/guix/manual/es/html_node/
guix.fr mono ${GS}/guix/manual/fr/guix.fr.html
guix.fr node ${GS}/guix/manual/fr/html_node/
guix.ru mono ${GS}/guix/manual/ru/guix.ru.html
guix.ru node ${GS}/guix/manual/ru/html_node/
guix.zh_CN mono ${GS}/guix/manual/zh-cn/guix.zh_CN.html
guix.zh_CN node ${GS}/guix/manual/zh-cn/html_node/
guix mono ${GS}/guix/manual/en/guix.html
guix node ${GS}/guix/manual/en/html_node/
gv mono ${GS}/gv/manual/gv.html
gv node ${GS}/gv/manual/html_node/
@@ -534,21 +503,18 @@ mcron node ${GS}/mcron/manual/html_node/
mdk mono ${GS}/mdk/manual/mdk.html
mdk node ${GS}/mdk/manual/html_node/
METAEXCHANGE = https://ftp.gwdg.de/pub/gnu2/iwfmdh/doc/texinfo
METAEXCHANGE = http://ftp.gwdg.de/pub/gnu2/iwfmdh/doc/texinfo
iwf_mh node ${METAEXCHANGE}/iwf_mh.html
scantest node ${METAEXCHANGE}/scantest.html
mes mono ${GS}/mes/manual/mes.html
mes node ${GS}/mes/manual/html_node/
MIT_SCHEME = ${GS}/mit-scheme/documentation/stable
mit-scheme-ref mono ${MIT_SCHEME}/mit-scheme-ref.html
MIT_SCHEME = ${GS}/mit-scheme/documentation
mit-scheme-ref node ${MIT_SCHEME}/mit-scheme-ref/
mit-scheme-user mono ${MIT_SCHEME}/mit-scheme-user.html
mit-scheme-user node ${MIT_SCHEME}/mit-scheme-user/
sos mono ${MIT_SCHEME}/mit-scheme-sos.html
sos node ${MIT_SCHEME}/mit-scheme-sos/
mit-scheme-imail mono ${MIT_SCHEME}/mit-scheme-imail.html
mit-scheme-imail node ${MIT_SCHEME}/mit-scheme-imail/
moe mono ${GS}/moe/manual/moe_manual.html
@@ -606,7 +572,7 @@ R = https://cran.r-project.org/doc/manuals
rcs mono ${GS}/rcs/manual/rcs.html
rcs node ${GS}/rcs/manual/html_node/
READLINE = https://tiswww.cwru.edu/php/chet/readline
READLINE = http://cnswww.cns.cwru.edu/php/chet/readline
readline mono ${READLINE}/readline.html
rluserman mono ${READLINE}/rluserman.html
history mono ${READLINE}/history.html
@@ -663,7 +629,7 @@ swbis mono ${GS}/swbis/manual.html
tar mono ${GS}/tar/manual/tar.html
tar chapter ${GS}/tar/manual/html_chapter/
tar section ${GS}/tar/manual/html_section/
tar node ${GS}/tar/manual/html_node/
tar node ${GS}/autoconf/manual/html_node/
teseq mono ${GS}/teseq/teseq.html
teseq node ${GS}/teseq/html_node/
@@ -671,6 +637,9 @@ teseq node ${GS}/teseq/html_node/
TEXINFO = ${GS}/texinfo/manual
texinfo mono ${TEXINFO}/texinfo/texinfo.html
texinfo node ${TEXINFO}/texinfo/html_node/
#
info mono ${TEXINFO}/info/info.html
info node ${TEXINFO}/info/html_node/
#
info-stnd mono ${TEXINFO}/info-stnd/info-stnd.html
info-stnd node ${TEXINFO}/info-stnd/html_node/
+111 -76
View File
@@ -1,79 +1,114 @@
digraph "Guix package" {
"139803511371136" [label = "gcc-core-mesboot0@2.95.3", shape = box, fontname = sans];
"139803511371136" -> "139803511371312" [color = red];
"139803511371136" -> "139803511372016" [color = red];
"139803511371136" -> "139803511371488" [color = red];
"139803511371136" -> "139803511371664" [color = red];
"139803511371136" -> "139803511371840" [color = red];
"139803511371136" -> "139803507105792" [color = red];
"139803511371136" -> "139803511373600" [color = red];
"139803511371136" -> "139803507105968" [color = red];
"139803511371136" -> "139803749199472" [color = red];
"139803511371312" [label = "binutils-mesboot0@2.20.1a", shape = box, fontname = sans];
"139803511371312" -> "139803511372016" [color = dimgrey];
"139803511371312" -> "139803511371488" [color = dimgrey];
"139803511371312" -> "139803511371664" [color = dimgrey];
"139803511371312" -> "139803511371840" [color = dimgrey];
"139803511371312" -> "139803507105792" [color = dimgrey];
"139803511371312" -> "139803511373600" [color = dimgrey];
"139803511371312" -> "139803507105968" [color = dimgrey];
"139803511371312" -> "139803749199472" [color = dimgrey];
"139803511372016" [label = "gzip-mesboot@1.2.4", shape = box, fontname = sans];
"139803511372016" -> "139803511372192" [color = magenta];
"139803511372016" -> "139803507105792" [color = magenta];
"139803511372016" -> "139803511373600" [color = magenta];
"139803511372016" -> "139803507105968" [color = magenta];
"139803511372016" -> "139803749199472" [color = magenta];
"139803511372192" [label = "tcc-boot0@0.9.26-1136-g5bba73cc", shape = box, fontname = sans];
"139803511372192" -> "139803511372368" [color = magenta];
"139803511372192" -> "139803511372544" [color = magenta];
"139803511372192" -> "139803507105792" [color = magenta];
"139803511372192" -> "139803511373600" [color = magenta];
"139803511372192" -> "139803507105968" [color = magenta];
"139803511372192" -> "139803749199472" [color = magenta];
"139803511372368" [label = "mes-boot@0.24", shape = box, fontname = sans];
"139803511372368" -> "139803511372544" [color = darkviolet];
"139803511372368" -> "139803507105792" [color = darkviolet];
"139803511372368" -> "139803511373600" [color = darkviolet];
"139803511372368" -> "139803507105968" [color = darkviolet];
"139803511372368" -> "139803749199472" [color = darkviolet];
"139803511372544" [label = "stage0-posix@1.4", shape = box, fontname = sans];
"139803511372544" -> "139803511373072" [color = peachpuff4];
"139803511372544" -> "139803507105792" [color = peachpuff4];
"139803511372544" -> "139803511373600" [color = peachpuff4];
"139803511372544" -> "139803507105968" [color = peachpuff4];
"139803511372544" -> "139803749199472" [color = peachpuff4];
"139803511373072" [label = "bootstrap-seeds@1.0.0", shape = ellipse, fontname = sans];
"139803511373072" -> "139803507105968" [color = cyan3];
"139803507105968" [label = "bootar@1b", shape = box, fontname = sans];
"139803507105968" -> "139803749199472" [color = dimgrey];
"139803749199472" [label = "guile-bootstrap@2.0", shape = ellipse, fontname = sans];
"139803507105792" [label = "gash-boot@0.3.0", shape = box, fontname = sans];
"139803507105792" -> "139803507105968" [color = darkviolet];
"139803507105792" -> "139803749199472" [color = darkviolet];
"139803511373600" [label = "gash-utils-boot@0.2.0", shape = box, fontname = sans];
"139803511373600" -> "139803507105968" [color = red];
"139803511373600" -> "139803507105792" [color = red];
"139803511373600" -> "139803749199472" [color = red];
"139803511371488" [label = "patch-mesboot@2.5.9", shape = box, fontname = sans];
"139803511371488" -> "139803511371840" [color = darkseagreen];
"139803511371488" -> "139803511372192" [color = darkseagreen];
"139803511371488" -> "139803507105792" [color = darkseagreen];
"139803511371488" -> "139803511373600" [color = darkseagreen];
"139803511371488" -> "139803507105968" [color = darkseagreen];
"139803511371488" -> "139803749199472" [color = darkseagreen];
"139803511371840" [label = "make-mesboot0@3.80", shape = box, fontname = sans];
"139803511371840" -> "139803511372192" [color = blue];
"139803511371840" -> "139803507105792" [color = blue];
"139803511371840" -> "139803511373600" [color = blue];
"139803511371840" -> "139803507105968" [color = blue];
"139803511371840" -> "139803749199472" [color = blue];
"139803511371664" [label = "tcc-boot@0.9.27", shape = box, fontname = sans];
"139803511371664" -> "139803511371840" [color = peachpuff4];
"139803511371664" -> "139803511372192" [color = peachpuff4];
"139803511371664" -> "139803507105792" [color = peachpuff4];
"139803511371664" -> "139803511373600" [color = peachpuff4];
"139803511371664" -> "139803507105968" [color = peachpuff4];
"139803511371664" -> "139803749199472" [color = peachpuff4];
"139781154519456" [label = "gcc-core-mesboot0@2.95.3", shape = box, fontname = Helvetica];
"139781154519456" -> "139781154519632" [color = darkgoldenrod];
"139781154519456" -> "139781154520688" [color = darkgoldenrod];
"139781154519456" -> "139781034971312" [color = darkgoldenrod];
"139781154519456" -> "139781154520160" [color = darkgoldenrod];
"139781154519456" -> "139781034971664" [color = darkgoldenrod];
"139781154519456" -> "139781154519984" [color = darkgoldenrod];
"139781154519456" -> "139781154519808" [color = darkgoldenrod];
"139781154519456" -> "139781154520512" [color = darkgoldenrod];
"139781154519456" -> "139781034971488" [color = darkgoldenrod];
"139781154519456" -> "139781034972896" [color = darkgoldenrod];
"139781154519456" -> "139781034972368" [color = darkgoldenrod];
"139781154519456" -> "139781034973072" [color = darkgoldenrod];
"139781154519456" -> "139781131267872" [color = darkgoldenrod];
"139781154519632" [label = "binutils-mesboot0@2.14", shape = box, fontname = Helvetica];
"139781154519632" -> "139781154520688" [color = peachpuff4];
"139781154519632" -> "139781034971312" [color = peachpuff4];
"139781154519632" -> "139781154520160" [color = peachpuff4];
"139781154519632" -> "139781034971664" [color = peachpuff4];
"139781154519632" -> "139781154519984" [color = peachpuff4];
"139781154519632" -> "139781154519808" [color = peachpuff4];
"139781154519632" -> "139781154520512" [color = peachpuff4];
"139781154519632" -> "139781034971488" [color = peachpuff4];
"139781154519632" -> "139781034972896" [color = peachpuff4];
"139781154519632" -> "139781034972368" [color = peachpuff4];
"139781154519632" -> "139781034973072" [color = peachpuff4];
"139781154519632" -> "139781131267872" [color = peachpuff4];
"139781154520688" [label = "bash-mesboot0@2.05b", shape = box, fontname = Helvetica];
"139781154520688" -> "139781034971488" [color = magenta];
"139781154520688" -> "139781034971840" [color = magenta];
"139781154520688" -> "139781034972896" [color = magenta];
"139781154520688" -> "139781034972368" [color = magenta];
"139781154520688" -> "139781034973072" [color = magenta];
"139781154520688" -> "139781131267872" [color = magenta];
"139781034971488" [label = "make-mesboot0@3.80", shape = box, fontname = Helvetica];
"139781034971488" -> "139781034971840" [color = dimgrey];
"139781034971488" -> "139781034972896" [color = dimgrey];
"139781034971488" -> "139781034972368" [color = dimgrey];
"139781034971488" -> "139781034973072" [color = dimgrey];
"139781034971488" -> "139781131267872" [color = dimgrey];
"139781034971840" [label = "tcc-boot0@0.9.26-1103-g6e62e0e", shape = box, fontname = Helvetica];
"139781034971840" -> "139781034972016" [color = magenta];
"139781034971840" -> "139781131266816" [color = magenta];
"139781034971840" -> "139781034972896" [color = magenta];
"139781034971840" -> "139781034972368" [color = magenta];
"139781034971840" -> "139781034973072" [color = magenta];
"139781034971840" -> "139781131267872" [color = magenta];
"139781034972016" [label = "mes-boot@0.22", shape = box, fontname = Helvetica];
"139781034972016" -> "139781034972192" [color = cyan3];
"139781034972016" -> "139781131266816" [color = cyan3];
"139781034972016" -> "139781034972896" [color = cyan3];
"139781034972016" -> "139781034972368" [color = cyan3];
"139781034972016" -> "139781034973072" [color = cyan3];
"139781034972016" -> "139781131267872" [color = cyan3];
"139781034972192" [label = "bootstrap-mes-rewired@0.19", shape = ellipse, fontname = Helvetica];
"139781034972192" -> "139781131266640" [color = darkseagreen];
"139781034972192" -> "139781034972896" [color = darkseagreen];
"139781131266640" [label = "bootstrap-mes@0", shape = ellipse, fontname = Helvetica];
"139781034972896" [label = "gash-boot@0.2.0", shape = box, fontname = Helvetica];
"139781034972896" -> "139781034973072" [color = darkviolet];
"139781034972896" -> "139781131267872" [color = darkviolet];
"139781034973072" [label = "bootar@1", shape = box, fontname = Helvetica];
"139781034973072" -> "139781131267872" [color = darkviolet];
"139781131267872" [label = "guile-bootstrap@2.0", shape = ellipse, fontname = Helvetica];
"139781131266816" [label = "bootstrap-mescc-tools@0.5.2", shape = ellipse, fontname = Helvetica];
"139781034972368" [label = "gash-utils-boot@0.1.0", shape = box, fontname = Helvetica];
"139781034972368" -> "139781034973072" [color = darkseagreen];
"139781034972368" -> "139781034972896" [color = darkseagreen];
"139781034972368" -> "139781131267872" [color = darkseagreen];
"139781034971312" [label = "bzip2-mesboot@1.0.8", shape = box, fontname = Helvetica];
"139781034971312" -> "139781034971488" [color = cyan3];
"139781034971312" -> "139781034971840" [color = cyan3];
"139781034971312" -> "139781034972896" [color = cyan3];
"139781034971312" -> "139781034972368" [color = cyan3];
"139781034971312" -> "139781034973072" [color = cyan3];
"139781034971312" -> "139781131267872" [color = cyan3];
"139781154520160" [label = "diffutils-mesboot@2.7", shape = box, fontname = Helvetica];
"139781154520160" -> "139781034971488" [color = red];
"139781154520160" -> "139781034971840" [color = red];
"139781154520160" -> "139781034972896" [color = red];
"139781154520160" -> "139781034972368" [color = red];
"139781154520160" -> "139781034973072" [color = red];
"139781154520160" -> "139781131267872" [color = red];
"139781034971664" [label = "gzip-mesboot@1.2.4", shape = box, fontname = Helvetica];
"139781034971664" -> "139781034971840" [color = red];
"139781034971664" -> "139781034972896" [color = red];
"139781034971664" -> "139781034972368" [color = red];
"139781034971664" -> "139781034973072" [color = red];
"139781034971664" -> "139781131267872" [color = red];
"139781154519984" [label = "patch-mesboot@2.5.9", shape = box, fontname = Helvetica];
"139781154519984" -> "139781034971488" [color = blue];
"139781154519984" -> "139781034971840" [color = blue];
"139781154519984" -> "139781034972896" [color = blue];
"139781154519984" -> "139781034972368" [color = blue];
"139781154519984" -> "139781034973072" [color = blue];
"139781154519984" -> "139781131267872" [color = blue];
"139781154519808" [label = "sed-mesboot0@1.18", shape = box, fontname = Helvetica];
"139781154519808" -> "139781034971488" [color = red];
"139781154519808" -> "139781034971840" [color = red];
"139781154519808" -> "139781034972896" [color = red];
"139781154519808" -> "139781034972368" [color = red];
"139781154519808" -> "139781034973072" [color = red];
"139781154519808" -> "139781131267872" [color = red];
"139781154520512" [label = "tcc-boot@0.9.27", shape = box, fontname = Helvetica];
"139781154520512" -> "139781034971312" [color = darkviolet];
"139781154520512" -> "139781034971488" [color = darkviolet];
"139781154520512" -> "139781034971840" [color = darkviolet];
"139781154520512" -> "139781034972896" [color = darkviolet];
"139781154520512" -> "139781034972368" [color = darkviolet];
"139781154520512" -> "139781034973072" [color = darkviolet];
"139781154520512" -> "139781131267872" [color = darkviolet];
}
+36 -29
View File
@@ -22,8 +22,8 @@
# along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
# If adding a language, update the following variables, and info_TEXINFOS.
MANUAL_LANGUAGES = de es fr pt_BR ru zh_CN
COOKBOOK_LANGUAGES = de fr ko sk
MANUAL_LANGUAGES = de es fa fr it ko pt_BR ru sk zh_CN
COOKBOOK_LANGUAGES = de fa fr ko zh_Hans
# Arg1: A list of languages codes.
# Arg2: The file name stem.
@@ -34,15 +34,20 @@ 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.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.fa.texi \
%D%/guix-cookbook.fr.texi \
%D%/guix-cookbook.ko.texi \
%D%/guix-cookbook.sk.texi
%D%/guix-cookbook.zh_Hans.texi
%C%_guix_TEXINFOS = \
%D%/contributing.texi \
@@ -73,8 +78,7 @@ EXTRA_DIST += \
OS_CONFIG_EXAMPLES_TEXI = \
%D%/os-config-bare-bones.texi \
%D%/os-config-desktop.texi \
%D%/os-config-lightweight-desktop.texi \
%D%/he-config-bare-bones.scm
%D%/os-config-lightweight-desktop.texi
TRANSLATED_INFO = \
$(call lang_to_texinfo,$(MANUAL_LANGUAGES),guix) \
@@ -91,31 +95,46 @@ PO4A_PARAMS += -k 0 # produce an output even if the translation is not complete
PO4A_PARAMS += -f texinfo # texinfo format
# When a change to guix.texi occurs, it is not translated immediately.
# Because @pxref and @xref commands are references to sections by name, they
# Because @pxref and @xref commands are reference to a section by name, they
# should be translated. If a modification adds a reference to a section, this
# reference is not translated, which means it references a section that does not
# exist.
# This command loops through the translated files looking for references. For
# each of these references, it tries to find the translation and replaces the
# reference name, even in untranslated strings.
# The last sed is a multiline sed because some references span multiple lines.
define xref_command
$(top_srcdir)/pre-inst-env $(GUILE) --no-auto-compile \
"$(top_srcdir)/build-aux/convert-xref.scm" \
$@.tmp $<
cat "$@.tmp" | egrep '@p?x?ref' -A1 | sed 'N;s|--\n||g;P;D' | sed 's|^| |g' | \
tr -d '\012' | sed 's|\(@p\?x\?ref\)|\n\1|g' | egrep '@p?x?ref' | \
sed 's|^.*@p\?x\?ref{\([^,}]*\).*$$|\1|g' | sort | uniq | while read e; do \
if [ -n "$$e" ]; then \
line=$$(grep -n "^msgid \"$$e\"" "$<" | cut -f1 --delimiter=":") ;\
((line++)) ;\
if [ "$$line" != "1" ]; then \
translation=$$(head -n "$$line" "$<" | tail -1 | grep msgstr | sed 's|msgstr "\([^"]*\)"|\1|') ;\
if [ "$$translation" != "" ]; then \
sed "N;s@\(p\?x\?ref\){$$(echo $$e | sed 's| |[\\n ]|g')\(,\|}\)@\1{$$translation\2@g;P;D" -i "$@.tmp" ;\
fi ;\
fi ;\
fi ;\
done
endef
$(srcdir)/%D%/guix.%.texi: po/doc/guix-manual.%.po $(srcdir)/%D%/contributing.%.texi guix/build/po.go
$(srcdir)/%D%/guix.%.texi: po/doc/guix-manual.%.po $(srcdir)/%D%/contributing.%.texi
-$(AM_V_PO4A)$(PO4A_TRANSLATE) $(PO4A_PARAMS) -m "%D%/guix.texi" -p "$<" -l "$@.tmp"
-sed -i "s|guix\.info|$$(basename "$@" | sed 's|texi$$|info|')|" "$@.tmp"
-$(AM_V_POXREF)LC_ALL=en_US.UTF-8 $(xref_command)
-$(AM_V_POXREF)$(xref_command)
-mv "$@.tmp" "$@"
$(srcdir)/%D%/guix-cookbook.%.texi: po/doc/guix-cookbook.%.po guix/build/po.go
$(srcdir)/%D%/guix-cookbook.%.texi: po/doc/guix-cookbook.%.po
-$(AM_V_PO4A)$(PO4A_TRANSLATE) $(PO4A_PARAMS) -m "%D%/guix-cookbook.texi" -p "$<" -l "$@.tmp"
-sed -i "s|guix-cookbook\.info|$$(basename "$@" | sed 's|texi$$|info|')|" "$@.tmp"
-$(AM_V_POXREF)LC_ALL=en_US.UTF-8 $(xref_command)
-$(AM_V_POXREF)$(xref_command)
-mv "$@.tmp" "$@"
$(srcdir)/%D%/contributing.%.texi: po/doc/guix-manual.%.po guix/build/po.go
$(srcdir)/%D%/contributing.%.texi: po/doc/guix-manual.%.po
-$(AM_V_PO4A)$(PO4A_TRANSLATE) $(PO4A_PARAMS) -m "%D%/contributing.texi" -p "$<" -l "$@.tmp"
-$(AM_V_POXREF)LC_ALL=en_US.UTF-8 $(xref_command)
-$(AM_V_POXREF)$(xref_command)
-mv "$@.tmp" "$@"
%D%/os-config-%.texi: gnu/system/examples/%.tmpl
@@ -179,31 +198,19 @@ sub_commands_mans = \
$(srcdir)/%D%/guix-archive.1 \
$(srcdir)/%D%/guix-build.1 \
$(srcdir)/%D%/guix-challenge.1 \
$(srcdir)/%D%/guix-container.1 \
$(srcdir)/%D%/guix-copy.1 \
$(srcdir)/%D%/guix-deploy.1 \
$(srcdir)/%D%/guix-describe.1 \
$(srcdir)/%D%/guix-download.1 \
$(srcdir)/%D%/guix-edit.1 \
$(srcdir)/%D%/guix-environment.1 \
$(srcdir)/%D%/guix-gc.1 \
$(srcdir)/%D%/guix-git.1 \
$(srcdir)/%D%/guix-graph.1 \
$(srcdir)/%D%/guix-hash.1 \
$(srcdir)/%D%/guix-home.1 \
$(srcdir)/%D%/guix-import.1 \
$(srcdir)/%D%/guix-lint.1 \
$(srcdir)/%D%/guix-offload.1 \
$(srcdir)/%D%/guix-pack.1 \
$(srcdir)/%D%/guix-package.1 \
$(srcdir)/%D%/guix-processes.1 \
$(srcdir)/%D%/guix-publish.1 \
$(srcdir)/%D%/guix-pull.1 \
$(srcdir)/%D%/guix-refresh.1 \
$(srcdir)/%D%/guix-repl.1 \
$(srcdir)/%D%/guix-shell.1 \
$(srcdir)/%D%/guix-size.1 \
$(srcdir)/%D%/guix-style.1 \
$(srcdir)/%D%/guix-system.1 \
$(srcdir)/%D%/guix-time-machine.1 \
$(srcdir)/%D%/guix-weather.1
@@ -229,8 +236,8 @@ $(srcdir)/%D%/guix.1: scripts/guix.in $(sub_commands_mans)
# The 'case' ensures the man pages are only generated if the corresponding
# source script (the first prerequisite) has been changed. The $(GOBJECTS)
# prerequisite is solely meant to force these docs to be made only after all
# Guile modules have been compiled. We also need the guix script to exist.
$(srcdir)/%D%/guix-%.1: guix/scripts/%.scm $(GOBJECTS) scripts/guix
# Guile modules have been compiled.
$(srcdir)/%D%/guix-%.1: guix/scripts/%.scm $(GOBJECTS)
-@case '$?' in \
*$<*) $(AM_V_P) && set -x || echo " HELP2MAN $@"; \
$(gen_man) --output="$@" "guix $*";; \
+94 -208
View File
@@ -4,9 +4,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; 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,53 +26,17 @@
;;; 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))
(define* (break-string str #:optional (max-line-length 70))
"Break the string STR into lines that are no longer than MAX-LINE-LENGTH.
Return a single string."
(define (restore-line words)
(string-join (reverse words) " "))
(if (<= (string-length str) max-line-length)
str
(let ((words+lengths (map (lambda (word)
(cons word (string-length word)))
(string-tokenize str))))
(match (fold (match-lambda*
(((word . length)
(count current lines))
(let ((new-count (+ count length 1)))
(if (< new-count max-line-length)
(list new-count
(cons word current)
lines)
(list length
(list word)
(cons (restore-line current) lines))))))
'(0 () ())
words+lengths)
((_ last-words lines)
(string-join (reverse (cons (restore-line last-words) lines))
"\n"))))))
(define* (break-string-with-newlines str #:optional (max-line-length 70))
"Break the lines of string STR into lines that are no longer than
MAX-LINE-LENGTH. Return a single string."
(string-join (map (cut break-string <> max-line-length)
(string-split str #\newline))
"\n"))
(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 textual-ports))
(define (read-excursion port)
"Read an expression from PORT and reset the port position before returning
@@ -101,16 +62,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 +76,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 +95,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 +128,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,13 +176,8 @@ 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)
(()
;; New-style plain lists
(match ((xpath:sxpath `(// ,field list *)) expr)
((inner) inner)
(_ '())))
;; Old-style labelled inputs
(match ((sxpath `(// ,field quasiquote *)) expr)
(() '())
((first . rest)
(map cadadr first))))
(define (listify items)
@@ -244,7 +191,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.~%"
@@ -257,70 +204,26 @@ corresponding to the top-level definition containing the staged changes."
(added (lset-difference equal? new-values old-values)))
(format port
"[~a]: ~a~%" field
(break-string
(match (list (map symbol->string removed)
(map symbol->string added))
((() added)
(format #f "Add ~a."
(listify added)))
((removed ())
(format #f "Remove ~a."
(listify removed)))
((removed added)
(format #f "Remove ~a; add ~a."
(listify removed)
(listify added))))))))))
(match (list (map symbol->string removed)
(map symbol->string added))
((() added)
(format #f "Add ~a."
(listify added)))
((removed ())
(format #f "Remove ~a."
(listify removed)))
((removed added)
(format #f "Remove ~a; add ~a."
(listify removed)
(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.~%"
(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.~%"
variable-name file-name variable-name))
(define* (custom-commit-message file-name variable-name message changelog
#:optional (port (current-output-port)))
"Print custom commit message for a change to VARIABLE-NAME in FILE-NAME, using
MESSAGE as the commit message and CHANGELOG as the body of the ChangeLog
entry. If CHANGELOG is #f, the commit message is reused. If CHANGELOG already
contains ': ', no colon is inserted between the location and body of the
ChangeLog entry."
(define (trim msg)
(string-trim-right (string-trim-both msg) (char-set #\.)))
(define (changelog-has-location? changelog)
(->bool (string-match "^[[:graph:]]+:[[:blank:]]" changelog)))
(let* ((message (trim message))
(changelog (if changelog (trim changelog) message))
(message/f (format #f "gnu: ~a: ~a." variable-name message))
(changelog/f (if (changelog-has-location? changelog)
(format #f "* ~a (~a)~a."
file-name variable-name changelog)
(format #f "* ~a (~a): ~a."
file-name variable-name changelog))))
(format port
"~a~%~%~a~%"
(break-string-with-newlines message/f 72)
(break-string-with-newlines changelog/f 72))))
(define (add-copyright-line line)
"Add the copyright line on LINE to the previous commit."
(let ((author (match:substring
(string-match "^\\+;;; Copyright ©[^[:alpha:]]+(.*)$" line)
1)))
(format
(current-output-port) "Amend and add copyright line for ~a~%" author)
(system* "git" "commit" "--amend" "--no-edit")))
(define (group-hunks-by-sexp hunks)
"Return a list of pairs associating all hunks with the S-expression they are
modifying."
@@ -349,80 +252,63 @@ modifying."
(define %delay 1000)
(define (main . args)
(define* (change-commit-message* file-name old new #:rest rest)
(let ((changelog #f))
(match args
((or (message changelog) (message))
(apply custom-commit-message
file-name (second old) message changelog rest))
(_
(apply change-commit-message file-name old new rest)))))
(match (diff-info)
(()
(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))))))
(apply main (cdr (command-line)))
(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)
(change-commit-message (hunk-file-name (first hunks))
old new
(current-output-port))
(let ((port (open-pipe* OPEN_WRITE "git" "commit" "-F" "-")))
(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)))))))
(main)
+100 -148
View File
@@ -1,6 +1,5 @@
# GNU Guix --- Functional package management for GNU
# Copyright © 2015-2022 Ludovic Courtès <ludo@gnu.org>
# Copyright © 2021 Tobias Geerinck-Rice <me@tobias.gr>
# Copyright © 2015, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
#
# This file is part of GNU Guix.
#
@@ -28,12 +27,11 @@ _guix_complete_command ()
if [ -z "$_guix_commands" ]
then
# Cache the list of commands to speed things up.
_guix_commands="$(${COMP_WORDS[0]} --help 2> /dev/null \
_guix_commands="$(guix --help 2> /dev/null \
| grep '^ ' \
| sed '-es/^ *\([a-z-]\+\).*$/\1/g')"
fi
COMPREPLY+=($(compgen -W "$_guix_commands" -- "$word_at_point"))
COMPREPLY=($(compgen -W "$_guix_commands" -- "$word_at_point"))
}
_guix_complete_subcommand ()
@@ -42,7 +40,7 @@ _guix_complete_subcommand ()
local subcommands="$(${COMP_WORDS[0]} $command --help 2> /dev/null \
| grep '^ [a-z]' \
| sed -e's/^ \+\([a-z-]\+\).*$/\1/g')"
COMPREPLY+=($(compgen -W "$subcommands" -- "${COMP_WORDS[$COMP_CWORD]}"))
COMPREPLY=($(compgen -W "$subcommands" -- "${COMP_WORDS[$COMP_CWORD]}"))
}
_guix_complete_available_package ()
@@ -55,7 +53,7 @@ _guix_complete_available_package ()
_guix_available_packages="$(${COMP_WORDS[0]} package -A 2> /dev/null \
| cut -f1)"
fi
COMPREPLY+=($(compgen -W "$_guix_available_packages" -- "$prefix"))
COMPREPLY=($(compgen -W "$_guix_available_packages" -- "$prefix"))
}
_guix_complete_installed_package ()
@@ -65,40 +63,36 @@ _guix_complete_installed_package ()
local prefix="$1"
local packages="$(${COMP_WORDS[0]} package -I "^$prefix" 2> /dev/null \
| cut -f1)"
COMPREPLY+=($(compgen -W "$packages" -- "$prefix"))
COMPREPLY=($(compgen -W "$packages" -- "$prefix"))
}
_guix_complete_option ()
{
local command="${COMP_WORDS[$1]}"
local subcommand="${COMP_WORDS[$(($1 + 1))]}"
if [ $1 -eq 0 ]
then
command=""
subcommand=""
elif _guix_is_option "$subcommand"
then
subcommand=""
fi
local options="$(${COMP_WORDS[0]} $command $subcommand --help 2> /dev/null \
local subcommand
case "${COMP_WORDS[2]}" in
-*) subcommand="";;
[a-z]*) subcommand="${COMP_WORDS[2]}";;
esac
local options="$(${COMP_WORDS[0]} ${COMP_WORDS[1]} $subcommand --help 2> /dev/null \
| grep '^ \+-' \
| sed -e's/^.*--\([a-zA-Z0-9_-]\+\)\(=\?\).*/--\1\2/g')"
compopt -o nospace
COMPREPLY+=($(compgen -W "$options" -- "$2"))
COMPREPLY=($(compgen -W "$options" -- "${COMP_WORDS[${#COMP_WORDS[*]} - 1]}"))
}
_guix_is_option ()
_guix_is_command ()
{
case "$1" in
-*)
true
;;
*)
false
;;
esac
local word
local result="false"
for word in ${COMP_WORDS[*]}
do
if [ "$word" = "$1" ]
then
result=true
break
fi
done
$result
}
_guix_is_removing ()
@@ -117,59 +111,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 ()
@@ -179,22 +172,10 @@ _guix_complete_file ()
COMPREPLY=()
}
_guix_complete_available_package_or_store_file ()
{
_guix_complete_available_package "$@"
# The current _guix_complete_file implementation doesn't compose (append to
# COMPREPLY), so we suggest file names only if no package names matched.
if [[ -z "$COMPREPLY" ]]
then
_guix_complete_file # TODO: restrict to store files
fi
}
_guix_complete_pid ()
{
local pids="$(cd /proc; echo [0-9]*)"
COMPREPLY+=($(compgen -W "$pids" -- "$1"))
COMPREPLY=($(compgen -W "$pids" -- "$1"))
}
_guix_complete ()
@@ -202,44 +183,22 @@ _guix_complete ()
local word_count=${#COMP_WORDS[*]}
local word_at_point="${COMP_WORDS[$COMP_CWORD]}"
# Find the innermost command at point, e.g. "build" in the case of
# "guix time-machine OPTIONS -- build<Tab>" -- but "time-machine" if
# point is moved before "build".
local command_index=0
local command
local word_index=0
local word
local expect_command="true"
while [[ $((++word_index)) -le COMP_CWORD ]]
do
word="${COMP_WORDS[$word_index]}"
if $expect_command
then
command_index=$word_index
command="$word"
expect_command="false"
continue
fi
if [[ "$word" = "--" ]]
then
case "$command" in
environment|shell)
break
;;
time-machine)
expect_command="true"
;;
esac
fi
done
if [ "$COMP_CWORD" -gt 1 ]
then
case "$word_at_point" in
-*)
_guix_complete_option "$word_at_point"
return
;;
esac
fi
case $COMP_CWORD in
$command_index)
1)
_guix_complete_command
_guix_complete_option 0 "$word_at_point"
;;
*)
if [[ "$command" = "package" ]]
if _guix_is_command "package"
then
if _guix_is_dash_L || _guix_is_dash_m || _guix_is_dash_p || _guix_is_dash_f
then
@@ -250,7 +209,7 @@ _guix_complete ()
else
_guix_complete_available_package "$word_at_point"
fi
elif [[ "$command" = "install" ]]
elif _guix_is_command "install"
then
if _guix_is_dash_L || _guix_is_dash_m || _guix_is_dash_p
then
@@ -258,7 +217,7 @@ _guix_complete ()
else
_guix_complete_available_package "$word_at_point"
fi
elif [[ "$command" = "upgrade" || "$command" = "remove" ]]
elif _guix_is_command "remove"
then
if _guix_is_dash_L || _guix_is_dash_m || _guix_is_dash_p
then
@@ -266,84 +225,77 @@ _guix_complete ()
else
_guix_complete_installed_package "$word_at_point"
fi
elif [[ "$command" = "build" ]]
elif _guix_is_command "upgrade"
then
if _guix_is_dash_L || _guix_is_dash_m || _guix_is_dash_p
then
_guix_complete_file
else
_guix_complete_installed_package "$word_at_point"
fi
elif _guix_is_command "build"
then
if _guix_is_dash_L || _guix_is_dash_m || _guix_is_dash_f
then
_guix_complete_file
else
_guix_complete_available_package_or_store_file "$word_at_point"
_guix_complete_available_package "$word_at_point"
fi
elif [[ "$command" = "environment" || "$command" = "shell" ]]
elif _guix_is_command "environment"
then
if _guix_is_dash_f && [[ "$command" = "shell" ]]
then
# The otherwise identical guix environment lacks the -f option.
_guix_complete_file
elif _guix_is_dash_L || _guix_is_dash_m || _guix_is_dash_p || _guix_is_dash_l
then
_guix_complete_file
elif _guix_is_option "$word_at_point"
then
_guix_complete_option "$command_index" "$word_at_point"
if _guix_is_dash_L || _guix_is_dash_m || _guix_is_dash_p || _guix_is_dash_l
then
_guix_complete_file
else
_guix_complete_available_package "$word_at_point"
fi
elif [[ "$command" = "download" || "$command" = "gc" || "$command" = "hash" ]]
elif _guix_is_command "download"
then
_guix_complete_file
elif [[ "$command" = "size" ]]
_guix_complete_file
elif _guix_is_command "system"
then
_guix_complete_available_package_or_store_file "$word_at_point"
elif [[ "$command" = "system" || "$command" = "home" ]]
then
case $((COMP_CWORD - command_index)) in
1) _guix_complete_subcommand;;
case $COMP_CWORD in
2) _guix_complete_subcommand;;
*) _guix_complete_file;; # TODO: restrict to *.scm
esac
elif [[ "$command" = "pull" ]]
elif _guix_is_command "pull"
then
if _guix_is_dash_C || _guix_is_dash_p
then
_guix_complete_file
fi
elif [[ "$command" = "time-machine" ]]
elif _guix_is_command "time-machine"
then
if _guix_is_dash_C
then
_guix_complete_file
else
_guix_complete_option "$command_index" "$word_at_point"
_guix_complete_command
fi
elif [[ "$command" = "container" ]]
elif _guix_is_command "container"
then
case $((COMP_CWORD - command_index)) in
1) _guix_complete_subcommand;;
2) _guix_complete_pid "$word_at_point";;
case $COMP_CWORD in
2) _guix_complete_subcommand;;
3) _guix_complete_pid "$word_at_point";;
*) _guix_complete_file;;
esac
elif [[ "$command" = "import" ]]
elif _guix_is_command "import"
then
_guix_complete_subcommand
elif [[ "$command" = "weather" ]]
elif _guix_is_command "hash" || _guix_is_command "gc"
then
_guix_complete_file
elif _guix_is_command "weather"
then
if _guix_is_dash_m
then
_guix_complete_file
else
_guix_complete_available_package "$word_at_point"
fi
else
_guix_complete_available_package "$word_at_point"
fi
;;
esac
if [[ -z "$COMPREPLY" && COMP_CWORD -gt command_index ]] &&
_guix_is_option "$word_at_point"
then
_guix_complete_option "$command_index" "$word_at_point"
fi
}
complete -F _guix_complete guix
+102 -309
View File
@@ -2,8 +2,6 @@
#
# GNU Guix --- Functional package management for GNU
# Copyright © 2016 Eric Le Bihan <eric.le.bihan.dev@free.fr>
# Copyright © 2021 Noah Evans <noah@nevans.me>
# Copyright © 2021 Brice Waegeneire <brice@waegenei.re>
#
# This file is part of GNU Guix.
#
@@ -58,7 +56,6 @@ _guix_list_available_packages()
if ( [[ ${+_guix_available_packages} -eq 0 ]] || _cache_invalid GUIX_AVAILABLE_PACKAGES ) \
&& ! _retrieve_cache GUIX_AVAILABLE_PACKAGES; then
_guix_available_packages=(${${(f)"$(guix package -A | cut -f1)"}})
_guix_available_packages=("${_guix_available_packages[@]// /}")
_store_cache GUIX_AVAILABLE_PACKAGES _guix_available_packages
fi
}
@@ -71,24 +68,21 @@ _guix_list_installed_packages()
(( $+functions[_guix_build] )) || _guix_build()
{
_arguments \
{-e,--expression=}'[build the package or derivation EXPR evaluates to]:EXPR' \
{-f,--file=}'[build the package or derivation that the code within FILE evaluates to]:FILE:_files' \
{-m,--manifest=}'[build the packages that the manifest given in FILE evaluates to]:FILE:_files' \
{-S,--source}'[build the packages source derivations]' \
'--sources=[build source derivations]:TYPE:(package all transitive)' \
{-s,--system=}'[attempt to build for SYSTEM (e.g. "i686-linux")]:SYSTEM' \
'--expression=[build the package matching EXPR]:EXPR' \
'--file=[build the package matching code evaluated from FILE]:FILE:_files' \
'--source[build the packages source derivations]' \
'--sources=[build source derivations]:TYPE:(all package transitive)' \
'--system=[attempt to build for SYSTEM (e.g. "i686-linux")]:SYSTEM' \
'--target=[cross-build for TRIPLET (e.g. "armel-linux-gnu")]:TRIPLET' \
{-d,--derivations}'[return the derivation paths of the given packages]' \
'--derivations[return the derivation paths of the given packages]' \
'--check[rebuild items to check for non-determinism issues]' \
'--repair[repair the specified items]' \
{-r,--root=}'[make FILE a symlink to the result, and register it as a GC root]:FILE:_files' \
{-v,--verbosity=}'[use the given verbosity LEVEL]:LEVEL' \
{-q,--quiet}'[do not show the build log]' \
'--root=[symlink result to FILE and register it as GC root]:FILE:_files' \
'--quiet[do not show the build log]' \
'--log-file[return the log file names for the given derivations]' \
{-L,--load-path=}'[prepend DIR to the package module search path]:DIR:_files -\' \
{-K,--keep-failed}'[keep build tree of failed builds]' \
{-k,--keep-going}'[keep going when some of the derivations fail]' \
{-n,--dry-run}'[do not build the derivations]' \
'--load-path=[prepend DIR to the package module search path]:DIR:_dirs' \
'--keep-failed[keep build tree of failed builds]' \
'--keep-going[keep going when some of the derivations fail]' \
'--dry-run[do not build the derivations]' \
'--fallback[fall back to building when the substituter fails]' \
'--no-substitutes[build instead of resorting to pre-built substitutes]' \
'--substitute-urls=[fetch substitute from URLS if they are authorized]:URLS:_urls' \
@@ -96,12 +90,12 @@ _guix_list_installed_packages()
'--no-offload[do not attempt to offload builds]' \
'--max-silent-time=[mark the build as failed after SECONDS of silence]:SECONDS' \
'--timeout=[mark the build as failed after SECONDS of activity]:SECONDS' \
'--verbosity=[use the given verbosity LEVEL]:LEVEL' \
'--rounds=[build N times in a row to detect non-determinism]:N' \
{-c,--cores=}'[allow the use of up to N CPU cores for the build]:N' \
{-M,--max-jobs=}'[allow at most N build jobs]:N' \
'--debug=[produce debugging output at LEVEL]:LEVEL' \
'--help-transform[list package transformation options not shown here]' \
{-V,--version}'[display version information and exit]' \
'--cores=[allow the use of up to N CPU cores for the build]:N' \
'--max-jobs=[allow at most N build jobs]:N' \
'--with-source=[use SOURCE when building the corresponding package]:SOURCE' \
'--with-input=[replace dependency PACKAGE by REPLACEMENT]:PACKAGE=REPLACEMENT' \
'*:package:->packages'
if [[ "$state" = packages ]]; then
@@ -113,10 +107,7 @@ _guix_list_installed_packages()
(( $+functions[_guix_challenge] )) || _guix_challenge()
{
_arguments \
'--substitute-urls=[compare build results with those at URLS]:URLS:_urls' \
'--diff=[show differences according to MODE]:MODE' \
{-v,--verbose}'[show details about successful comparisons]' \
{-V,--version}'[display version information and exit]' \
'--substitute-urls=[fetch substitute from URLS if they are authorized]:URL:_urls' \
'*:package:->packages'
if [[ "$state" = packages ]]; then
@@ -135,11 +126,7 @@ _guix_list_installed_packages()
(( $+functions[_guix_download] )) || _guix_download()
{
_arguments \
{-f,--format=}'[write the hash in the given format]:FMT:(nix-base32 base16 base32 hex)' \
{-H,--hash=}'[use the given hash ALGORITHM]:ALGORITHM' \
'--no-check-certificate[do not validate the certificate of HTTPS servers ]' \
{-o,--output=}'[download to FILE]:FILE:_files' \
{-V,--version}'[display version information and exit]' \
'--format=[write the hash in the given format]:FMT:(nix-base32 base16 base32 hex)' \
'1:URL:_urls'
}
@@ -152,29 +139,21 @@ _guix_list_installed_packages()
(( $+functions[_guix_environment] )) || _guix_environment()
{
_arguments \
{-e,--expression=}'[create environment for the package that EXPR evaluates to]:EXPR' \
{-l,--load=}'[create environment for the package that the code within FILE evaluates to]:FILE:_files' \
{-m,--manifest=}'[create environment with the manifest from FILE]:FILE:_files' \
{-p,--profile=}'[create environment from profile at PATH]:PATH:_files -/' \
'--ad-hoc[include all specified packages in the environment instead of only their inputs]' \
'--expression=[create environment for the package evaluated from EXPR]:EXPR' \
'--load=[create environment for the package evaluated from FILE]:FILE:_files' \
'--ad-hoc[include all specified packages, not only their inputs]' \
'--pure[unset existing environment variables]' \
{-E,--preserve=}'[preserve environment variables that match REGEXP]:REGEXP' \
'--search-paths[display needed environment variable definitions]' \
{-s,--system=}'[attempt to build for SYSTEM (e.g. "i686-linux")]:SYSTEM' \
{-r,--root=}'[make FILE a symlink to the result, and register it as a GC root]:FILE:_files' \
{-C,--container}'[run command within an isolated container]' \
{-N,--network}'[allow containers to access the network]' \
{-P,--link-profile}'[link environment profile to ~/.guix-profile within an isolated container]' \
{-u,--user=}'[instead of copying the name and home of the current user into an isolated container, use the name USER with home directory /home/USER]:USER:_users' \
'--no-cwd[do not share current working directory with an isolated container]' \
'--share=[for containers, share writable host file system according to SPEC]:SPEC' \
'--expose=[for containers, expose read-only host file system according to SPEC]:SPEC' \
{-v,--verbosity=}'[use the given verbosity LEVEL]:LEVEL' \
'--system=[attempt to build for SYSTEM (e.g. "i686-linux")]:SYSTEM' \
'--container[run command within an isolated container]' \
'--network[allow containers to access the network]' \
'--share=[share writable host file system according to SPEC]:SPEC' \
'--expose=[expose read-only host file system according to SPEC]:SPEC' \
'--bootstrap[use bootstrap binaries to build the environment]' \
{-L,--load-path=}'[prepend DIR to the package module search path]:DIR:_files -/' \
{-K,--keep-failed}'[keep build tree of failed builds]' \
{-k,--keep-going}'[keep going when some of the derivations fail]' \
{-n,--dry-run}'[do not build the derivations]' \
'--load-path=[prepend DIR to the package module search path]:DIR:_dirs' \
'--keep-failed[keep build tree of failed builds]' \
'--keep-going[keep going when some of the derivations fail]' \
'--dry-run[do not build the derivations]' \
'--fallback[fall back to building when the substituter fails]' \
'--no-substitutes[build instead of resorting to pre-built substitutes]' \
'--substitute-urls=[fetch substitute from URLS if they are authorized]:URLS:_urls' \
@@ -182,12 +161,10 @@ _guix_list_installed_packages()
'--no-offload[do not attempt to offload builds]' \
'--max-silent-time=[mark the build as failed after SECONDS of silence]:SECONDS' \
'--timeout=[mark the build as failed after SECONDS of activity]:SECONDS' \
'--verbosity=[use the given verbosity LEVEL]:LEVEL' \
'--rounds=[build N times in a row to detect non-determinism]:N' \
{-c,--cores=}'[allow the use of up to N CPU cores for the build]:N' \
{-M,--max-jobs=}'[allow at most N build jobs]:N' \
'--debug=[produce debugging output at LEVEL]:LEVEL' \
'--help-transform[list package transformation options not shown here]' \
{-V,--version}'[display version information and exit]' \
'--cores=[allow the use of up to N CPU cores for the build]:N' \
'--max-jobs=[allow at most N build jobs]:N' \
'*:package:->packages'
if [[ "$state" = packages ]]; then
@@ -200,39 +177,27 @@ _guix_list_installed_packages()
(( $+functions[_guix_gc] )) || _guix_gc()
{
_arguments \
{-C,--collect-garbage=}'[collect at least MIN bytes of garbage]:MIN' \
{-F,--free-space=}'[attempt to reach FREE available space in the store]:FREE' \
{-d,--delete-generations=}'[delete profile generations matching PATTERN]:PATTERN' \
{-D,--delete}'[attempt to delete PATHS]' \
'--list-roots[list the users GC roots]' \
'--list-busy[list store items used by running processes]' \
'--collect-garbage=[collect at least MIN bytes of garbage]:MIN' \
'--free-space=[attempt to reach FREE available space in the store]:FREE' \
'--delete[attempt to delete PATHS]' \
'--optimize[optimize the store by deduplicating identical files]' \
'--list-dead[list dead paths]' \
'--list-live[list live paths]' \
'--references[list the references of PATHS]' \
{-R,--requisites}'[list the requisites of PATHS]' \
'--requisites[list the requisites of PATHS]' \
'--referrers[list the referrers of PATHS]' \
'--derivers[list the derivers of PATHS]' \
'--verify=[verify the integrity of the store]:OPTS:(contents repair)' \
'--list-failures[list cached build failures]' \
'--clear-failures[remove PATHS from the set of cached failures]' \
{-V,--version}'[display version information and exit]:V' \
'1:PATH:_files -/'
'1:PATH:_dirs'
}
(( $+functions[_guix_graph] )) || _guix_graph()
{
_arguments \
{-b,--backend=}'[produce a graph with the given backend TYPE]:TYPE:->types' \
'--list-backends[list the available graph backends]' \
{-t,--type=}'[represent nodes of the given TYPE]:TYPE:->types' \
'--type=[represent nodes of the given TYPE]:TYPE:->types' \
'--list-types[list the available graph types]' \
'--path[display the shortest path between the given nodes]' \
{-e,--expression=}'[consider the package EXPR evaluates to]:EXPR' \
{-s,--system=}'[consider the graph for SYSTEM (e.g. "i686-linux")]:SYSTEM' \
{-L,--load-path=}'[prepend DIR to the package module search path]:DIR:_files -/' \
'--help-transform[list package transformation options not shown here]' \
{-V,--version}'[display version information and exit]' \
'--expression=[consider the package EXPR evaluates to]:EXPR' \
'1:PACKAGE:->packages'
case "$state" in
@@ -251,18 +216,14 @@ _guix_list_installed_packages()
(( $+functions[_guix_hash] )) || _guix_hash()
{
_arguments \
{-x,--exclude-vcs}'[exclude version control directories]' \
{-H,--hash=}'[use the given hash ALGORITHM]:ALGORITHM' \
{-f,--format=}'[write the hash in the given format]:FMT:(nix-base32 base16 base32 hex)' \
{-r,--recursive}'[compute the hash on FILE recursively]' \
{-V,--version}'[display version information and exit]' \
'--format=[write the hash in the given format]:FMT:(nix-base32 base16 base32 hex)' \
'--recursive[compute the hash on FILE recursively]'\
'1:FILE:_files'
}
(( $+functions[_guix_import] )) || _guix_import()
{
_arguments \
{-V,--version}'[display version information and exit]' \
'1:IMPORTER:->importer' \
'*:args:'
@@ -275,12 +236,8 @@ _guix_list_installed_packages()
(( $+functions[_guix_lint] )) || _guix_lint()
{
_arguments \
{-c,--checkers=}'[only run the specified checkers]:CHECKERS:->checkers' \
{-x,--exclude=}'[exclude the specified checkers]:CHECKERSS:->checkers' \
{-n,--no-network}'[only run checkers that do not access the network]' \
{-L,--load-path=}'[prepend DIR to the package module search path]:DIR:_files -/' \
{-l,--list-checkers}'[display the list of available lint checkers]' \
{-V,--version}'[display version information and exit]' \
'--checkers=[only run the specified checkers]:CHECKERS:->checkers' \
'--list-checkers[display the list of available lint checkers]' \
'1:PACKAGE:->packages'
case "$state" in
@@ -298,32 +255,29 @@ _guix_list_installed_packages()
(( $+functions[_guix_package] )) || _guix_package()
{
_arguments \
{-i,--install}'[install one or more packages]: :->install' \
{-e,--install-from-expression=}'[install the package EXP evaluates to]:EXP' \
{-f,--install-from-file=}'[install the package evaluated from FILE]:FILE:_files' \
{-r,--remove}'[remove one or more packages]: :->remove' \
{-u,--upgrade=}'[upgrade all the installed packages matching REGEXP]:REGEXP' \
{-m,--manifest=}'[create a new profile generation from FILE]:FILE:_files' \
'--install[install one or more packages]: :->install' \
'--install-from-expression=[install the package EXP evaluates to]:EXP' \
'--install-from-file=[install the package evaluated from FILE]:FILE:_files' \
'--remove[remove one or more packages]: :->remove' \
'--upgrade=[upgrade all the installed packages matching REGEXP]:REGEXP' \
'--manifest=[create a new profile generation from FILE]:FILE:_files' \
'--do-not-upgrade=[do not upgrade any packages matching REGEXP]:REGEXP' \
'--roll-back[roll back to the previous generation]' \
'--search-paths=[display needed environment variable definitions]:KINDS' \
{-l,--list-generations=}'[list generations matching PATTERN]:PATTERN' \
{-d,--delete-generations=}'[delete generations matching PATTERN]:PATTERN' \
{-S,--switch-generation=}'[switch to a generation matching PATTERN]:PATTERN' \
'--export-manifest[print a manifest for the chosen profile]' \
'--export-channels[print channels for the chosen profile]' \
{-p,--profile}'[use PROFILE instead of the default profile]:PROFILE:_files -/' \
'--list-profiles[list the profiles]' \
'--allow-collisions[do not treat collisions in the profile as an error]' \
'--list-generations=[list generations matching PATTERN]:PATTERN' \
'--delete-generations=[delete generations matching PATTERN]:PATTERN' \
'--switch-generation=[switch to a generation matching PATTERN]:PATTERN' \
'--profile=[use PROFILE instead of the default profile]:PROFILE' \
'--bootstrap[use the bootstrap Guile to build the profile]' \
{-s,--search=}'[search in synopsis and description using REGEXP]:REGEXP' \
{-I,--list-installed=}'[list installed packages matching REGEXP]:REGEXP' \
{-A,--list-available=}'[list available packages matching REGEXP]:REGEXP' \
'--verbose[produce verbose output]' \
'--search=[search in synopsis and description using REGEXP]:REGEXP' \
'--list-installed=[list installed packages matching REGEXP]:REGEXP' \
'--list-available=[list available packages matching REGEXP]:REGEXP' \
'--show=[show details about a package]: :->show' \
{-L,--load-path=}'[prepend DIR to the package module search path]:DIR:_files -/' \
{-K,--keep-failed}'[keep build tree of failed builds]' \
{-k,--keep-going}'[keep going when some of the derivations fail]' \
{-n,--dry-run}'[do not build the derivations]' \
'--load-path=[prepend DIR to the package module search path]:DIR:_dirs' \
'--keep-failed[keep build tree of failed builds]' \
'--keep-going[keep going when some of the derivations fail]' \
'--dry-run[do not build the derivations]' \
'--fallback[fall back to building when the substituter fails]' \
'--no-substitutes[build instead of resorting to pre-built substitutes]' \
'--substitute-urls=[fetch substitute from URLS if they are authorized]:URLS:_urls' \
@@ -331,13 +285,12 @@ _guix_list_installed_packages()
'--no-offload[do not attempt to offload builds]' \
'--max-silent-time=[mark the build as failed after SECONDS of silence]:SECONDS' \
'--timeout=[mark the build as failed after SECONDS of activity]:SECONDS' \
'--verbosity=[use the given verbosity LEVEL]:LEVEL' \
'--rounds=[build N times in a row to detect non-determinism]:N' \
{-c,--cores=}'[allow the use of up to N CPU cores for the build]:N' \
{-M,--max-jobs=}'[allow at most N build jobs]:N' \
'--debug=[produce debugging output at LEVEL]' \
'--help-transform[list package transformation options not shown here]' \
{-v,--verbosity=}'[use the given verbosity LEVEL]' \
{-V,--version}'[display version information and exit]'
'--cores=[allow the use of up to N CPU cores for the build]:N' \
'--max-jobs=[allow at most N build jobs]:N' \
'--with-source=[use SOURCE when building the corresponding package]:SOURCE' \
'--with-input=[replace dependency PACKAGE by REPLACEMENT]:PACKAGE=REPLACEMENT'
case "$state" in
install|show)
@@ -351,165 +304,37 @@ _guix_list_installed_packages()
esac
}
(( $+functions[_guix_install] )) || _guix_install()
{
_arguments \
{-p,--profile=}'[use PROFILE instead of the users default profile]:PROFILE:_files -/' \
{-v,--verbosity=}'[use the given verbosity LEVEL]:LEVEL' \
{-L,--load-path=}'[prepend DIR to the package module search path]:DIR:_files -/' \
{-K,--keep-failed}'[keep build tree of failed builds]' \
{-k,--keep-going}'[keep going when some of the derivations fail]' \
{-n,--dry-run}'[do not build the derivations]' \
'--fallback[fall back to building when the substituter fails]' \
'--no-substitutes[build instead of resorting to pre-built substitutes]' \
'--substitute-urls=[fetch substitute from URLS if they are authorized]:URLS:_urls' \
'--no-grafts[do not graft packages]' \
'--no-offload[do not attempt to offload builds]' \
'--max-silent-time=[mark the build as failed after SECONDS of silence]:SECONDS' \
'--timeout=[mark the build as failed after SECONDS of activity]:SECONDS' \
'--rounds=[build N times in a row to detect non-determinism]:N' \
{-c,--cores=}'[allow the use of up to N CPU cores for the build]:N' \
{-M,--max-jobs=}'[allow at most N build jobs]:N' \
'--debug=[produce debugging output at LEVEL]:LEVEL' \
'--help-transform[list package transformation options not shown here]' \
{-V,--version}'[display version information and exit]' \
'*:package:->packages'
if [[ "$state" = packages ]]; then
_guix_list_available_packages
compadd -a -- _guix_available_packages
fi
}
(( $+functions[_guix_remove] )) || _guix_remove()
{
_arguments \
{-p,--profile=}'[use PROFILE instead of the users default profile]:PROFILE:_files -/' \
{-v,--verbosity=}'[use the given verbosity LEVEL]:LEVEL' \
{-L,--load-path=}'[prepend DIR to the package module search path]:DIR:_files -/' \
{-K,--keep-failed}'[keep build tree of failed builds]' \
{-k,--keep-going}'[keep going when some of the derivations fail]' \
{-n,--dry-run}'[do not build the derivations]' \
'--fallback[fall back to building when the substituter fails]' \
'--no-substitutes[build instead of resorting to pre-built substitutes]' \
'--substitute-urls=[fetch substitute from URLS if they are authorized]:URLS:_urls' \
'--no-grafts[do not graft packages]' \
'--no-offload[do not attempt to offload builds]' \
'--max-silent-time=[mark the build as failed after SECONDS of silence]:SECONDS' \
'--timeout=[mark the build as failed after SECONDS of activity]:SECONDS' \
'--rounds=[build N times in a row to detect non-determinism]:N' \
{-c,--cores=}'[allow the use of up to N CPU cores for the build]:N' \
{-M,--max-jobs=}'[allow at most N build jobs]:N' \
'--debug=[produce debugging output at LEVEL]:LEVEL' \
{-V,--version}'[display version information and exit]' \
'*:package:->packages'
if [[ "$state" = packages ]]; then
_guix_list_installed_packages
compadd -a -- _guix_installed_packages
fi
}
(( $+functions[_guix_upgrade] )) || _guix_upgrade()
{
_arguments \
{-p,--profile=}'[use PROFILE instead of the users default profile]:PROFILE:_files -/' \
{-v,--verbosity=}'[use the given verbosity LEVEL]:LEVEL' \
'--do-not-upgrade=[do not upgrade any packages matching REGEXP]:REGEXP' \
{-L,--load-path=}'[prepend DIR to the package module search path]:DIR:_files -/' \
{-K,--keep-failed}'[keep build tree of failed builds]' \
{-k,--keep-going}'[keep going when some of the derivations fail]' \
{-n,--dry-run}'[do not build the derivations]' \
'--fallback[fall back to building when the substituter fails]' \
'--no-substitutes[build instead of resorting to pre-built substitutes]' \
'--substitute-urls=[fetch substitute from URLS if they are authorized]:URLS:_urls' \
'--no-grafts[do not graft packages]' \
'--no-offload[do not attempt to offload builds]' \
'--max-silent-time=[mark the build as failed after SECONDS of silence]:SECONDS' \
'--timeout=[mark the build as failed after SECONDS of activity]:SECONDS' \
'--rounds=[build N times in a row to detect non-determinism]:N' \
{-c,--cores=}'[allow the use of up to N CPU cores for the build]:N' \
{-M,--max-jobs=}'[allow at most N build jobs]:N' \
'--debug=[produce debugging output at LEVEL]:LEVEL' \
'--help-transform[list package transformation options not shown here]' \
{-V,--version}'[display version information and exit]' \
'*:regexp'
}
(( $+functions[_guix_publish] )) || _guix_publish()
{
_arguments \
{-p,--port=}'[listen on PORT]:PORT' \
'--listen=[listen on the network interface for HOST]:HOST_hosts' \
{-u,--user=}'[change privileges to USER as soon as possible]:USER_users' \
{-a,--advertise}'[advertise on the local network]' \
{-C,--compression=}'[compress archives with METHOD at LEVEL]:METHOD' \
{-c,--cache=}'[cache published items to DIRECTORY]:DIRECTORY:_files -/' \
'--cache-bypass-threshold=[serve store items below SIZE even when not cached]:SIZE' \
'--workers=[use N workers to bake items]:N' \
'--port=[listen on PORT]:PORT:' \
'--listen=[listen on the network interface for HOST]:HOST:_hosts' \
'--user=[change privileges to USER as soon as possible]:USER:_users' \
'--compression=[compress archives at LEVEL]:LEVEL' \
'--ttl=[announce narinfos can be cached for TTL seconds]:TTL' \
'--negative-ttl=[announce missing narinfos can be cached for TTL seconds]:TTL' \
'--nar-path=[use PATH as the prefix for nar URLs]:PATH' \
'--public-key=[use FILE as the public key for signatures]:FILE:_files' \
'--private-key=[use FILE as the private key for signatures]:FILE:_files' \
{-r,--repl=}'[spawn REPL server on PORT]:PORT' \
{-V,--version}'[display version information and exit]' \
'--repl=[spawn REPL server on PORT]:PORT'
}
(( $+functions[_guix_pull] )) || _guix_pull()
{
_arguments \
{-C,--channels=}'[deploy the channels defined in FILE]:FILE:_files' \
'--url=[download from the Git repository at URL]:URL:_urls' \
'--commit=[download the specified COMMIT]:COMMIT' \
'--branch=[download the tip of the specified BRANCH]:BRANCH' \
'--allow-downgrades[allow downgrades to earlier channel revisions]' \
'--disable-authentication[disable channel authentication]' \
{-N,--news}'[display news compared to the previous generation]' \
{-l,--list-generations=}'[list generations matching PATTERN]:PATTERN' \
'--roll-back[roll back to the previous generation]' \
{-d,--delete-generations=}'[delete generations matching PATTERN]:PATTERN' \
{-S,--switch-generation=}'[switch to a generation matching PATTERN]:PATTERN' \
{-p,--profile=}'[use PROFILE instead of ~/.config/guix/current]:PROFILE:_files -/' \
{-v,--verbosity=}'[use the given verbosity LEVEL]:LEVEL' \
{-s,--system=}'[attempt to build for SYSTEM (e.g. "i686-linux")]:SYSTEM' \
'--bootstrap[use the bootstrap Guile to build the new Guix]' \
{-L,--load-path=}'[prepend DIR to the package module search path]:DIR:_files -/' \
{-K,--keep-failed}'[keep build tree of failed builds]' \
{-k,--keep-going}'[keep going when some of the derivations fail]' \
{-n,--dry-run}'[do not build the derivations]' \
'--fallback[fall back to building when the substituter fails]' \
'--no-substitutes[build instead of resorting to pre-built substitutes]' \
'--substitute-urls=[fetch substitute from URLS if they are authorized]:URLS:_urls' \
'--no-grafts[do not graft packages]' \
'--no-offload[do not attempt to offload builds]' \
'--max-silent-time=[mark the build as failed after SECONDS of silence]:SECONDS' \
'--timeout=[mark the build as failed after SECONDS of activity]:SECONDS' \
'--rounds=[build N times in a row to detect non-determinism]:N' \
{-c,--cores=}'[allow the use of up to N CPU cores for the build]:N' \
{-M,--max-jobs=}'[allow at most N build jobs]:N' \
'--debug=[produce debugging output at LEVEL]:LEVEL' \
{-V,--version}'[display version information and exit]'
'--verbose[produce verbose output]' \
'--url=[download the Guix tarball from URL]:URL:_urls' \
'--bootstrap[use the bootstrap Guile to build the new Guix]'
}
(( $+functions[_guix_refresh] )) || _guix_refresh()
{
_arguments \
{-e,--expression=}'[consider the package EXPR evaluates to]:EXPR' \
{-u,--update}'[update source files in place]' \
{-s,--select=}'[select all the packages in SUBSET, one of]:SUBSET:(core non-core)' \
{-m,--manifest=}'[select all the packages from the manifest in FILE]:FILE:_files' \
{-t,--type=}'[restrict to updates from the specified updaters]:UPDATER:-.updaters' \
{-L,--list-updaters}'[list available updaters and exit]' \
{-l,--list-dependent}'[list top-level dependent packages that would need to be rebuilt as a result of upgrading PACKAGE...]' \
{-r,--recursive}'[check the PACKAGE and its inputs for upgrades]' \
'--list-transitive[list all the packages that PACKAGE depends on]' \
'--keyring=[use FILE as the keyring of upstream OpenPGP keys]:FILE:_files' \
'--key-server=[use HOST as the OpenPGP key server]:HOST_hosts' \
'--expression=[consider the package EXPR evaluates to]:EXPR' \
'--update[update source files in place]' \
'--select=[select all the packages in SUBSET]:SUBSET:(core non-core)' \
'--type=[restrict to updates from the specified updaters]:UPDATER:->updaters' \
'--list-updaters[list available updaters and exit]' \
'--list-dependent[list top-level dependent packages]' \
'--key-server=[use HOST as the OpenPGP key server]:HOST:_hosts' \
'--gpg=[use COMMAND as the GnuPG 2.x command]:COMMAND' \
'--key-download=[handle missing OpenPGP keys according to POLICY:]:POLICY:(always interactive never)' \
'--load-path=[prepend DIR to the package module search path]:DIR:_files -/' \
{-V,--version}'[display version information and exit]' \
'--key-download=[policy to handle missing OpenPGP keys]:POLICY:(always interactive never)' \
'*:package:->packages'
case "$state" in
@@ -527,12 +352,9 @@ _guix_list_installed_packages()
(( $+functions[_guix_size] )) || _guix_size()
{
_arguments \
'--substitute-urls=[fetch substitute from URLS if they are authorized]:URLS:_urls' \
{-s,--system=}'[consider packages for SYSTEM (e.g. "i686-linux")]:SYSTEM' \
'--sort=[sort according to KEY]:KEY:(closure self)' \
{-m,--map-file=}'[write to FILE a graphical map of disk usage]:FILE:_files' \
{-L,--load-path=}'[prepend DIR to the package module search path]:DIR:_files -/' \
{-V,--version}'[display version information and exit]' \
'--substitute-urls=[fetch substitute from URLS if they are authorized]:URL:_urls' \
'-system=[consider packages for SYSTEM--e.g., "i686-linux"]:SYSTEM' \
'--map-file=[write to FILE a graphical map of disk usage]:FILE:_files' \
'*:package:->packages'
if [[ "$state" = packages ]]; then
@@ -544,42 +366,28 @@ _guix_list_installed_packages()
(( $+functions[_guix_system] )) || _guix_system()
{
_arguments \
{-L,--load-path=}'[prepend DIR to the package module search path]:DIR:_files -/' \
{-K,--keep-failed}'[keep build tree of failed builds]' \
{-k,--keep-going}'[keep going when some of the derivations fail]' \
{-n,--dry-run}'[do not build the derivations]' \
'--load-path=[prepend DIR to the package module search path]:DIR:_dirs' \
'--keep-failed[keep build tree of failed builds]' \
'--keep-going[keep going when some of the derivations fail]' \
'--dry-run[do not build the derivations]' \
'--fallback[fall back to building when the substituter fails]' \
'--no-substitutes[build instead of resorting to pre-built substitutes]' \
'--substitute-urls=[fetch substitute from URLS if they are authorized]:URLS:_urls' \
'--substitute-urls=[fetch substitute from URLS if they are authorized]:URL:_urls' \
'--no-grafts[do not graft packages]' \
'--no-offload[do not attempt to offload builds]' \
'--max-silent-time=[mark the build as failed after SECONDS of silence]:SECONDS' \
'--timeout=[mark the build as failed after SECONDS of activity]:SECONDS' \
'--verbosity=[use the given verbosity LEVEL]:LEVEL' \
'--rounds=[build N times in a row to detect non-determinism]:N' \
{-c,--cores=}'[allow the use of up to N CPU cores for the build]:N' \
{-M,--max-jobs=}'[allow at most N build jobs]:N' \
'--debug=[produce debugging output at LEVEL]:LEVEL' \
{-d,--derivation}'[return the derivation of the given system]' \
{-e,--expression=}'[consider the operating-system EXPR evaluates to instead of reading FILE, when applicable]:EXPR' \
'--allow-downgrades[for reconfigure, allow downgrades to earlier channel revisions]' \
'--on-error=[apply STRATEGY when an error occurs while reading FILE]:STRATEGY:(nothing-special backtrace debug)' \
'--list-image-types[list available image types]' \
{-t,--image-type=}'[for image, produce an image of TYPE]:TYPE' \
'--image-size=[for image, produce an image of SIZE]:SIZE' \
'--no-bootloader[for init, do not install a bootloader]' \
'--volatile[for image, make the root file system volatile]' \
'--label=[for image, label disk image with LABEL]:LABEL' \
'--save-provenance[save provenance information]' \
'--share=[for vm and container, share host file system with read/write access according to SPEC]:SPEC' \
'--expose=[for vm and container, expose host file system directory as read-only according to SPEC]:SPEC' \
{-N,--network}'[for container, allow containers to access the network]' \
{-r,--root=}'[for vm, image, container and build, make FILE a symlink to the result, and register it as a GC root]:FILE:_files' \
'--full-boot[for vm, make a full boot sequence]' \
'--skip-checks[skip file system and initrd module safety checks]' \
'--target=[cross-build for TRIPLET (e.g. "armel-linux-gnu")]:TRIPLET' \
{-v,--verbosity=}'[use the given verbosity LEVEL]:LEVEL' \
'--graph-backend=[use BACKEND for extension-graphs and shepherd-graph]:BACKEND' \
{-V,--version}'[display version information and exit]' \
'--cores=[allow the use of up to N CPU cores for the build]:N' \
'--max-jobs=[allow at most N build jobs]:N' \
'--derivation[return the derivation of the given system]' \
'--on-error=[apply STRATEGY when an error occurs while reading FILE]:STRATEGY' \
'--image-size=[for "image", produce an image of SIZE]:SIZE' \
'--no-grub[for "init", do not install GRUB]' \
'--share=[for "vm", share host file system according to SPEC]:SPEC' \
'--expose=[for "vm", expose host file system according to SPEC]:SPEC' \
'--full-boot[for "vm", make a full boot sequence]' \
'1:action:->actions' \
'*:file:_files'
@@ -597,35 +405,20 @@ _guix_list_installed_packages()
"build:Build a given package"
"challenge:Challenge the substitutes for a package"
"container:Build and manipulate Linux containers"
"copy:Copy store items remotely over SSH"
"deploy:Deploy operating systems on a set of machines"
"describe:Describe the channel revisions currently used"
"download:Download the file at given URL and add it to the store"
"edit:Edit the definitions of a package"
"environment:Build an environment with a package and its dependencies"
"gc:Invoke the garbage collector"
"git:Operate on Git repositories"
"graph:Emit a DOT representation of the dependencies of a package"
"hash:Return the cryptographic hash of a file"
"import:Run an importer"
"install:Install packages"
"lint:Run a set of checkers on a package"
"offload:Set up and operate build offloading"
"pack:Create application bundles"
"package:Install, remove, or upgrade packages"
"processes:List currently running sessions"
"publish:Publish /gnu/store over HTTP."
"pull:Download and deploy the latest version of Guix"
"refresh:Update package definitions to match the latest version"
"remove:Remove packages"
"repl:Read-eval-print loop (REPL) for interactive programming"
"search:Search for packages"
"show:Show information about packages"
"size:Report the size of a package and its dependencies"
"system:Build the operating system"
"time-machine:Run commands from a different revision"
"upgrade:Upgrade packages"
"weather:Report on the availability of pre-built package binaries"
)
if (( CURRENT == 1 )); then
-127
View File
@@ -1,127 +0,0 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2021-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 that builds a directory containing Disarchive
;;; metadata for all the tarballs packages refer to.
(use-modules (srfi srfi-1) (ice-9 match)
(guix packages) (guix gexp) (guix profiles)
(guix base16)
(gnu packages))
(include "source-manifest.scm")
(define (tarball-origin? origin)
(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.
(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)
"Return a directory containing Disarchive metadata for ORIGIN, a tarball, or
an empty directory if ORIGIN could not be disassembled."
(define file-name
(let ((hash (origin-hash origin)))
(string-append (symbol->string (content-hash-algorithm hash))
"/"
(bytevector->base16-string
(content-hash-value hash)))))
(define disarchive
(specification->package "disarchive"))
(define build
(with-imported-modules '((guix build utils))
#~(begin
(use-modules (guix build utils)
(srfi srfi-34))
(define tarball
#+(upstream-origin origin))
(define file-name
(string-append #$output "/" #$file-name))
(define profile
#+(profile (content (packages->manifest (list disarchive)))))
(mkdir-p (dirname file-name))
(setenv "PATH" (string-append profile "/bin"))
(setenv "GUILE_LOAD_PATH"
(string-append profile "/share/guile/site/"
(effective-version)))
(setenv "GUILE_LOAD_COMPILED_PATH"
(string-append profile "/lib/guile/" (effective-version)
"/site-ccache"))
(guard (c ((invoke-error? c)
;; Sometimes Disarchive fails with "could not find Gzip
;; compressor". When that happens, produce an empty
;; directory instead of failing.
(report-invoke-error c)
(delete-file file-name)))
(with-output-to-file file-name
(lambda ()
;; Disarchive records the tarball name in its output. Thus,
;; strip the hash from TARBALL.
(let ((short-name (strip-store-file-name tarball)))
(symlink tarball short-name)
(invoke "disarchive" "disassemble" short-name))))))))
(computed-file (match (origin-actual-file-name origin)
((? string? str) (string-append str ".dis"))
(#f "anonymous-tarball.dis"))
build))
(define (disarchive-collection origins)
"Return a directory containing all the Disarchive metadata for ORIGINS."
(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))
;; The manifest containing Disarchive data.
(let ((origins (all-origins)))
(manifest
(list (manifest-entry
(name "disarchive-collection")
(version (number->string (length origins)))
(item (disarchive-collection origins))))))
-18
View File
@@ -1,18 +0,0 @@
[diff "scheme"]
xfuncname = "^(\\(define.*)$"
[diff "texinfo"]
xfuncname = "^@node[[:space:]]+([^,]+).*$"
[format]
forceinbodyfrom = true # help preserve commit authorship
thread = shallow
useAutoBase = true
[pull]
rebase = true
[sendemail]
to = guix-patches@gnu.org
headerCmd = etc/teams.scm cc-members-header-cmd
thread = no
+6 -32
View File
@@ -1,6 +1,6 @@
; -*- lisp -*-
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2018, 2022 Ricardo Wurmus <rekado@elephly.net>
;;; Copyright © 2018 Ricardo Wurmus <rekado@elephly.net>
;;; Copyright © 2020 Daniel Brooks <db48x@db48x.net>
;;; Copyright © 2020 Marius Bakke <marius@gnu.org>
;;;
@@ -37,13 +37,11 @@
(block guix_daemon
;; Require existing types
(typeattributeset cil_gen_require domain)
(typeattributeset cil_gen_require init_t)
(typeattributeset cil_gen_require init_var_run_t)
(typeattributeset cil_gen_require nscd_var_run_t)
(typeattributeset cil_gen_require system_dbusd_var_run_t)
(typeattributeset cil_gen_require tmp_t)
(typeattributeset cil_gen_require nscd_var_run_t)
(typeattributeset cil_gen_require var_log_t)
(typeattributeset cil_gen_require domain)
;; Declare own types
(type guix_daemon_t)
@@ -94,9 +92,6 @@
(allow init_t
guix_store_content_t
(file (open read execute)))
(allow init_t
guix_profiles_t
(dir (setattr)))
;; guix-daemon needs to know the names of users
(allow guix_daemon_t
@@ -176,11 +171,6 @@
execute_no_trans read write open entrypoint map
getattr link unlink)))
;; Remounting /gnu/store read-write.
(allow guix_daemon_t
fs_t
(filesystem (remount)))
;; TODO: unknown
(allow guix_daemon_t
root_t
@@ -228,9 +218,6 @@
(allow guix_daemon_t
tmpfs_t
(file (create open read unlink write)))
(allow guix_daemon_t ;same as above, but with tmp_t
tmp_t
(file (create open read unlink write)))
(allow guix_daemon_t
tmpfs_t
(dir (getattr add_name remove_name write)))
@@ -297,14 +284,6 @@
guix_store_content_t
(sock_file (create getattr setattr unlink write)))
;; Access to run state directories
(allow guix_daemon_t
system_dbusd_var_run_t
(dir (search)))
(allow guix_daemon_t
init_var_run_t
(dir (search)))
;; Access to configuration files and directories
(allow guix_daemon_t
guix_daemon_conf_t
@@ -322,7 +301,7 @@
open read write)))
(allow guix_daemon_t
guix_daemon_conf_t
(lnk_file (create getattr rename unlink read)))
(lnk_file (create getattr rename unlink)))
(allow guix_daemon_t net_conf_t
(file (getattr open read)))
(allow guix_daemon_t net_conf_t
@@ -349,9 +328,6 @@
(allow guix_daemon_t
cache_home_t
(dir (search)))
(allow guix_daemon_t
cache_home_t
(lnk_file (getattr read)))
;; self upgrades
(allow guix_daemon_t
@@ -364,7 +340,7 @@
;; Socket operations
(allow guix_daemon_t
guix_daemon_socket_t
(sock_file (unlink write)))
(sock_file (unlink)))
(allow guix_daemon_t
init_t
(fd (use)))
@@ -376,7 +352,7 @@
(unix_stream_socket (listen)))
(allow guix_daemon_t
guix_daemon_conf_t
(sock_file (create unlink write)))
(sock_file (create unlink)))
(allow guix_daemon_t
self
(unix_stream_socket (create
@@ -468,8 +444,6 @@
any (unconfined_u object_r guix_store_content_t (low low)))
(filecon "@prefix@/bin/guix-daemon"
file (system_u object_r guix_daemon_exec_t (low low)))
(filecon "@guix_localstatedir@/guix/profiles/per-user/[^/]+/current-guix/bin/guix-daemon"
file (system_u object_r guix_daemon_exec_t (low low)))
(filecon "@storedir@/.+-(guix-.+|profile)/bin/guix-daemon"
file (system_u object_r guix_daemon_exec_t (low low)))
(filecon "@storedir@/[a-z0-9]+-guix-daemon"
+1 -1
View File
@@ -7,4 +7,4 @@ start on runlevel [2345]
stop on runlevel [016]
exec @localstatedir@/guix/profiles/per-user/root/current-guix/bin/guix-daemon --build-users-group=guixbuild --discover=no
exec @localstatedir@/guix/profiles/per-user/root/current-guix/bin/guix-daemon --build-users-group=guixbuild
+2 -9
View File
@@ -6,19 +6,12 @@
Description=Build daemon for GNU Guix
[Service]
ExecStart=@localstatedir@/guix/profiles/per-user/root/current-guix/bin/guix-daemon \
--build-users-group=guixbuild --discover=no
ExecStart=@localstatedir@/guix/profiles/per-user/root/current-guix/bin/guix-daemon --build-users-group=guixbuild
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.
-20
View File
@@ -1,20 +0,0 @@
# This is a "service unit file" for the systemd init system to perform a
# one-shot 'guix gc' operation. It is meant to be triggered by a timer.
# Drop it in /etc/systemd/system or similar together with 'guix-gc.timer'
# to set it up.
[Unit]
Description=Discard unused Guix store items
[Service]
Type=oneshot
# Customize the 'guix gc' arguments to fit your needs.
ExecStart=@localstatedir@/guix/profiles/per-user/root/current-guix/bin/guix gc -d 1m -F 10G
PrivateDevices=yes
PrivateNetwork=yes
PrivateUsers=no
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
MemoryDenyWriteExecute=yes
SystemCallFilter=@default @file-system @basic-io @system-service
-15
View File
@@ -1,15 +0,0 @@
# This is a "timer unit file" for the systemd init system to trigger
# 'guix-gc.service' periodically. Drop it in /etc/systemd/system or similar
# together with 'guix-gc.service' to set it up.
[Unit]
Description=Discard unused Guix store items
[Timer]
OnCalendar=weekly
AccuracySec=1h
Persistent=true
RandomizedDelaySec=6000
[Install]
WantedBy=timers.target
+95 -203
View File
@@ -3,15 +3,13 @@
# Copyright © 2017 sharlatan <sharlatanus@gmail.com>
# Copyright © 2018 Ricardo Wurmus <rekado@elephly.net>
# Copyright © 2018 Efraim Flashner <efraim@flashner.co.il>
# Copyright © 20192020, 2022 Tobias Geerinckx-Rice <me@tobias.gr>
# Copyright © 2019, 2020 Tobias Geerinckx-Rice <me@tobias.gr>
# Copyright © 2020 Morgan Smith <Morgan.J.Smith@outlook.com>
# Copyright © 2020 Simon Tournier <zimon.toutoune@gmail.com>
# Copyright © 2020 Daniel Brooks <db48x@db48x.net>
# Copyright © 2021 Jakub Kądziołka <kuba@kadziolka.net>
# Copyright © 2021 Chris Marusich <cmmarusich@gmail.com>
# Copyright © 2021, 2022, 2023 Maxim Cournoyer <maxim.cournoyer@gmail.com>
# Copyright © 2022 Prafulla Giri <prafulla.giri@protonmail.com>
# Copyright © 2023 Andrew Tropin <andrew@trop.in>
# Copyright © 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com>
#
# This file is part of GNU Guix.
#
@@ -30,28 +28,12 @@
# We require Bash but for portability we'd rather not use /bin/bash or
# /usr/bin/env in the shebang, hence this hack.
# Environment variables
#
# GUIX_BINARY_FILE_NAME
#
# Can be used to override the automatic download mechanism and point
# to a local Guix binary archive filename like
# "/tmp/guix-binary-1.4.0rc2.armhf-linux.tar.xz"
#
# GUIX_ALLOW_OVERWRITE
#
# Instead of aborting to avoid overwriting a previous installations,
# allow copying over /var/guix or /gnu. This can be useful when the
# installation required the user to extract Guix packs under /gnu to
# satisfy its dependencies.
if [ "x$BASH_VERSION" = "x" ]
then
exec bash "$0" "$@"
fi
set -eo pipefail
set -e
[ "$UID" -eq 0 ] || { echo "This script must be run as root."; exit 1; }
@@ -70,7 +52,6 @@ REQUIRE=(
"chmod"
"uname"
"groupadd"
"useradd"
"tail"
"tr"
"xz"
@@ -111,20 +92,17 @@ _debug()
fi
}
die()
{
_err "${ERR}$*"
exit 1
}
# Return true if user answered yes, false otherwise. The prompt is
# yes-biased, that is, when the user simply enter newline, it is equivalent to
# answering "yes".
# Return true if user answered yes, false otherwise.
# $1: The prompt question.
prompt_yes_no() {
local -l yn
read -rp "$1 [Y/n]" yn
[[ ! $yn || $yn = y || $yn = yes ]] || return 1
while true; do
read -rp "$1" yn
case $yn in
[Yy]*) return 0;;
[Nn]*) return 1;;
*) _msg "Please answer yes or no."
esac
done
}
chk_require()
@@ -138,8 +116,10 @@ chk_require()
command -v "$c" &>/dev/null || warn+=("$c")
done
[ "${#warn}" -ne 0 ] && die "Missing commands: ${warn[*]}."
[ "${#warn}" -ne 0 ] &&
{ _err "${ERR}Missing commands: ${warn[*]}.";
return 1; }
_msg "${PAS}verification of required commands completed"
}
@@ -154,27 +134,21 @@ chk_gpg_keyring()
gpg_key_id=${GPG_SIGNING_KEYS[$user_id]}
# Without --dry-run this command will create a ~/.gnupg owned by root on
# systems where gpg has never been used, causing errors and confusion.
if gpg --dry-run --list-keys "$gpg_key_id" >/dev/null 2>&1; then
continue
fi
if prompt_yes_no "${INF}The following OpenPGP public key is \
if ! gpg --dry-run --list-keys "$gpg_key_id" >/dev/null 2>&1; then
if prompt_yes_no "${INF}The following OpenPGP public key is \
required to verify the Guix binary signature: $gpg_key_id.
Would you like me to fetch it for you?"; then
# Use a reasonable time-out here so users don't report silent
# freezes when Savannah goes out to lunch, as has happened.
if wget "https://sv.gnu.org/people/viewgpg.php?user_id=$user_id" \
--timeout=30 --no-verbose -O- | gpg --import -; then
continue
fi
fi
# If we reach this point, the key is (still) missing. Report further
# missing keys, if any, but then abort the installation.
_err "${ERR}Missing OpenPGP public key ($gpg_key_id).
Would you like me to fetch it for you? (yes/no)"; then
wget "https://sv.gnu.org/people/viewgpg.php?user_id=$user_id" \
-qO - | 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 - | \
wget \"https://sv.gnu.org/people/viewgpg.php?user_id=$user_id\" -qO - | \
sudo -i gpg --import -"
exit_flag=yes
exit_flag=yes
fi
fi
done
if [ "$exit_flag" = yes ]; then
exit 1
@@ -246,7 +220,8 @@ chk_sys_arch()
local arch=powerpc64le
;;
*)
die "Unsupported CPU type: ${arch}"
_err "${ERR}Unsupported CPU type: ${arch}"
exit 1
esac
case "$os" in
@@ -254,7 +229,8 @@ chk_sys_arch()
local os=linux
;;
*)
die "Your operation system (${os}) is not supported."
_err "${ERR}Your operation system (${os}) is not supported."
exit 1
esac
ARCH_OS="${arch}-${os}"
@@ -273,16 +249,6 @@ chk_sys_nscd()
fi
}
# Configure substitute discovery according to user's preferences.
# $1 is the installed service file to edit.
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
sed -i 's/--discover=no/--discover=yes/' "$1"
fi
}
# ------------------------------------------------------------------------------
#+MAIN
@@ -296,7 +262,7 @@ guix_get_bin_list()
_debug "--- [ ${FUNCNAME[0]} ] ---"
# Filter only version and architecture
bin_ver_ls=("$(wget "$gnu_url" --no-verbose -O- \
bin_ver_ls=("$(wget -qO- "$gnu_url" \
| sed -n -e 's/.*guix-binary-\([0-9.]*[a-z0-9]*\)\..*.tar.xz.*/\1/p' \
| sort -Vu)")
@@ -309,7 +275,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.
@@ -328,13 +295,14 @@ guix_get_bin()
_msg "${INF}Downloading Guix release archive"
wget --help | grep -q '\--show-progress' \
&& wget_args=("--no-verbose" "--show-progress")
&& wget_args=("-q" "--show-progress")
if wget "${wget_args[@]}" -P "$dl_path" \
"${url}/${bin_ver}.tar.xz" "${url}/${bin_ver}.tar.xz.sig"; then
_msg "${PAS}download completed."
else
die "could not download ${url}/${bin_ver}.tar.xz."
_err "${ERR}could not download ${url}/${bin_ver}.tar.xz."
exit 1
fi
pushd "${dl_path}" >/dev/null
@@ -342,7 +310,8 @@ guix_get_bin()
_msg "${PAS}Signature is valid."
popd >/dev/null
else
die "could not verify the signature."
_err "${ERR}could not verify the signature."
exit 1
fi
}
@@ -353,25 +322,24 @@ sys_create_store()
_debug "--- [ ${FUNCNAME[0]} ] ---"
if [[ -e /var/guix && -e /gnu ]]; then
if [ -n "$GUIX_ALLOW_OVERWRITE" ]; then
_msg "${WAR}Overwriting existing installation!"
else
die "A previous Guix installation was found. Refusing to overwrite."
fi
if [[ -e "/var/guix" || -e "/gnu" ]]; then
_err "${ERR}A previous Guix installation was found. Refusing to overwrite."
exit 1
fi
cd "$tmp_path"
tar --extract --file "$pkg" && _msg "${PAS}unpacked archive"
_msg "${INF}Installing /var/guix and /gnu..."
# Strip (skip) the leading . component, which fails on read-only /.
tar --extract --strip-components=1 --file "$pkg" -C /
mv "${tmp_path}/var/guix" /var/
mv "${tmp_path}/gnu" /
_msg "${INF}Linking the root user's profile"
mkdir -p ~root/.config/guix
mkdir -p "~root/.config/guix"
ln -sf /var/guix/profiles/per-user/root/current-guix \
~root/.config/guix/current
"~root/.config/guix/current"
GUIX_PROFILE=~root/.config/guix/current
GUIX_PROFILE="~root/.config/guix/current"
# shellcheck disable=SC1090
source "${GUIX_PROFILE}/etc/profile"
_msg "${PAS}activated root profile at ${GUIX_PROFILE}"
@@ -391,7 +359,7 @@ sys_create_build_user()
if getent group kvm > /dev/null; then
_msg "${INF}group kvm exists and build users will be added to it"
local KVMGROUP=,kvm
local KVMGROUP=,kvm
fi
for i in $(seq -w 1 10); do
@@ -427,45 +395,48 @@ sys_enable_guix_daemon()
case "$INIT_SYS" in
upstart)
{ initctl reload-configuration;
cp ~root/.config/guix/current/lib/upstart/system/guix-daemon.conf \
cp "~root/.config/guix/current/lib/upstart/system/guix-daemon.conf" \
/etc/init/ &&
configure_substitute_discovery /etc/init/guix-daemon.conf &&
start guix-daemon; } &&
_msg "${PAS}enabled Guix daemon via upstart"
;;
systemd)
{ install_unit()
{
local dest="/etc/systemd/system/$1"
rm -f "$dest"
cp ~root/.config/guix/current/lib/systemd/system/"$1" "$dest"
chmod 664 "$dest"
systemctl daemon-reload
systemctl enable "$1"
}
install_unit guix-daemon.service
configure_substitute_discovery \
/etc/systemd/system/guix-daemon.service
# Install after guix-daemon.service to avoid a harmless warning.
# systemd .mount units must be named after the target directory.
{ # systemd .mount units must be named after the target directory.
# Here we assume a hard-coded name of /gnu/store.
install_unit gnu-store.mount
# XXX Work around <https://issues.guix.gnu.org/41356> until next release.
if [ -f "~root/.config/guix/current/lib/systemd/system/gnu-store.mount" ]; then
cp "~root/.config/guix/current/lib/systemd/system/gnu-store.mount" \
/etc/systemd/system/;
chmod 664 /etc/systemd/system/gnu-store.mount;
systemctl daemon-reload &&
systemctl enable gnu-store.mount;
fi
cp "~root/.config/guix/current/lib/systemd/system/guix-daemon.service" \
/etc/systemd/system/;
chmod 664 /etc/systemd/system/guix-daemon.service;
# Work around <https://bugs.gnu.org/36074>, present in 1.0.1.
sed -i /etc/systemd/system/guix-daemon.service \
-e "s/GUIX_LOCPATH='/'GUIX_LOCPATH=/";
# Work around <https://bugs.gnu.org/35671>, present in 1.0.1.
if ! grep en_US /etc/systemd/system/guix-daemon.service >/dev/null;
then sed -i /etc/systemd/system/guix-daemon.service \
-e 's/^Environment=\(.*\)$/Environment=\1 LC_ALL=en_US.UTF-8';
fi;
systemctl daemon-reload &&
systemctl enable guix-daemon &&
systemctl start guix-daemon; } &&
_msg "${PAS}enabled Guix daemon via systemd"
;;
sysv-init)
{ mkdir -p /etc/init.d;
cp ~root/.config/guix/current/etc/init.d/guix-daemon \
cp "~root/.config/guix/current/etc/init.d/guix-daemon" \
/etc/init.d/guix-daemon;
chmod 775 /etc/init.d/guix-daemon;
configure_substitute_discovery /etc/init.d/guix-daemon
update-rc.d guix-daemon defaults &&
update-rc.d guix-daemon enable &&
service guix-daemon start; } &&
@@ -473,12 +444,10 @@ sys_enable_guix_daemon()
;;
openrc)
{ mkdir -p /etc/init.d;
cp ~root/.config/guix/current/etc/openrc/guix-daemon \
cp "~root/.config/guix/current/etc/openrc/guix-daemon" \
/etc/init.d/guix-daemon;
chmod 775 /etc/init.d/guix-daemon;
configure_substitute_discovery /etc/init.d/guix-daemon
rc-update add guix-daemon default &&
rc-service guix-daemon start; } &&
_msg "${PAS}enabled Guix daemon via OpenRC"
@@ -501,22 +470,14 @@ sys_enable_guix_daemon()
}
sys_authorize_build_farms()
{ # authorize the public key(s) of the build farm(s)
local hosts=(
ci.guix.gnu.org
bordeaux.guix.gnu.org
)
{ # authorize the public key of the build farm
if prompt_yes_no "Permit downloading pre-built package binaries from the \
project's build farms?"; then
for host in "${hosts[@]}"; do
local key=~root/.config/guix/current/share/guix/$host.pub
[ -f "$key" ] \
&& guix archive --authorize < "$key" \
&& _msg "${PAS}Authorized public key for $host"
done
else
_msg "${INF}Skipped authorizing build farm public keys"
project's build farm? (yes/no) "; then
guix archive --authorize \
< "~root/.config/guix/current/share/guix/ci.guix.gnu.org.pub" \
&& _msg "${PAS}Authorized public key for ci.guix.gnu.org"
else
_msg "${INF}Skipped authorizing build farm public keys"
fi
}
@@ -524,17 +485,7 @@ sys_create_init_profile()
{ # Define for better desktop integration
# This will not take effect until the next shell or desktop session!
[ -d "/etc/profile.d" ] || mkdir /etc/profile.d # Just in case
cat <<"EOF" > /etc/profile.d/zzz-guix.sh
# Explicitly initialize XDG base directory variables to ease compatibility
# with Guix System: see <https://issues.guix.gnu.org/56050#3>.
export XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
export XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}"
export XDG_DATA_DIRS="${XDG_DATA_DIRS:-/usr/local/share/:/usr/share/}"
export XDG_CONFIG_DIRS="${XDG_CONFIG_DIRS:-/etc/xdg}"
export XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}"
# no default for XDG_RUNTIME_DIR (depends on foreign distro for semantics)
cat <<"EOF" > /etc/profile.d/guix.sh
# _GUIX_PROFILE: `guix pull` profile
_GUIX_PROFILE="$HOME/.config/guix/current"
export PATH="$_GUIX_PROFILE/bin${PATH:+:}$PATH"
@@ -544,19 +495,16 @@ export PATH="$_GUIX_PROFILE/bin${PATH:+:}$PATH"
# searches 'Info-default-directory-list'.
export INFOPATH="$_GUIX_PROFILE/share/info:$INFOPATH"
# GUIX_PROFILE: User's default profile and home profile
# GUIX_PROFILE: User's default profile
GUIX_PROFILE="$HOME/.guix-profile"
[ -L $GUIX_PROFILE ] || return
GUIX_LOCPATH="$GUIX_PROFILE/lib/locale"
export GUIX_PROFILE GUIX_LOCPATH
[ -f "$GUIX_PROFILE/etc/profile" ] && . "$GUIX_PROFILE/etc/profile"
[ -L "$GUIX_PROFILE" ] || \
GUIX_LOCPATH="$GUIX_PROFILE/lib/locale:${GUIX_LOCPATH:+:}$GUIX_LOCPATH"
GUIX_PROFILE="$HOME/.guix-home/profile"
[ -f "$GUIX_PROFILE/etc/profile" ] && . "$GUIX_PROFILE/etc/profile"
[ -L "$GUIX_PROFILE" ] || \
GUIX_LOCPATH="$GUIX_PROFILE/lib/locale:${GUIX_LOCPATH:+:}$GUIX_LOCPATH"
export GUIX_LOCPATH
# set XDG_DATA_DIRS to include Guix installations
export XDG_DATA_DIRS="$GUIX_PROFILE/share:${XDG_DATA_DIRS:-/usr/local/share/:/usr/share/}"
EOF
}
@@ -579,53 +527,9 @@ sys_create_shell_completion()
_msg "${PAS}installed shell completion"
}
sys_customize_bashrc()
{
prompt_yes_no "Customize users Bash shell prompt for Guix?" || return 0
for bashrc in /home/*/.bashrc /root/.bashrc; do
test -f "$bashrc" || continue
grep -Fq '$GUIX_ENVIRONMENT' "$bashrc" && continue
cp "${bashrc}" "${bashrc}.bak"
echo '
# Automatically added by the Guix install script.
if [ -n "$GUIX_ENVIRONMENT" ]; then
if [[ $PS1 =~ (.*)"\\$" ]]; then
PS1="${BASH_REMATCH[1]} [env]\\\$ "
fi
fi
' >> "$bashrc"
done
_msg "${PAS}Bash shell prompt successfully customized for Guix"
}
sys_maybe_setup_selinux()
{
if ! [ -f /sys/fs/selinux/policy ]
then
return
fi
local c
for c in semodule restorecon
do
if ! command -v "$c" &>/dev/null
then
return
fi
done
prompt_yes_no "Install SELinux policy that might be required to run guix-daemon?" \
|| return 0
local var_guix=/var/guix/profiles/per-user/root/current-guix
semodule -i "${var_guix}/share/selinux/guix-daemon.cil"
restorecon -R /gnu /var/guix
}
welcome()
{
local char
cat<<"EOF"
░░░ ░░░
░░▒▒░░░░░░░░░ ░░░░░░░░░▒▒░░
@@ -651,18 +555,8 @@ This script installs GNU Guix on your system
https://www.gnu.org/software/guix/
EOF
# Don't use read -p here! It won't display when run non-interactively.
echo -n "Press return to continue..."$'\r'
if ! read -r char; then
echo
die "Can't read standard input. Hint: don't pipe scripts into a shell."
fi
if [ "$char" ]; then
echo
echo "...that ($char) was not a return!"
_msg "${WAR}Use newlines to automate installation, e.g.: yes '' | ${0##*/}"
_msg "${WAR}Any other method is unsupported and likely to break in future."
fi
echo -n "Press return to continue..."
read -r
}
main()
@@ -682,7 +576,7 @@ main()
_msg "${INF}system is ${ARCH_OS}"
umask 0022
tmp_path="$(mktemp -t -d guix.XXXXXX)"
tmp_path="$(mktemp -t -d guix.XXX)"
if [ -z "${GUIX_BINARY_FILE_NAME}" ]; then
guix_get_bin_list "${GNU_URL}"
@@ -698,12 +592,10 @@ main()
sys_create_store "${GUIX_BINARY_FILE_NAME}" "${tmp_path}"
sys_create_build_user
sys_maybe_setup_selinux
sys_enable_guix_daemon
sys_authorize_build_farms
sys_create_init_profile
sys_create_shell_completion
sys_customize_bashrc
_msg "${INF}cleaning up ${tmp_path}"
rm -r "${tmp_path}"
+1 -3
View File
@@ -11,12 +11,10 @@ After=guix-daemon.service
[Service]
ExecStart=@localstatedir@/guix/profiles/per-user/root/current-guix/bin/guix publish --user=nobody --port=8181
Environment='GUIX_LOCPATH=@localstatedir@/guix/profiles/per-user/root/guix-profile/lib/locale' LC_ALL=en_US.utf8
RemainAfterExit=yes
StandardOutput=syslog
StandardError=syslog
# Despite the name, this is rate-limited: a broken daemon will eventually fail.
Restart=always
# See <https://lists.gnu.org/archive/html/guix-devel/2016-04/msg00608.html>.
TasksMax=1024
+117
View File
@@ -0,0 +1,117 @@
:;exec emacs --batch --quick --load="$0" --funcall=main "$@"
;;; indent-code.el --- Run Emacs to indent a package definition.
;; Copyright © 2017 Alex Kost <alezost@gmail.com>
;; Copyright © 2017 Ludovic Courtès <ludo@gnu.org>
;; Copyright © 2020 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;; Copyright © 2020 Tobias Geerinckx-Rice <me@tobias.gr>
;; 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 this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; This scripts indents the given file or package definition in the specified
;; file using Emacs.
;;; Code:
;; Load Scheme indentation rules from ".dir-locals.el".
(with-temp-buffer
(scheme-mode)
(let ((default-directory (file-name-as-directory load-file-name))
(enable-local-variables :all))
(hack-dir-local-variables)
(hack-local-variables-apply)))
;; Add indentation info for Scheme constructs that are not Guix-specific.
;; This is normally provided by Geiser but this file is for people who may not
;; be running Geiser, so we just copy it here (from 'geiser-syntax.el').
(defmacro guix-syntax--scheme-indent (&rest pairs)
`(progn ,@(mapcar (lambda (p)
`(put ',(car p) 'scheme-indent-function ',(cadr p)))
pairs)))
(guix-syntax--scheme-indent
(and-let* 1)
(case-lambda 0)
(catch defun)
(class defun)
(dynamic-wind 0)
(guard 1)
(let*-values 1)
(let-values 1)
(let/ec 1)
(letrec* 1)
(match 1)
(match-lambda 0)
(match-lambda* 0)
(match-let scheme-let-indent)
(match-let* 1)
(match-letrec 1)
(opt-lambda 1)
(parameterize 1)
(parameterize* 1)
(receive 2)
(require-extension 0)
(syntax-case 2)
(test-approximate 1)
(test-assert 1)
(test-eq 1)
(test-equal 1)
(test-eqv 1)
(test-group-with-cleanup 1)
(test-runner-on-bad-count! 1)
(test-runner-on-bad-end-name! 1)
(test-runner-on-final! 1)
(test-runner-on-group-begin! 1)
(test-runner-on-group-end! 1)
(test-runner-on-test-begin! 1)
(test-runner-on-test-end! 1)
(test-with-runner 1)
(unless 1)
(when 1)
(while 1)
(with-exception-handler 1)
(with-syntax 1))
(defun main ()
(pcase command-line-args-left
(`(,file-name ,package-name)
;; Indent the definition of PACKAGE-NAME in FILE-NAME.
(find-file file-name)
(goto-char (point-min))
(if (re-search-forward (concat "^(define\\(\\|-public\\) +"
package-name)
nil t)
(let ((indent-tabs-mode nil))
(beginning-of-defun)
(indent-sexp)
(save-buffer)
(message "Done!"))
(error "Package '%s' not found in '%s'"
package-name file-name)))
(`(,file-name)
;; Indent all of FILE-NAME.
(find-file file-name)
(let ((indent-tabs-mode nil))
(indent-region (point-min) (point-max))
(save-buffer)
(message "Done!")))
(x
(error "Usage: indent-code.el FILE [PACKAGE]"))))
;;; indent-code.el ends here
+1 -1
View File
@@ -36,7 +36,7 @@ start)
-E LC_ALL=en_US.utf8 \
-p "/var/run/guix-daemon.pid" \
@localstatedir@/guix/profiles/per-user/root/current-guix/bin/guix-daemon \
--build-users-group=guixbuild --discover=no
--build-users-group=guixbuild
fi
;;
stop)
-35
View File
@@ -1,35 +0,0 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2022 Leo Famulari <leo@famulari.name>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
;;; This file returns a manifest of packages related to linux-libre.
;;; Simplistically, it selects packages whose names begin with "linux-libre".
;;; It is used to assist continuous integration of the kernel packages.
(use-modules (guix packages)
(guix profiles)
(gnu packages))
(manifest
(map package->manifest-entry
(fold-packages
(lambda (package lst)
(if (string-prefix? "linux-libre"
(package-name package))
(cons package lst)
lst))
'())))
+17 -1795
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -20,7 +20,7 @@
export GUIX_LOCPATH=@localstatedir@/guix/profiles/per-user/root/guix-profile/lib/locale
export LC_ALL=en_US.utf8
command="@localstatedir@/guix/profiles/per-user/root/current-guix/bin/guix-daemon"
command_args="--build-users-group=guixbuild --discover=no"
command_args="--build-users-group=guixbuild"
command_background="yes"
pidfile="/var/run/guix-daemon.pid"
+20 -29
View File
@@ -1,7 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2020-2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2020, 2021 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
;;; Copyright © 2023 Andreas Enge <andreas@enge.fr>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -24,10 +23,9 @@
(use-modules (gnu packages)
(guix packages)
(guix profiles)
((guix platform) #:select (targets))
((gnu ci) #:select (%cross-targets))
((gnu services xorg) #:select (%default-xorg-modules))
(guix utils)
(guix gexp)
(srfi srfi-1)
(srfi srfi-26))
@@ -52,17 +50,18 @@ TARGET."
"openssh" "emacs" "vim" "python" "guile" "guix")))
(define %base-packages/armhf
;; The guix package doesn't build natively on armhf due to Guile memory
;; issues compiling the package modules
(remove (lambda (package)
(string=? (package-name package) "guix"))
%base-packages))
;; XXX: Relax requirements for armhf-linux for lack of enough build power.
(map (lambda (package)
(if (string=? (package-name package) "emacs")
(specification->package "emacs-no-x")
package))
%base-packages))
(define %base-packages/hurd
;; XXX: For now we are less demanding of "i586-gnu".
(map specification->package
'("coreutils" "grep" "findutils" "gawk" "make"
#;"gcc-toolchain" "tar" "xz")))
"gcc-toolchain" "tar" "xz")))
(define %system-packages
;; Key packages proposed by the Guix System installer.
@@ -74,14 +73,16 @@ TARGET."
"connman" "network-manager" "network-manager-applet"
"openssh" "ntp" "tor"
"linux-libre" "grub-hybrid"
"icecat"))
;; FIXME: Add IceCat when Rust is available on i686.
;;"icecat"
))
%default-xorg-modules))
(define %packages-to-cross-build
;; Packages that must be cross-buildable from x86_64-linux.
;; FIXME: Add (@ (gnu packages gcc) gcc) when <https://bugs.gnu.org/40463>
;; is fixed.
(append (list (@ (gnu packages guile) guile-3.0/pinned))
(append (list (@ (gnu packages guile) guile-3.0/fixed))
(map specification->package
'("coreutils" "grep" "sed" "findutils" "diffutils" "patch"
"gawk" "gettext" "gzip" "xz"
@@ -110,6 +111,8 @@ TARGET."
(cond ((string=? system "i586-gnu")
%base-packages/hurd)
((string=? system "armhf-linux")
;; FIXME: Drop special case when ci.guix.gnu.org
;; has more ARMv7 build power.
%base-packages/armhf)
((string=? system "powerpc64le-linux")
;; FIXME: Drop 'bootstrap-tarballs' until
@@ -122,13 +125,8 @@ TARGET."
(define %system-manifest
(manifest
(append-map (lambda (system)
;; Some of %SYSTEM-PACKAGES are currently unsupported on some
;; systems--e.g., GNOME on non-x86_64, due to Rust. Filter
;; them out.
(filter-map (lambda (package)
(and (supported-package? package system)
(package->manifest-entry* package system)))
%system-packages))
(map (cut package->manifest-entry* <> system)
%system-packages))
'("x86_64-linux" "i686-linux")))) ;Guix System
(define %cross-manifest
@@ -139,16 +137,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
@@ -19,9 +19,7 @@
(t "(string-append \\"https://\\" version \\".tar.gz\\")"))}$0)
${1:$(cond ((equal yas-text "git-fetch")
"(file-name (git-file-name name version))")
((equal yas-text "hg-fetch")
"(file-name (hg-file-name name version))")
((member yas-text '("svn-fetch" "cvs-fetch" "bzr-fetch"))
((member yas-text '("svn-fetch" "hg-fetch" "cvs-fetch" "bzr-fetch"))
"(file-name (string-append name \\"-\\" version \\"-checkout\\"))")
(t ""))}
(sha256
@@ -11,7 +11,6 @@
"ant-build-system"
"asdf-build-system"
"cargo-build-system"
"chicken-build-system"
"clojure-build-system"
"cmake-build-system"
"copy-build-system"
@@ -28,7 +27,6 @@
"linux-module-build-system"
"maven-build-system"
"meson-build-system"
"minetest-build-system"
"minify-build-system"
"node-build-system"
"ocaml-build-system"
@@ -37,8 +35,6 @@
"qt-build-system"
"r-build-system"
"rakudo-build-system"
"rebar-build-system"
"renpy-build-system"
"ruby-build-system"
"scons-build-system"
"texlive-build-system"
-89
View File
@@ -1,89 +0,0 @@
-*- mode: lisp-data -*-
scheme-mode
(package...
"(define-public " (s name)
n> "(package"
n > "(name \"" (s name) "\")"
n > "(version \"" p "\")"
n > "(source origin...)"
n > "(build-system " (p "gnu") "-build-system)"
n > "(home-page \"" p "\")"
n > "(synopsis \"" p "\")"
n > "(description \"" p "\")"
n > "(license license:" (p "unknown") ")))" n)
(origin...
"(origin"
n> "(method " (p "url-fetch" method) ")"
n> "(uri " (cl-case (and method (intern method))
('git-fetch "git-reference...")
('svn-fetch "svn-reference...")
('hg-fetch "hg-reference...")
('cvs-fetch "cvs-reference...")
('bzr-fetch "bzr-reference...")
(t "\"https://...\""))
")"
n>
(cl-case (and method (intern method))
('git-fetch
(insert "(file-name (git-file-name name version))")
(newline)
(indent-according-to-mode))
('hg-fetch
(insert "(file-name (hg-file-name name version))")
(newline)
(indent-according-to-mode))
('svn-fetch
(insert "(file-name (string-append name \"-\" version \"-checkout\"))")
(newline)
(indent-according-to-mode))
('cvs-fetch
(insert "(file-name (string-append name \"-\" version \"-checkout\"))")
(newline)
(indent-according-to-mode))
('bzr-fetch
(insert "(file-name (string-append name \"-\" version \"-checkout\"))")
(newline)
(indent-according-to-mode))
(t ""))
> "(sha256"
n > "(base32 \""
;; hash of an empty directory
(p "0sjjj9z1dhilhpc8pq4154czrb79z9cm044jvn75kxcjv6v5l2m5") "\")))")
(git-reference...
"(git-reference"
n> "(url \"" p "\")"
n> "(commit " (p "commit") "))")
(svn-reference...
"(svn-reference"
n> "(url \"" p "\")"
n> "(revision " (p "revision") "))")
(cvs-reference...
"(cvs-reference"
n> "(root-directory \"" p "\")"
n> "(module \"" p "\")"
n> "(revision \"" p "\"))")
(hg-reference...
"(hg-reference"
n> "(url \"" p "\")"
n> "(changeset " (p "changeset") "))")
(bzr-reference...
"(bzr-reference"
n> "(url \"" p "\")"
n> "(revision " (p "revision") "))")
(:phases\ "#:phases (modify-phases %standard-phases"
n> p ")")
(add-before\ "(add-before '" p " '" p
n > p ")")
(add-after\ "(add-after '" p " '" p
n > p ")")
(replace\ "(replace '" p " " p")")
-158
View File
@@ -1,158 +0,0 @@
-*- mode: lisp-data -*-
text-mode :when (bound-and-true-p git-commit-mode)
(add\ "gnu: Add "
(p (with-temp-buffer
(magit-git-wash #'magit-diff-wash-diffs
"diff" "--staged")
(goto-char (point-min))
(when (re-search-forward "\\+(define-public \\(\\S-+\\)"
nil 'noerror)
(match-string-no-properties 1)))
var)
"." n n
"* " (p (or (car (magit-staged-files)) ""))
" (" (s var ) "): New variable.")
(remove\ "gnu: Remove "
(p (with-temp-buffer
(magit-git-wash #'magit-diff-wash-diffs
"diff" "--staged")
(goto-char (point-min))
(when (re-search-forward "\\-(define-public \\(\\S-+\\)"
nil 'noerror)
(match-string-no-properties 1)))
var)
"." n n
"* " (p (or (car (magit-staged-files)) ""))
" (" (s var) "): Delete variable.")
(rename\ "gnu: "
(p (with-temp-buffer
(magit-git-wash #'magit-diff-wash-diffs
"diff" "--staged")
(beginning-of-buffer)
(when (search-forward "-(define-public " nil 'noerror)
(thing-at-point 'sexp 'no-properties)))
prev-var)
": Rename package to "
(p (with-temp-buffer
(magit-git-wash #'magit-diff-wash-diffs
"diff" "--staged")
(beginning-of-buffer)
(when (search-forward "+(define-public " nil 'noerror)
(thing-at-point 'sexp 'no-properties)))
new-var)
"." n n
"* " (p (or (car (magit-staged-files)) "")) " (" (s prev-var) "): "
"Define in terms of" n
"'deprecated-package'." n
"(" (s new-var) "): New variable, formerly known as \""
(s prev-var) "\".")
(update\ "gnu: "
(p (with-temp-buffer
(magit-git-wash #'magit-diff-wash-diffs
"diff" "--staged")
(goto-char (point-min))
(when (re-search-forward "^[ ]*(define-public \\(\\S-+\\)"
nil 'noerror)
(match-string-no-properties 1)))
var)
": Update to "
(p (with-temp-buffer
(magit-git-wash #'magit-diff-wash-diffs
"diff" "--staged")
(goto-char (point-min))
(search-forward "name" nil 'noerror)
(search-forward "+" nil 'noerror) ; first change
(when (and (search-forward "version " nil 'noerror)
(looking-at-p "\""))
(let ((end (save-excursion (search-forward "\")"
nil 'noerror))))
(when end
(forward-char)
(buffer-substring-no-properties (point) (- end 2))))))
version)
"." n n
"* " (p (or (car (magit-staged-files)) "")) " (" (s var) "): "
"Update to " (s version) "." n
(mapconcat (lambda (file) (concat "* " file))
(cdr (magit-staged-files))
"\n"))
(addcl\ "gnu: Add cl-"
(p (replace-regexp-in-string
"^cl-" "" (with-temp-buffer
(magit-git-wash #'magit-diff-wash-diffs
"diff" "--staged")
(beginning-of-buffer)
(when (search-forward "+(define-public " nil 'noerror)
(replace-regexp-in-string
"^sbcl-" ""
(thing-at-point 'sexp 'no-properties)))))
var)
"." n n
"* " (p (or (car (magit-staged-files)) ""))
" (cl-" (s var)
", ecl-" (s var)
", sbcl-" (s var) "): New variables.")
(https\ "gnu: "
(p (with-temp-buffer
(magit-git-wash #'magit-diff-wash-diffs
"diff" "--staged")
(goto-char (point-min))
(when (re-search-forward "^[ ]*(define-public \\(\\S-+\\)"
nil 'noerror)
(match-string-no-properties 1)))
var)
": Use HTTPS home page." n n
"* " (p (or (car (magit-staged-files)) ""))
" (" (s var) ")[home-page]: Use HTTPS."
n
(mapconcat (lambda (file) (concat "* " file))
(cdr (magit-staged-files))
"\n"))
(move\ "gnu: "
(p (with-temp-buffer
(magit-git-wash #'magit-diff-wash-diffs
"diff" "--staged")
(goto-char (point-min))
(when (re-search-forward "\\-(define-public \\(\\S-+\\)"
nil 'noerror)
(match-string-no-properties 1)))
var)
": Move to ("
(p (with-temp-buffer
(magit-git-wash #'magit-diff-wash-diffs
"diff" "--staged")
(goto-char (point-min))
(when (and
(re-search-forward "\\+(define-public \\(\\S-+\\)"
nil 'noerror)
(re-search-backward "modified[ ]*\\(\\S-+\\)"
nil 'noerror))
(string-replace
"\.scm" ""
(string-replace "/" " "
(match-string-no-properties 1)))))
new-module)
")." n
n
"* " (p (with-temp-buffer
(magit-git-wash #'magit-diff-wash-diffs
"diff" "--staged")
(goto-char (point-min))
(when (and
(re-search-forward "\\-(define-public \\(\\S-+\\)"
nil 'noerror)
(re-search-backward "modified[ ]*\\(\\S-+\\)"
nil 'noerror))
(match-string-no-properties 1)))
source)
" (" (s var) "): Move from here…" n
"* " (concat (string-replace " " "/" new-module) ".scm")
" (" (s var) "): …to here.")
@@ -8,7 +8,7 @@ gnu: ${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)
(when (re-search-forward "(define-public \\(\\S-+\\)" nil 'noerror)
(match-string-no-properties 1)))`}: Update to ${2:`(with-temp-buffer
(magit-git-wash #'magit-diff-wash-diffs
"diff" "--staged")
@@ -1,9 +0,0 @@
# -*- mode: snippet -*-
# name: guix-vc-commit-message-add-package
# key: add
# --
gnu: Add ${1:`(when (string-match "\\+(define-public \\(\\S-+\\)" vc-patch-string)
(match-string-no-properties 1 vc-patch-string))`}.
* `(car (log-edit-files))` ($1): New variable.
`(mapconcat (lambda (file) (concat "* " file)) (cdr (log-edit-files)) "\n")`
@@ -1,9 +0,0 @@
# -*- mode: snippet -*-
# name: guix-vc-commit-message-remove-package
# key: remove
# --
gnu: Remove ${1:`(when (string-match "\\-(define-public \\(\\S-+\\)" vc-patch-string)
(match-string-no-properties 1 vc-patch-string))`}.
* `(car (log-edit-files))` ($1): Delete variable.
`(mapconcat (lambda (file) (concat "* " file)) (cdr (log-edit-files)) "\n")`
@@ -1,14 +0,0 @@
# -*- mode: snippet -*-
# name: guix-vc-commit-message-rename-package
# key: rename
# --
gnu: ${1:`(when (string-match "\\-(define-public \\(\\S-+\\)" vc-patch-string)
(match-string-no-properties 1 vc-patch-string))
`}: Rename package to ${2:`
(when (string-match "\\+(define-public \\(\\S-+\\)" vc-patch-string)
(match-string-no-properties 1 vc-patch-string))`}.
* `(car (log-edit-files))` ($1): Define in terms of
'deprecated-package'.
($2): New variable, formerly known as "$1".
`(mapconcat (lambda (file) (concat "* " file)) (cdr (log-edit-files)) "\n")`
@@ -1,12 +0,0 @@
# -*- mode: snippet -*-
# name: guix-vc-commit-message-update-package
# key: update
# --
gnu: ${1:`(when (string-match "^[ ]*(define-public \\(\\S-+\\)" vc-patch-string)
(match-string-no-properties 1 vc-patch-string))`}: Update to ${2:`
(when (string-match "^\\+[ ]*(version \"\\(.*\\)\"" vc-patch-string)
(match-string-no-properties 1 vc-patch-string))`}.
* `(car (log-edit-files))` ($1): Update to $2.$0
`(mapconcat (lambda (file) (concat "* " file)) (cdr (log-edit-files)) "\n")`
@@ -1,9 +0,0 @@
# -*- mode: snippet -*-
# name: guix-vc-commit-message-use-https-home-page
# key: https
# --
gnu: ${1:`(when (string-match "^[ ]*(define-public \\(\\S-+\\)" vc-patch-string)
(match-string-no-properties 1 vc-patch-string))`}: Use HTTPS home page URI.
* `(car (log-edit-files))` ($1)[home-page]: Use HTTPS URI.
`(mapconcat (lambda (file) (concat "* " file)) (cdr (log-edit-files)) "\n")`
@@ -1,9 +0,0 @@
# -*- mode: snippet -*-
# name: guix-news-entry
# key: entry...
# --
(entry (commit "$1")
(title
(en "$2"))
(body
(en "$3")))
@@ -1,13 +0,0 @@
# -*- mode: snippet -*-
# name: guix-commit-message-remove-package
# key: remove
# condition: git-commit-mode
# --
gnu: Remove ${1:`(with-temp-buffer
(magit-git-wash #'magit-diff-wash-diffs
"diff" "--staged")
(goto-char (point-min))
(when (re-search-forward "\\-(define-public \\(\\S-+\\)" nil 'noerror)
(match-string-no-properties 1)))`}.
* `(car (magit-staged-files))` ($1): Delete variable.
-66
View File
@@ -1,66 +0,0 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2021 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 origins of all the packages. The
;;; main purpose is to allow continuous integration services to keep upstream
;;; source code around. It can also be passed to 'guix weather -m'.
(use-modules (srfi srfi-1) (srfi srfi-26)
(ice-9 match) (ice-9 vlist)
(guix packages) (guix profiles)
(gnu packages))
(define (all-packages)
"Return the list of all the packages, public or private, omitting only
superseded packages."
(fold-packages (lambda (package lst)
(match (package-replacement package)
(#f (cons package lst))
(replacement
(append (list replacement package) lst))))
'()
#:select? (negate package-superseded)))
(define (upstream-origin source)
"Return SOURCE without any patches or snippet."
(origin (inherit source)
(snippet #f) (patches '())))
(define (all-origins)
"Return the list of origins referred to by all the packages."
(let loop ((packages (all-packages))
(origins '())
(visited vlist-null))
(match packages
((head . tail)
(let ((new (remove (cut vhash-assq <> visited)
(package-direct-sources head))))
(loop tail (append new origins)
(fold (cut vhash-consq <> #t <>)
visited new))))
(()
origins))))
;; Return a manifest containing all the origins.
(manifest (map (lambda (origin)
(manifest-entry
(name (or (origin-actual-file-name origin)
"origin"))
(version "0")
(item (upstream-origin origin))))
(all-origins)))
@@ -1,6 +0,0 @@
(public-key
(ecc
(curve Ed25519)
(q #7D602902D3A2DBB83F8A0FB98602A754C5493B0B778C8D1DD4E0F41DE14DE34F#)
)
)
+11 -16
View File
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2016, 2018-2020, 2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2016, 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -18,8 +18,7 @@
(use-modules (gnu tests)
(gnu packages package-management)
(guix monads)
(guix store)
((gnu ci) #:select (channel-source->package))
((guix git-download) #:select (git-predicate))
((guix utils) #:select (current-source-directory))
(git)
@@ -49,19 +48,15 @@ instance."
;; of tests to run in the usual way:
;;
;; make check-system TESTS=installed-os
(let ((guix (channel-source->package source #:commit commit)))
(map (lambda (test)
(system-test
(inherit test)
(value (mparameterize %store-monad ((current-guix-package guix))
(system-test-value test)))))
(match (getenv "TESTS")
(#f
(all-system-tests))
((= string-tokenize (tests ...))
(filter (lambda (test)
(member (system-test-name test) tests))
(all-system-tests)))))))
(parameterize ((current-guix-package
(channel-source->package source #:commit commit)))
(match (getenv "TESTS")
(#f
(all-system-tests))
((= string-tokenize (tests ...))
(filter (lambda (test)
(member (system-test-name test) tests))
(all-system-tests))))))
(define (system-test->manifest-entry test)
"Return a manifest entry for TEST, a system test."
-840
View File
@@ -1,840 +0,0 @@
#!@GUILE@ \
--no-auto-compile -s
!#
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2022, 2023 Ricardo Wurmus <rekado@elephly.net>
;;; Copyright © 2022 Mathieu Othacehe <othacehe@gnu.org>
;;; Copyright © 2022, 2023 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;; Copyright © 2022 Simon Tournier <zimon.toutoune@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; This code defines development teams and team members, as well as their
;; scope.
;;; Code:
(use-modules (srfi srfi-1)
(srfi srfi-9)
(srfi srfi-26)
(ice-9 format)
(ice-9 regex)
(ice-9 match)
(ice-9 rdelim)
(guix ui)
(git))
(define-record-type <regexp*>
(%make-regexp* pat flag rx)
regexp*?
(pat regexp*-pattern)
(flag regexp*-flag)
(rx regexp*-rx))
;;; Work around regexp implementation.
;;; This record allows to track the regexp pattern and then display it.
(define* (make-regexp* pat #:optional (flag regexp/extended))
"Alternative to `make-regexp' producing annotated <regexp*> objects."
(%make-regexp* pat flag (make-regexp pat flag)))
(define (regexp*-exec rx* str)
"Execute the RX* regexp, a <regexp*> object."
(regexp-exec (regexp*-rx rx*) str))
(define-record-type <team>
(make-team id name description members scope)
team?
(id team-id)
(name team-name)
(description team-description)
(members team-members set-team-members!)
(scope team-scope))
(define-record-type <person>
(make-person name email)
person?
(name person-name)
(email person-email))
(define* (person name #:optional email)
(make-person name email))
(define* (team id #:key name description (members '())
(scope '()))
(make-team id
(or name (symbol->string id))
description
members
scope))
(define %teams
(make-hash-table))
(define-syntax define-team
(lambda (x)
(syntax-case x ()
((_ id value)
#`(begin
(define-public id value)
(hash-set! %teams 'id id))))))
(define-syntax-rule (define-member person teams ...)
(let ((p person))
(for-each (lambda (team-id)
(let ((team
(hash-ref %teams team-id
(lambda ()
(error (format #false
"Unknown team ~a for ~a~%"
team-id p))))))
(set-team-members!
team (cons p (team-members team)))))
(quote (teams ...)))))
(define-team python
(team 'python
#:name "Python team"
#:description
"Python, Python packages, the \"pypi\" importer, and the python-build-system."
#:scope
(list "gnu/packages/django.scm"
"gnu/packages/jupyter.scm"
;; Match haskell.scm and haskell-*.scm.
(make-regexp* "^gnu/packages/python(-.+|)\\.scm$")
"gnu/packages/sphinx.scm"
"gnu/packages/tryton.scm"
"guix/build/pyproject-build-system.scm"
"guix/build-system/pyproject.scm"
"guix/build/python-build-system.scm"
"guix/build-system/python.scm"
"guix/import/pypi.scm"
"guix/scripts/import/pypi.scm"
"tests/pypi.scm")))
(define-team haskell
(team 'haskell
#:name "Haskell team"
#:description
"GHC, Hugs, Haskell packages, the \"hackage\" and \"stackage\" importers, and
the haskell-build-system."
#:scope
(list "gnu/packages/dhall.scm"
;; Match haskell.scm and haskell-*.scm.
(make-regexp* "^gnu/packages/haskell(-.+|)\\.scm$")
"gnu/packages/purescript.scm"
"guix/build/haskell-build-system.scm"
"guix/build-system/haskell.scm"
"guix/import/cabal.scm"
"guix/import/hackage.scm"
"guix/import/stackage.scm"
"guix/scripts/import/hackage.scm")))
(define-team qt
(team 'qt
#:name "Qt team"
#:description
"The Qt toolkit/library and the qt-build-system,
as well as some packages using Qt."
#:scope (list "gnu/packages/qt.scm"
"guix/build-system/qt.scm"
"guix/build/qt-build-system.scm"
"guix/build/qt-utils.scm")))
(define-team r
(team 'r
#:name "R team"
#:description
"The R language, CRAN and Bioconductor repositories, the \"cran\" importer,
and the r-build-system."
#:scope (list "gnu/packages/bioconductor.scm"
"gnu/packages/cran.scm"
"guix/build/r-build-system.scm"
"guix/build-system/r.scm"
"guix/import/cran.scm"
"guix/scripts/import/cran.scm"
"tests/cran.scm")))
(define-team telephony
(team 'telephony
#:name "Telephony team"
#:description
"Telephony packages and services such as Jami, Linphone, etc."
#:scope (list "gnu/build/jami-service.scm"
"gnu/packages/jami.scm"
"gnu/packages/linphone.scm"
"gnu/packages/telephony.scm"
"gnu/services/telephony.scm"
"gnu/tests/data/jami-dummy-account.dat"
"gnu/tests/telephony.scm"
"tests/services/telephony.scm")))
(define-team tex
(team 'tex
#:name "TeX team"
#:description
"TeX, LaTeX, XeLaTeX, LuaTeX, TeXLive, the texlive-build-system, and
the \"texlive\" importer."
#:scope (list "gnu/packages/tex.scm"
"gnu/packages/texlive.scm"
"guix/build/texlive-build-system.scm"
"guix/build-system/texlive.scm"
"guix/import/texlive.scm"
"guix/scripts/import/texlive.scm"
"tests/texlive.scm")))
(define-team julia
(team 'julia
#:name "Julia team"
#:description
"The Julia language, Julia packages, and the julia-build-system."
#:scope (list (make-regexp* "^gnu/packages/julia(-.+|)\\.scm$")
"guix/build/julia-build-system.scm"
"guix/build-system/julia.scm")))
(define-team ocaml
(team 'ocaml
#:name "OCaml and Dune team"
#:description
"The OCaml language, the Dune build system, OCaml packages, the \"opam\"
importer, and the ocaml-build-system."
#:scope
(list "gnu/packages/ocaml.scm"
"gnu/packages/coq.scm"
"guix/build/ocaml-build-system.scm"
"guix/build/dune-build-system.scm"
"guix/build-system/ocaml.scm"
"guix/build-system/dune.scm"
"guix/import/opam.scm"
"guix/scripts/import/opam.scm"
"tests/opam.scm")))
(define-team java
(team 'java
#:name "Java and Maven team"
#:description
"The JDK and JRE, the Maven build system, Java packages, the ant-build-system,
and the maven-build-system."
#:scope
(list ;; Match java.scm and java-*.scm.
(make-regexp* "^gnu/packages/java(-.+|)\\.scm$")
;; Match maven.scm and maven-*.scm
(make-regexp* "^gnu/packages/maven(-.+|)\\.scm$")
"guix/build/ant-build-system.scm"
"guix/build/java-utils.scm"
"guix/build/maven-build-system.scm"
;; The maven directory
(make-regexp* "^guix/build/maven/")
"guix/build-system/ant.scm"
"guix/build-system/maven.scm")))
(define-team science
(team 'science
#:name "Science team"
#:description "The main science disciplines and fields related
packages (e.g. Astronomy, Chemistry, Math, Physics etc.)"
#:scope (list "gnu/packages/algebra.scm"
"gnu/packages/astronomy.scm"
"gnu/packages/geo.scm"
"gnu/packages/chemistry.scm"
"gnu/packages/maths.scm")))
(define-team emacs
(team 'emacs
#:name "Emacs team"
#:description "The extensible, customizable text editor and its
ecosystem."
#:scope (list "gnu/packages/aux-files/emacs/guix-emacs.el"
(make-regexp* "^gnu/packages/emacs(-.+|)\\.scm$")
"gnu/packages/tree-sitter.scm"
"guix/build/emacs-build-system.scm"
"guix/build/emacs-utils.scm"
"guix/build-system/emacs.scm"
"guix/import/elpa.scm"
"guix/scripts/import/elpa.scm"
"tests/elpa.scm")))
(define-team lisp
(team 'lisp
#:name "Lisp team"
#:description
"Common Lisp and similar languages, Common Lisp packages and the
asdf-build-system."
#:scope (list (make-regexp* "^gnu/packages/lisp(-.+|)\\.scm$")
"guix/build/asdf-build-system.scm"
"guix/build/lisp-utils.scm"
"guix/build-system/asdf.scm")))
(define-team ruby
(team 'ruby
#:name "Ruby team"
#:scope (list "gnu/packages/ruby.scm"
"guix/build/ruby-build-system.scm"
"guix/build-system/ruby.scm"
"guix/import/gem.scm"
"guix/scripts/import/gem.scm"
"tests/gem.scm")))
(define-team go
(team 'go
#:name "Go team"
#:scope (list "gnu/packages/golang.scm"
"guix/build/go-build-system.scm"
"guix/build-system/go.scm"
"guix/import/go.scm"
"guix/scripts/import/go.scm"
"tests/go.scm")))
(define-team bootstrap
(team 'bootstrap
#:name "Bootstrap"
#:scope (list "gnu/packages/mes.scm")))
(define-team embedded
(team 'embedded
#:name "Embedded"
#:scope (list "gnu/packages/bootloaders.scm"
"gnu/packages/firmware.scm")))
(define-team rust
(team 'rust
#:name "Rust"
#:scope (list (make-regexp* "^gnu/packages/(crates|rust)(-.+|)\\.scm$")
"gnu/packages/sequoia.scm"
"guix/build/cargo-build-system.scm"
"guix/build/cargo-utils.scm"
"guix/build-system/cargo.scm"
"guix/import/crate.scm"
"guix/scripts/import/crate.scm"
"tests/crate.scm")))
(define-team kernel
(team 'kernel
#:name "Linux-libre kernel team"
#:scope (list "gnu/build/linux-modules.scm"
"gnu/packages/linux.scm"
"gnu/tests/linux-modules.scm"
"guix/build/linux-module-build-system.scm"
"guix/build-system/linux-module.scm")))
(define-team core
(team 'core
#:name "Core / Tools / Internals"
#:scope
(list "guix/avahi.scm"
"guix/base16.scm"
"guix/base32.scm"
"guix/base64.scm"
"guix/bzr-download.scm"
"guix/cache.scm"
"guix/channels.scm"
"guix/ci.scm"
"guix/colors.scm"
"guix/combinators.scm"
"guix/config.scm"
"guix/cpio.scm"
"guix/cpu.scm"
"guix/cve.scm"
"guix/cvs-download.scm"
"guix/deprecation.scm"
"guix/derivations.scm"
"guix/describe.scm"
"guix/diagnostics.scm"
"guix/discovery.scm"
"guix/docker.scm"
"guix/download.scm"
"guix/elf.scm"
"guix/ftp-client.scm"
"guix/gexp.scm"
"guix/git-authenticate.scm"
"guix/git-download.scm"
"guix/git.scm"
"guix/glob.scm"
"guix/gnu-maintenance.scm"
"guix/gnupg.scm"
"guix/grafts.scm"
"guix/graph.scm"
"guix/hash.scm"
"guix/hg-download.scm"
"guix/http-client.scm"
"guix/i18n.scm"
"guix/inferior.scm"
"guix/ipfs.scm"
"guix/least-authority.scm"
"guix/licenses.scm"
"guix/lint.scm"
"guix/man-db.scm"
"guix/memoization.scm"
"guix/modules.scm"
"guix/monad-repl.scm"
"guix/monads.scm"
"guix/narinfo.scm"
"guix/nar.scm"
"guix/openpgp.scm"
"guix/packages.scm"
"guix/pki.scm"
"guix/platform.scm"
"guix/profiles.scm"
"guix/profiling.scm"
"guix/progress.scm"
"guix/quirks.scm"
"guix/read-print.scm"
"guix/records.scm"
"guix/remote.scm"
"guix/repl.scm"
"guix/search-paths.scm"
"guix/self.scm"
"guix/serialization.scm"
"guix/sets.scm"
"guix/ssh.scm"
"guix/status.scm"
"guix/store.scm"
"guix/substitutes.scm"
"guix/svn-download.scm"
"guix/swh.scm"
"guix/tests.scm"
"guix/transformations.scm"
"guix/ui.scm"
"guix/upstream.scm"
"guix/utils.scm"
"guix/workers.scm"
(make-regexp* "^guix/platforms/")
(make-regexp* "^guix/scripts/")
(make-regexp* "^guix/store/"))))
(define-team games
(team 'games
#:name "Games and Toys"
#:description "Packaging programs for amusement."
#:scope (list "gnu/packages/games.scm"
"gnu/packages/game-development.scm"
"gnu/packages/minetest.scm"
"gnu/packages/esolangs.scm" ; granted, rather niche
"gnu/packages/motti.scm"
"guix/build/minetest-build-system.scm")))
(define-team localization
(team 'localization
#:name "Localization (l10n) team"
#:description
"Localization of your system to specific languages."
#:scope (list "gnu/packages/anthy.scm"
"gnu/packages/fcitx5.scm"
"gnu/packages/fcitx.scm"
"gnu/packages/fonts.scm"
"gnu/packages/ibus.scm")))
(define-team translations
(team 'translations
#:name "Translations"
#:scope (list "etc/news.scm"
(make-regexp* "^po/"))))
(define-team installer
(team 'installer
#:name "Installer script and system installer"
#:scope (list (make-regexp* "^gnu/installer(\\.scm$|/)"))))
(define-team home
(team 'home
#:name "Team for \"Guix Home\""
#:scope (list (make-regexp* "^(gnu|guix/scripts)/home(\\.scm$|/)")
"tests/guix-home.sh"
"tests/home-import.scm"
"tests/home-services.scm")))
(define-team mentors
(team 'mentors
#:name "Mentors"
#:description
"A group of mentors who chaperone contributions by newcomers."))
(define-team mozilla
(team 'mozilla
#:name "Mozilla"
#:description
"Taking care about Icecat and Icedove, built from Mozilla Firefox
and Thunderbird."
#:scope (list "gnu/packages/gnuzilla.scm")))
(define-team racket
(team 'racket
#:name "Racket team"
#:description
"The Racket language and Racket-based languages, Racket packages,
Racket's variant of Chez Scheme, and development of a Racket build system and
importer."
#:scope (list "gnu/packages/chez.scm"
"gnu/packages/racket.scm")))
(define-team reproduciblebuilds
(team 'reproduciblebuilds
#:name "Reproducible Builds team"
#:description
"Reproducible Builds tooling and issues that affect any guix packages."
#:scope (list "gnu/packages/diffoscope.scm")))
(define-team gnome
(team 'gnome
#:name "Gnome team"
#:description
"The Gnome desktop environment, along with core technologies such as
GLib/GIO, GTK, GStreamer and Webkit."
#:scope (list "gnu/packages/glib.scm"
"gnu/packages/gstreamer.scm"
"gnu/packages/gtk.scm"
"gnu/packages/gnome.scm"
"gnu/packages/gnome-xyz.scm"
"gnu/packages/webkit.scm"
"guix/build/glib-or-gtk-build-system.scm"
"guix/build/meson-build-system.scm")))
(define-team xfce
(team 'xfce
#:name "Xfce team"
#:description "Xfce desktop environment."
#:scope (list "gnu/packages/xfce.scm")))
(define-team lxqt
(team 'lxqt
#:name "LXQt team"
#:description "LXQt desktop environment."
#:scope (list "gnu/packages/lxqt.scm"
"gnu/packages/qt.scm")))
(define-member (person "Eric Bavier"
"bavier@posteo.net")
science)
(define-member (person "Lars-Dominik Braun"
"lars@6xq.net")
python haskell)
(define-member (person "Jonathan Brielmaier"
"jonathan.brielmaier@web.de")
mozilla)
(define-member (person "Ludovic Courtès"
"ludo@gnu.org")
core home bootstrap installer mentors)
(define-member (person "Andreas Enge"
"andreas@enge.fr")
lxqt science tex)
(define-member (person "Tobias Geerinckx-Rice"
"me@tobias.gr")
core kernel mentors)
(define-member (person "Björn Höfling"
"bjoern.hoefling@bjoernhoefling.de")
java)
(define-member (person "Leo Famulari"
"leo@famulari.name")
kernel)
(define-member (person "Efraim Flashner"
"efraim@flashner.co.il")
embedded bootstrap julia rust science)
(define-member (person "jgart"
"jgart@dismail.de")
python lisp mentors)
(define-member (person "Guillaume Le Vaillant"
"glv@posteo.net")
lisp)
(define-member (person "Julien Lepiller"
"julien@lepiller.eu")
java ocaml translations)
(define-member (person "Philip McGrath"
"philip@philipmcgrath.com")
racket)
(define-member (person "Mathieu Othacehe"
"othacehe@gnu.org")
core installer mentors)
(define-member (person "Florian Pelz"
"pelzflorian@pelzflorian.de")
translations)
(define-member (person "Liliana Marie Prikler"
"liliana.prikler@gmail.com")
emacs games gnome)
(define-member (person "Ricardo Wurmus"
"rekado@elephly.net")
r core mentors tex)
(define-member (person "Christopher Baines"
"guix@cbaines.net")
core mentors ruby)
(define-member (person "Andrew Tropin"
"andrew@trop.in")
home emacs)
(define-member (person "pukkamustard"
"pukkamustard@posteo.net")
ocaml)
(define-member (person "Josselin Poiret"
"dev@jpoiret.xyz")
core installer)
(define-member (person "("
"paren@disroot.org")
home mentors)
(define-member (person "Simon Tournier"
"zimon.toutoune@gmail.com")
julia core mentors)
(define-member (person "Raghav Gururajan"
"rg@raghavgururajan.name")
gnome mentors)
(define-member (person "宋文武"
"iyzsong@envs.net")
games localization lxqt xfce)
(define-member (person "Vagrant Cascadian"
"vagrant@debian.org")
embedded)
(define-member (person "Vagrant Cascadian"
"vagrant@reproducible-builds.org")
reproduciblebuilds)
(define-member (person "Zhu Zihao"
"all_but_last@163.com")
localization xfce)
(define-member (person "Maxim Cournoyer"
"maxim.cournoyer@gmail.com")
gnome qt telephony)
(define-member (person "Katherine Cox-Buday"
"cox.katherine.e+guix@gmail.com")
emacs go lisp)
(define (find-team name)
(or (hash-ref %teams (string->symbol name))
(error (format #false
"no such team: ~a~%" name))))
(define (find-team-by-scope files)
"Return the team(s) which scope matches at least one of the FILES, as list
of file names as string."
(hash-fold
(lambda (key team acc)
(if (any (lambda (file)
(any (match-lambda
((? string? scope)
(string=? scope file))
((? regexp*? scope)
(regexp*-exec scope file)))
(team-scope team)))
files)
(cons team acc)
acc))
'()
%teams))
(define (cc . teams)
"Return arguments for `git send-email' to notify the members of the given
TEAMS when a patch is received by Debbugs."
(let ((members (append-map team-members teams)))
(unless (null? members)
(format #true "--add-header=\"X-Debbugs-Cc: ~{~a~^, ~}\""
(map person-email (sort-members members))))))
(define (sort-members members)
"Deduplicate and sort MEMBERS alphabetically by their name."
(sort (delete-duplicates members equal?)
(lambda (m1 m2)
(string<? (person-name m1) (person-name m2)))))
(define (member->string member)
"Return the 'email <name>' string representation of MEMBER."
(let* ((name (person-name member))
(quoted-name/maybe (if (string-contains name ",")
(string-append "\"" name "\"")
name)))
(format #false "~a <~a>" quoted-name/maybe (person-email member))))
(define* (list-members team #:key (prefix ""))
"Print the members of the given TEAM."
(for-each (lambda (member)
(format #t "~a~a~%" prefix (member->string member)))
(sort-members (team-members team))))
(define (print-team team)
"Print TEAM, a <team> record object."
(format #t
"\
id: ~a
name: ~a
description: ~a
~amembers:
"
(team-id team)
(team-name team)
(or (and=> (team-description team)
(lambda (text)
(string->recutils
(fill-paragraph text (%text-width)
(string-length "description: ")))))
"<none>")
(match (team-scope team)
(() "")
(scope (format #f "scope:~%~{+ ~a~^~%~}~%"
(sort (map (match-lambda
((? regexp*? rx)
(regexp*-pattern rx))
(item item))
scope)
string<?)))))
(list-members team #:prefix "+ ")
(newline))
(define (sort-teams teams)
"Sort TEAMS, a list of <team> record objects."
(sort teams
(lambda (team1 team2)
(string<? (symbol->string (team-id team1))
(symbol->string (team-id team2))))))
(define* (list-teams #:optional team-names)
"Print all teams, their scope and their members."
(for-each print-team
(sort-teams
(if team-names
(map find-team team-names)
(hash-map->list (lambda (_ value) value) %teams)))))
(define (diff-revisions rev-start rev-end)
"Return the list of added, modified or removed files between REV-START
and REV-END, two git revision strings."
(let* ((repository (repository-open (getcwd)))
(commit1 (commit-lookup repository
(object-id
(revparse-single repository rev-start))))
(commit2 (commit-lookup repository
(object-id
(revparse-single repository rev-end))))
(diff (diff-tree-to-tree repository
(commit-tree commit1)
(commit-tree commit2)))
(files '()))
(diff-foreach
diff
(lambda (delta progress)
(set! files
(cons (diff-file-path (diff-delta-old-file delta)) files))
0)
(const 0)
(const 0)
(const 0))
files))
(define (git-patch->commit-id file)
"Parse the commit ID from the first line of FILE, a patch produced with git."
(call-with-input-file file
(lambda (port)
(let ((m (string-match "^From ([0-9a-f]{40})" (read-line port))))
(unless m
(error "invalid patch file:" file))
(match:substring m 1)))))
(define (git-patch->revisions file)
"Return the start and end revisions of FILE, a patch file produced with git."
(let* ((rev-end (git-patch->commit-id file))
(rev-start (string-append rev-end "^")))
(list rev-start rev-end)))
(define (patch->teams patch-file)
"Return the name of the teams in scope for the changes in PATCH-FILE."
(map (compose symbol->string team-id)
(find-team-by-scope (apply diff-revisions
(git-patch->revisions patch-file)))))
(define (main . args)
(match args
(("cc" . team-names)
(apply cc (map find-team team-names)))
(("cc-members" patch-file)
(unless (file-exists? patch-file)
(error "patch file does not exist:" patch-file))
(apply main "cc-members" (git-patch->revisions patch-file)))
(("cc-members" rev-start rev-end)
(apply cc (find-team-by-scope
(diff-revisions rev-start rev-end))))
(("cc-members-header-cmd" patch-file)
(let* ((teams (map find-team (patch->teams patch-file)))
(members (sort-members (append-map team-members teams))))
(unless (null? members)
(format #true "X-Debbugs-Cc: ~{~a~^, ~}"
(map member->string members)))))
(("cc-mentors-header-cmd" patch-file)
(format #true "X-Debbugs-Cc: ~{~a~^, ~}"
(map member->string
(sort-members (team-members (find-team "mentors"))))))
(("get-maintainer" patch-file)
(apply main "list-members" (patch->teams patch-file)))
(("list-teams" . args)
(list-teams))
(("list-members" . team-names)
(for-each
(lambda (team-name)
(list-members (find-team team-name)))
team-names))
(("show" . team-names)
(list-teams team-names))
(anything
(format (current-error-port)
"Usage: etc/teams.scm <command> [<args>]
Commands:
cc <team-name>
get git send-email flags for cc-ing <team-name>
cc-members <start> <end> | <patch>
cc teams related to files changed between revisions or in a patch file
cc-members-header-cmd <patch>
cc-members variant for use with 'git send-email --header-cmd'
cc-mentors-header-cmd <patch>
command to use with 'git send-email --header-cmd' to notify mentors
list-teams
list teams and their members
list-members <team-name>
list members belonging to <team-name>
get-maintainer <patch>
compatibility mode with Linux get_maintainer.pl
show <team-name>
display <team-name> properties~%"))))
(apply main (cdr (command-line)))
-50
View File
@@ -1,50 +0,0 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2023 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
;;; This file returns a manifest of packages related to linux-libre.
;;; Simplistically, it selects packages whose names begin with "linux-libre".
;;; It is used to assist continuous integration of the kernel packages.
(use-modules (guix packages)
(guix profiles)
(guix utils)
(gnu packages))
(define* (qt-packages-manifest #:key major-version negate-version-test?)
"Return a manifest of Qt packages for MAJOR-VERSION, or any version if left
unspecified. If NEGATE-VERSION-TEST? is true, select all the Qt packages
*not* matching MAJOR-VERSION."
(manifest
(map package->manifest-entry
(fold-packages
(lambda (package lst)
(let ((uri (and=> (package-source package)
(lambda (x)
(and (origin? x)
(origin-uri x))))))
(if (and uri
(string? uri)
(string-prefix? "mirror://qt/" uri)
(if major-version
((if negate-version-test? not identity)
(string=? major-version (version-major
(package-version package))))
#t))
(cons package lst)
lst)))
'()))))
-34
View File
@@ -1,34 +0,0 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2023 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
;;; This file returns a manifest of packages related to linux-libre.
;;; Simplistically, it selects packages whose names begin with "linux-libre".
;;; It is used to assist continuous integration of the kernel packages.
(load "common.scm")
;;; Commentary:
;;;
;;; This manifest can be used to update the latest Qt packages collection, via
;;; e.g.:
;;;
;;; ./pre-inst-env guix refresh -u -m etc/teams/qt/qt-manifest.scm
;;;
;;; Code:
(qt-packages-manifest #:major-version "5" #:negate-version-test? #t)
-34
View File
@@ -1,34 +0,0 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2023 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
;;; This file returns a manifest of packages related to linux-libre.
;;; Simplistically, it selects packages whose names begin with "linux-libre".
;;; It is used to assist continuous integration of the kernel packages.
(load "common.scm")
;;; Commentary:
;;;
;;; This manifest can be used to update the Qt 5 packages collection, via
;;; e.g.:
;;;
;;; ./pre-inst-env guix refresh -u -m etc/teams/qt/qt5-manifest.scm --target-version=5.15.10
;;;
;;; Code:
(qt-packages-manifest #:major-version "5")
-84
View File
@@ -1,84 +0,0 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2022 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
;;; This file returns a manifest containing entries to build past Guix
;;; releases from the current Guix, as per 'guix time-machine'.
(use-modules (srfi srfi-9) (ice-9 match)
(guix channels) (guix gexp)
((guix store) #:select (%store-monad))
((guix monads) #:select (mparameterize return))
((guix git) #:select (%repository-cache-directory))
((guix build utils) #:select (mkdir-p)))
;; Representation of the latest channels. This type exists just so we can
;; refer to such records in a gexp.
(define-record-type <guix-instance>
(guix-instance channels)
guix-instance?
(channels guix-instance-channels))
(define-gexp-compiler (guix-instance-compiler (instance <guix-instance>)
system target)
(match instance
(($ <guix-instance> channels)
;; When this manifest is evaluated by Cuirass, make sure it does not
;; fiddle with the cached checkout that Cuirass is also using since
;; concurrent accesses are unsafe.
(mparameterize %store-monad ((%repository-cache-directory
(string-append (%repository-cache-directory)
"/time-travel/" system)))
(return (mkdir-p (%repository-cache-directory)))
(latest-channel-derivation channels)))))
(define (guix-instance->manifest-entry instance)
"Return a manifest entry for INSTANCE."
(define (shorten commit)
(string-take commit 7))
(manifest-entry
(name "guix")
(version (string-join (map (compose shorten channel-commit)
(guix-instance-channels instance))
"-"))
(item instance)))
(define (commit->guix-instance commit)
"Return a Guix instance for COMMIT."
(guix-instance (list (channel
(inherit %default-guix-channel)
(commit commit)))))
(define %release-commits
;; Release commits: the list of version/commit pairs.
'(("1.3.0" . "a0178d34f582b50e9bdbb0403943129ae5b560ff")
("1.2.0" . "a099685659b4bfa6b3218f84953cbb7ff9e88063")
("1.1.0" . "d62c9b2671be55ae0305bebfda17b595f33797f2")
("1.0.1" . "d68de958b60426798ed62797ff7c96c327a672ac")
("1.0.0" . "6298c3ffd9654d3231a6f25390b056483e8f407c")
("0.16.0" . "4a0b87f0ec5b6c2dcf82b372dd20ca7ea6acdd9c")))
(manifest
(map (match-lambda
((version . commit)
(let ((entry (guix-instance->manifest-entry
(commit->guix-instance commit))))
(manifest-entry
(inherit entry)
(version version)))))
%release-commits))
+2 -2
View File
@@ -29,7 +29,7 @@
;;; Code:
(define %artwork-repository
(let ((commit "4c7f2ce6428a63e202cd2a9474a06f68a946934d"))
(let ((commit "2f2fe74c1078be605a6a93c2193fd6c715cebbb0"))
(origin
(method git-fetch)
(uri (git-reference
@@ -39,6 +39,6 @@
"-checkout"))
(sha256
(base32
"1rl569759q9wm1dxn7nkq3873d2k92giic7aa6jwzwr3n16prc7y")))))
"0c8r0phvm3wgf914n2kw1461cwdjl2zbzqvzq9x7d9pwkgv7xmq7")))))
;;; artwork.scm ends here
+88 -179
View File
@@ -1,11 +1,9 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2017 David Craven <david@craven.ch>
;;; Copyright © 2017, 2020, 2022 Mathieu Othacehe <othacehe@gnu.org>
;;; Copyright © 2017, 2020 Mathieu Othacehe <m.othacehe@gmail.com>
;;; Copyright © 2017 Leo Famulari <leo@famulari.name>
;;; Copyright © 2019, 2021 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2019 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,19 +21,12 @@
;;; 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)
#:use-module (guix records)
#:use-module (guix deprecation)
#:use-module ((guix ui) #:select (warn-about-load-error))
#:use-module (guix diagnostics)
#:use-module (guix i18n)
#:use-module (guix ui)
#: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 +39,6 @@
menu-entry-multiboot-kernel
menu-entry-multiboot-arguments
menu-entry-multiboot-modules
menu-entry-chain-loader
menu-entry->sexp
sexp->menu-entry
@@ -65,8 +55,7 @@
bootloader-configuration
bootloader-configuration?
bootloader-configuration-bootloader
bootloader-configuration-target ;deprecated
bootloader-configuration-targets
bootloader-configuration-target
bootloader-configuration-menu-entries
bootloader-configuration-default-entry
bootloader-configuration-timeout
@@ -76,7 +65,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 +96,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 +132,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 +145,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)))))
;;;
@@ -242,57 +179,30 @@ record."
;; The <bootloader-configuration> record contains bootloader independant
;; configuration used to fill bootloader configuration file.
(define-with-syntax-properties (warn-target-field-deprecation
(value properties))
(when value
(warning (source-properties->location properties)
(G_ "the 'target' field is deprecated, please use 'targets' \
instead~%")))
value)
(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
(define-deprecated (bootloader-configuration-target config)
bootloader-configuration-targets
(%bootloader-configuration-target config))
(define (bootloader-configuration-targets config)
(or (%bootloader-configuration-targets config)
;; TODO: Remove after the deprecated 'target' field is removed.
(list (%bootloader-configuration-target config))
;; XXX: At least the GRUB installer (see (gnu bootloader grub)) has this
;; peculiar behavior of installing fonts and GRUB modules when DEVICE is #f,
;; hence the default value of '(#f) rather than '().
(list #f)))
(bootloader bootloader-configuration-bootloader) ;<bootloader>
(target bootloader-configuration-target ;string
(default #f))
(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)))
;;;
@@ -322,22 +232,26 @@ instead~%")))
(force %bootloaders))
(leave (G_ "~a: no such bootloader~%") name)))
(define (efi-bootloader-profile packages files hooks)
"Creates a profile from the lists of PACKAGES and FILES from the store.
This profile is meant to be used by the bootloader-installer.
(define (efi-bootloader-profile files bootloader-package hooks)
"Creates a profile with BOOTLOADER-PACKAGE and a directory collection/ with
links to additional FILES from the store. This collection is meant to be used
by the bootloader installer.
FILES is a list of file or directory names from the store, which will be
symlinked into the profile. If a directory name ends with '/', then the
directory content instead of the directory itself will be symlinked into the
profile.
symlinked into the collection/ directory. If a directory name ends with '/',
then the directory content instead of the directory itself will be symlinked
into the collection/ directory.
FILES may contain file like objects produced by procedures like plain-file,
FILES may contain file like objects produced by functions like plain-file,
local-file, etc., or package contents produced with file-append.
HOOKS lists additional hook functions to modify the profile."
(define (efi-bootloader-profile-hook manifest)
(define (bootloader-collection manifest)
(define build
(with-imported-modules '((guix build utils))
(with-imported-modules '((guix build utils)
(ice-9 ftw)
(srfi srfi-1)
(srfi srfi-26))
#~(begin
(use-modules ((guix build utils)
#:select (mkdir-p strip-store-file-name))
@@ -361,7 +275,8 @@ HOOKS lists additional hook functions to modify the profile."
(define (name-is-store-entry? name)
"Return #t if NAME is a direct store entry and nothing inside."
(not (string-index (strip-store-file-name name) #\/)))
(let* ((files '#$files)
(let* ((collection (string-append #$output "/collection"))
(files '#$files)
(directories (filter name-ends-with-/? files))
(names-from-directories
(append-map (lambda (directory)
@@ -369,11 +284,11 @@ HOOKS lists additional hook functions to modify the profile."
directories))
(names (append names-from-directories
(remove name-ends-with-/? files))))
(mkdir-p #$output)
(mkdir-p collection)
(if (every file-exists? names)
(begin
(for-each (lambda (name)
(symlink-to name #$output
(symlink-to name collection
(if (name-is-store-entry? name)
strip-store-file-name
basename)))
@@ -381,63 +296,57 @@ HOOKS lists additional hook functions to modify the profile."
#t)
#f)))))
(gexp->derivation "efi-bootloader-profile"
(gexp->derivation "bootloader-collection"
build
#:local-build? #t
#:substitutable? #f
#:properties
`((type . profile-hook)
(hook . efi-bootloader-profile-hook))))
(hook . bootloader-collection))))
(profile (content (packages->manifest packages))
(name "efi-bootloader-profile")
(hooks (cons efi-bootloader-profile-hook hooks))
(profile (content (packages->manifest (list bootloader-package)))
(name "bootloader-profile")
(hooks (append (list bootloader-collection) hooks))
(locales? #f)
(allow-collisions? #f)
(relative-symlinks? #f)))
(define* (efi-bootloader-chain final-bootloader
(define* (efi-bootloader-chain files
final-bootloader
#:key
(packages '())
(files '())
(hooks '())
installer
disk-image-installer)
"Define a chain of bootloaders with the FINAL-BOOTLOADER, optional PACKAGES,
and optional directories and files from the store given in the list of FILES.
installer)
"Define a bootloader chain with FINAL-BOOTLOADER as the final bootloader and
certain directories and files from the store given in the list of FILES.
The package of the FINAL-BOOTLOADER and all PACKAGES and FILES will be placed
in an efi-bootloader-profile, which will be passed to the INSTALLER.
FILES may contain file-like objects produced by procedures like plain-file,
local-file, etc., or package contents produced with file-append.
FILES may contain file like objects produced by functions like plain-file,
local-file, etc., or package contents produced with file-append. They will be
collected inside a directory collection/ inside a generated bootloader profile,
which will be passed to the INSTALLER.
If a directory name in FILES ends with '/', then the directory content instead
of the directory itself will be symlinked into the efi-bootloader-profile.
of the directory itself will be symlinked into the collection/ directory.
The procedures in the HOOKS list can be used to further modify the bootloader
profile. It is possible to pass a single function instead of a list.
If the INSTALLER argument is used, then this gexp procedure will be called to
install the efi-bootloader-profile. Otherwise the installer of the
FINAL-BOOTLOADER will be called.
If the DISK-IMAGE-INSTALLER is used, then this gexp procedure will be called
to install the efi-bootloader-profile into a disk image. Otherwise the
disk-image-installer of the FINAL-BOOTLOADER will be called."
(bootloader
(inherit final-bootloader)
(name "efi-bootloader-chain")
(package
(efi-bootloader-profile (cons (bootloader-package final-bootloader)
packages)
files
(if (list? hooks)
hooks
(list hooks))))
(installer
(or installer
(bootloader-installer final-bootloader)))
(disk-image-installer
(or disk-image-installer
(bootloader-disk-image-installer final-bootloader)))))
If the INSTALLER argument is used, then this function will be called to install
the bootloader. Otherwise the installer of the FINAL-BOOTLOADER will be called."
(let* ((final-installer (or installer
(bootloader-installer final-bootloader)))
(profile (efi-bootloader-profile files
(bootloader-package final-bootloader)
(if (list? hooks)
hooks
(list hooks)))))
(bootloader
(inherit final-bootloader)
(package profile)
(installer
#~(lambda (bootloader target mount-point)
(#$final-installer bootloader target mount-point)
(copy-recursively
(string-append bootloader "/collection")
(string-append mount-point target)
#:follow-symlinks? #t
#:log (%make-void-port "w")))))))
+2 -10
View File
@@ -1,7 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2017 David Craven <david@craven.ch>
;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
;;; Copyright © 2022 Reza Alizadeh Majd <r.majd@pantherx.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -39,9 +38,6 @@ corresponding to old generations of the system."
(define all-entries
(append entries (bootloader-configuration-menu-entries config)))
(define with-fdtdir?
(bootloader-configuration-device-tree-support? config))
(define (menu-entry->gexp entry)
(let ((label (menu-entry-label entry))
(kernel (menu-entry-linux entry))
@@ -50,16 +46,12 @@ corresponding to old generations of the system."
#~(format port "LABEL ~a
MENU LABEL ~a
KERNEL ~a
~a
FDTDIR ~a/lib/dtbs
INITRD ~a
APPEND ~a
~%"
#$label #$label
#$kernel
(if #$with-fdtdir?
(string-append "FDTDIR " (dirname #$kernel) "/lib/dtbs")
"")
#$initrd
#$kernel (dirname #$kernel) #$initrd
(string-join (list #$@kernel-arguments)))))
(define builder
+143 -286
View File
@@ -3,12 +3,10 @@
;;; Copyright © 2016 Chris Marusich <cmmarusich@gmail.com>
;;; Copyright © 2017 Leo Famulari <leo@famulari.name>
;;; Copyright © 2017, 2020 Mathieu Othacehe <m.othacehe@gmail.com>
;;; Copyright © 2019, 2020, 2023 Janneke Nieuwenhuizen <janneke@gnu.org>
;;; Copyright © 2019, 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
;;; Copyright © 2019, 2020 Miguel Ángel Arruga Vivas <rosen644835@gmail.com>
;;; Copyright © 2020 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;; Copyright © 2020 Stefan <stefan-guix@vodafonemail.de>
;;; Copyright © 2022 Karl Hallsby <karl@hallsby.com>
;;; Copyright © 2022 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -52,15 +50,11 @@
grub-theme-color-highlight
grub-theme-gfxmode
install-grub-efi-removable
make-grub-efi-netboot-installer
install-grub-efi-netboot
grub-bootloader
grub-efi-bootloader
grub-efi-removable-bootloader
grub-efi32-bootloader
grub-efi-netboot-bootloader
grub-efi-netboot-removable-bootloader
grub-mkrescue-bootloader
grub-minimal-bootloader
@@ -270,38 +264,36 @@ is a string that can be inserted in grub.cfg."
at_keyboard usb_keyboard))
(io (string-append
;; UNIT and SPEED are arguments to the same GRUB command
;; ("serial"), so we process them together.
(if (or unit speed)
(string-append
"serial"
(if unit
;; COM ports 1 through 4
(if (and (exact-integer? unit) (<= unit 3) (>= unit 0))
(string-append " --unit=" (number->string unit))
#f)
"")
(if speed
(if (exact-integer? speed)
(string-append " --speed=" (number->string speed))
#f)
"")
"\n")
"")
(if (null? inputs)
""
(string-append
"terminal_output "
(symbols->string
(map
(lambda (output)
(if (memq output valid-outputs) output #f)) outputs)) "\n"
(if (null? inputs)
""
(string-append
"terminal_input "
(symbols->string
(map
(lambda (input)
(if (memq input valid-inputs) input #f)) inputs))
"\n"))
"terminal_output "
(symbols->string
(map
(lambda (output)
(if (memq output valid-outputs) output #f)) outputs)))))
(map
(lambda (input)
(if (memq input valid-inputs) input #f)) inputs)) "\n"))
;; UNIT and SPEED are arguments to the same GRUB command
;; ("serial"), so we process them together.
(if (or unit speed)
(string-append
"serial"
(if unit
;; COM ports 1 through 4
(if (and (exact-integer? unit) (<= unit 3) (>= unit 0))
(string-append " --unit=" (number->string unit))
#f)
"")
(if speed
(if (exact-integer? speed)
(string-append " --speed=" (number->string speed))
#f)
""))
""))))
(format #f "~a" io)))
(define (grub-root-search device file)
@@ -354,7 +346,7 @@ code."
((or #f (? string?))
#~(format #f "search --file --set ~a" #$file)))))
(define* (make-grub-configuration grub config entries
(define* (grub-configuration-file config entries
#:key
(locale #f)
(system (%current-system))
@@ -375,63 +367,44 @@ when booting a root file system on a Btrfs subvolume."
(let ((label (menu-entry-label entry))
(linux (menu-entry-linux entry))
(device (menu-entry-device entry))
(device-mount-point (menu-entry-device-mount-point entry))
(multiboot-kernel (menu-entry-multiboot-kernel entry))
(chain-loader (menu-entry-chain-loader entry)))
(cond
(linux
(let ((arguments (menu-entry-linux-arguments entry))
(linux (normalize-file linux
device-mount-point
store-directory-prefix))
(initrd (normalize-file (menu-entry-initrd entry)
device-mount-point
store-directory-prefix)))
;; Here DEVICE is the store and DEVICE-MOUNT-POINT is its mount point.
;; Use the right file names for LINUX and INITRD in case
;; DEVICE-MOUNT-POINT is not "/", meaning that the store is on a
;; separate partition.
(device-mount-point (menu-entry-device-mount-point entry)))
(if linux
(let ((arguments (menu-entry-linux-arguments entry))
(linux (normalize-file linux
device-mount-point
store-directory-prefix))
(initrd (normalize-file (menu-entry-initrd entry)
device-mount-point
store-directory-prefix)))
;; Here DEVICE is the store and DEVICE-MOUNT-POINT is its mount point.
;; Use the right file names for LINUX and INITRD in case
;; DEVICE-MOUNT-POINT is not "/", meaning that the store is on a
;; separate partition.
;; When STORE-DIRECTORY-PREFIX is defined, prepend it the linux and
;; initrd paths, to allow booting from a Btrfs subvolume.
#~(format port "menuentry ~s {
;; When BTRFS-SUBVOLUME-FILE-NAME is defined, prepend it the linux and
;; initrd paths, to allow booting from a Btrfs subvolume.
#~(format port "menuentry ~s {
~a
linux ~a ~a
initrd ~a
}~%"
#$label
#$(grub-root-search device linux)
#$linux (string-join (list #$@arguments))
#$initrd)))
(multiboot-kernel
(let* ((kernel (menu-entry-multiboot-kernel entry))
(arguments (menu-entry-multiboot-arguments entry))
;; Choose between device names as understood by Mach's built-in
;; IDE driver ("hdX") and those understood by rumpdisk ("wdX"
;; in the "noide" case).
(disk (if (member "noide" arguments) "w" "h"))
(modules (menu-entry-multiboot-modules entry))
(root-index 1)) ; XXX EFI will need root-index 2
#~(format port "
menuentry ~s {
multiboot ~a root=part:~a:device:~ad0~a~a
}~%"
#$label
#$kernel
#$root-index
#$disk
(string-join (list #$@arguments) " " 'prefix)
(string-join (map string-join '#$modules)
"\n module " 'prefix))))
(chain-loader
#$label
#$(grub-root-search device linux)
#$linux (string-join (list #$@arguments))
#$initrd))
(let ((kernel (menu-entry-multiboot-kernel entry))
(arguments (menu-entry-multiboot-arguments entry))
(modules (menu-entry-multiboot-modules entry))
(root-index 1)) ; XXX EFI will need root-index 2
#~(format port "
menuentry ~s {
~a
chainloader ~a
multiboot ~a root=device:hd0s~a~a~a
}~%"
#$label
#$(grub-root-search device chain-loader)
#$chain-loader)))))
#$kernel
#$root-index (string-join (list #$@arguments) " " 'prefix)
(string-join (map string-join '#$modules)
"\n module " 'prefix))))))
(define (crypto-devices)
(define (crypto-device->cryptomount dev)
@@ -442,7 +415,8 @@ menuentry ~s {
;; Other type of devices aren't implemented.
#~()))
(let ((devices (map crypto-device->cryptomount store-crypto-devices))
(modules #~(format port "insmod luks~%insmod luks2~%")))
;; XXX: Add luks2 when grub 2.06 is packaged.
(modules #~(format port "insmod luks~%")))
(if (null? devices)
devices
(cons modules devices))))
@@ -460,7 +434,9 @@ menuentry ~s {
(define locale-config
(let* ((entry (first all-entries))
(device (menu-entry-device entry))
(mount-point (menu-entry-device-mount-point entry)))
(mount-point (menu-entry-device-mount-point entry))
(bootloader (bootloader-configuration-bootloader config))
(grub (bootloader-package bootloader)))
#~(let ((locale #$(and locale
(locale-definition-source
(locale-name->definition locale))))
@@ -486,6 +462,8 @@ set lang=~a~%"
(define keyboard-layout-config
(let* ((layout (bootloader-configuration-keyboard-layout config))
(grub (bootloader-package
(bootloader-configuration-bootloader config)))
(keymap* (and layout
(keyboard-layout-file layout #:grub grub)))
(entry (first all-entries))
@@ -536,16 +514,6 @@ fi~%"))))
#:options '(#:local-build? #t
#:substitutable? #f)))
(define (grub-configuration-file config . args)
(let* ((bootloader (bootloader-configuration-bootloader config))
(grub (bootloader-package bootloader)))
(apply make-grub-configuration grub config args)))
(define (grub-efi-configuration-file . args)
(apply make-grub-configuration grub-efi args))
(define grub-cfg "/boot/grub/grub.cfg")
;;;
@@ -639,101 +607,61 @@ fi~%"))))
"--bootloader-id=Guix"
"--efi-directory" target-esp)))))
(define install-grub-efi-removable
#~(lambda (bootloader efi-dir mount-point)
;; NOTE: mount-point is /mnt in guix system init /etc/config.scm /mnt/point
;; NOTE: efi-dir comes from target list of booloader configuration
;; There is nothing useful to do when called in the context of a disk
;; image generation.
(when efi-dir
;; Install GRUB onto the EFI partition mounted at EFI-DIR, for the
;; system whose root is mounted at MOUNT-POINT.
(let ((grub-install (string-append bootloader "/sbin/grub-install"))
(install-dir (string-append mount-point "/boot"))
;; When installing Guix, it's common to mount EFI-DIR below
;; MOUNT-POINT rather than /boot/efi on the live image.
(target-esp (if (file-exists? (string-append mount-point efi-dir))
(string-append mount-point efi-dir)
efi-dir)))
;; Tell 'grub-install' that there might be a LUKS-encrypted /boot or
;; root partition.
(setenv "GRUB_ENABLE_CRYPTODISK" "y")
(invoke/quiet grub-install "--boot-directory" install-dir
"--removable"
;; "--no-nvram"
"--bootloader-id=Guix"
"--efi-directory" target-esp)))))
(define install-grub-efi32
#~(lambda (bootloader efi-dir mount-point)
;; There is nothing useful to do when called in the context of a disk
;; image generation.
(when efi-dir
;; Install GRUB onto the EFI partition mounted at EFI-DIR, for the
;; system whose root is mounted at MOUNT-POINT.
(let ((grub-install (string-append bootloader "/sbin/grub-install"))
(install-dir (string-append mount-point "/boot"))
;; When installing Guix, it's common to mount EFI-DIR below
;; MOUNT-POINT rather than /boot/efi on the live image.
(target-esp (if (file-exists? (string-append mount-point efi-dir))
(string-append mount-point efi-dir)
efi-dir)))
;; Tell 'grub-install' that there might be a LUKS-encrypted /boot or
;; root partition.
(setenv "GRUB_ENABLE_CRYPTODISK" "y")
(invoke/quiet grub-install "--boot-directory" install-dir
"--bootloader-id=Guix"
(cond ((target-x86?) "--target=i386-efi")
((target-arm?) "--target=arm-efi"))
"--efi-directory" target-esp)))))
(define* (make-grub-efi-netboot-installer grub-efi grub-cfg subdir)
"Make a bootloader-installer for a grub-efi-netboot bootloader, which expects
its files in SUBDIR and its configuration file in GRUB-CFG.
As a grub-efi-netboot package is already pre-installed by 'grub-mknetdir', the
installer basically copies all files from the bootloader-package (or profile)
into the bootloader-target directory.
Additionally for network booting over TFTP, two relative symlinks to the store
and to the GRUB-CFG file are necessary. Due to this a TFTP root directory must
not be located on a FAT file-system.
If the bootloader-target does not support symlinks, then it is assumed to be a
kind of EFI System Partition (ESP). In this case an intermediate configuration
file is created with the help of GRUB-EFI to load the GRUB-CFG.
The installer is usable for any efi-bootloader-chain, which prepares the
bootloader-profile in a way ready for copying.
The installer does not manipulate the system's 'UEFI Boot Manager'.
The returned installer accepts the BOOTLOADER, TARGET and MOUNT-POINT
arguments. Its job is to copy the BOOTLOADER, which must be a pre-installed
grub-efi-netboot package with a SUBDIR like efi/boot or efi/Guix, below the
directory TARGET for the system whose root is mounted at MOUNT-POINT.
(define (install-grub-efi-netboot subdir)
"Define a grub-efi-netboot bootloader installer for installation in SUBDIR,
which is usually efi/Guix or efi/boot."
(let* ((system (string-split (nix-system->gnu-triplet
(or (%current-target-system)
(%current-system)))
#\-))
(arch (first system))
(boot-efi-link (match system
;; These are the supportend systems and the names
;; defined by the UEFI standard for removable media.
(("i686" _ ...) "/bootia32.efi")
(("x86_64" _ ...) "/bootx64.efi")
(("arm" _ ...) "/bootarm.efi")
(("aarch64" _ ...) "/bootaa64.efi")
(("riscv" _ ...) "/bootriscv32.efi")
(("riscv64" _ ...) "/bootriscv64.efi")
;; Other systems are not supported, although defined.
;; (("riscv128" _ ...) "/bootriscv128.efi")
;; (("ia64" _ ...) "/bootia64.efi")
((_ ...) #f)))
(core-efi (string-append
;; This is the arch dependent file name of GRUB, e.g.
;; i368-efi/core.efi or arm64-efi/core.efi.
(match arch
("i686" "i386")
("aarch64" "arm64")
("riscv" "riscv32")
(_ arch))
"-efi/core.efi")))
(with-imported-modules
'((guix build union))
#~(lambda (bootloader target mount-point)
"Install the BOOTLOADER, which must be the package grub, as e.g.
bootx64.efi or bootaa64.efi into SUBDIR, which is usually efi/Guix or efi/boot,
below the directory TARGET for the system whose root is mounted at MOUNT-POINT.
MOUNT-POINT is the last argument in 'guix system init /etc/config.scm mnt/point'
or '/' for other 'guix system' commands.
Where TARGET comes from the targets argument given to the
bootloader-configuration in:
TARGET is the target argument given to the bootloader-configuration in
(operating-system
(bootloader (bootloader-configuration
(targets '(\"/boot/efi\"))
(target \"/boot\")
…))
…)
TARGET is required to be an absolute directory name, usually mounted via NFS,
and finally needs to be provided by a TFTP server as
the TFTP root directory.
and finally needs to be provided by a TFTP server as the TFTP root directory.
Usually the installer will be used to prepare network booting over TFTP. Then
GRUB will load tftp://server/SUBDIR/grub.cfg and this file will instruct it to
load more files from the store like tftp://server/gnu/store/…-linux…/Image.
To make this possible two symlinks are created. The first symlink points
To make this possible two symlinks will be created. The first symlink points
relatively form MOUNT-POINT/TARGET/SUBDIR/grub.cfg to
MOUNT-POINT/boot/grub/grub.cfg, and the second symlink points relatively from
MOUNT-POINT/TARGET/%store-prefix to MOUNT-POINT/%store-prefix.
@@ -743,80 +671,34 @@ paths on the TFTP server side are unknown.
It is also important to note that both symlinks will point outside the TFTP root
directory and that the TARGET/%store-prefix symlink makes the whole store
accessible via TFTP. Possibly the TFTP server must be configured to allow
accesses outside its TFTP root directory. This all may need to be considered
for security aspects. It is advised to disable any TFTP write access!
The installer can also be used to prepare booting from local storage, if the
underlying file-system, like FAT on an EFI System Partition (ESP), does not
support symlinks. In this case the MOUNT-POINT/TARGET/SUBDIR/grub.cfg will be
created with the help of GRUB-EFI to load the /boot/grub/grub.cfg file. A
symlink to the store is not needed in this case."
(with-imported-modules '((guix build union))
#~(lambda (bootloader target mount-point)
;; In context of a disk image creation TARGET will be #f and an
;; installer is expected to do necessary installations on MOUNT-POINT,
;; which will become the root file system. If TARGET is #f, this
;; installer has nothing to do, as it only cares about the EFI System
;; Partition (ESP).
(when target
(use-modules ((guix build union) #:select (symlink-relative))
(ice-9 popen)
(ice-9 rdelim))
(let* ((mount-point/target (string-append mount-point target "/"))
;; When installing Guix, it is common to mount TARGET below
;; MOUNT-POINT rather than the root directory.
(bootloader-target (if (file-exists? mount-point/target)
mount-point/target
target))
(store (string-append mount-point (%store-prefix)))
(store-link (string-append bootloader-target (%store-prefix)))
(grub-cfg (string-append mount-point #$grub-cfg))
(grub-cfg-link (string-append bootloader-target
#$subdir "/"
(basename grub-cfg))))
;; Copy the bootloader into the bootloader-target directory.
;; Should we beforehand recursively delete any existing file?
(copy-recursively bootloader bootloader-target
#:follow-symlinks? #t
#:log (%make-void-port "w"))
;; For TFTP we need to install additional relative symlinks.
;; If we install on an EFI System Partition (ESP) or some other FAT
;; file-system, then symlinks cannot be created and are not needed.
;; Therefore we ignore exceptions when trying.
;; Prepare the symlink to the grub.cfg.
(mkdir-p (dirname grub-cfg-link))
(false-if-exception (delete-file grub-cfg-link))
(if (unspecified?
(false-if-exception (symlink-relative grub-cfg grub-cfg-link)))
;; Symlinks are supported.
(begin
;; Prepare the symlink to the store.
(mkdir-p (dirname store-link))
(false-if-exception (delete-file store-link))
(symlink-relative store store-link))
;; Creating symlinks does not seem to be supported. Probably
;; an ESP is used. Add a script to search and load the actual
;; grub.cfg.
(let* ((probe #$(file-append grub-efi "/sbin/grub-probe"))
(port (open-pipe* OPEN_READ probe "--target=fs_uuid"
grub-cfg))
(search-root
(match (read-line port)
((? eof-object?)
;; There is no UUID available. As a fallback search
;; everywhere for the grub.cfg.
(string-append "search --file --set " #$grub-cfg))
(fs-uuid
;; The UUID to load the grub.cfg from is known.
(string-append "search --fs-uuid --set " fs-uuid))))
(load-grub-cfg (string-append "configfile " #$grub-cfg)))
(close-pipe port)
(with-output-to-file grub-cfg-link
(lambda ()
(display (string-join (list search-root
load-grub-cfg)
"\n")))))))))))
accessible via TFTP. Possibly the TFTP server must be configured
to allow accesses outside its TFTP root directory. This may need to be
considered for security aspects."
(use-modules ((guix build union) #:select (symlink-relative)))
(let* ((net-dir (string-append mount-point target "/"))
(sub-dir (string-append net-dir #$subdir "/"))
(store (string-append mount-point (%store-prefix)))
(store-link (string-append net-dir (%store-prefix)))
(grub-cfg (string-append mount-point "/boot/grub/grub.cfg"))
(grub-cfg-link (string-append sub-dir (basename grub-cfg)))
(boot-efi-link (string-append sub-dir #$boot-efi-link)))
;; Prepare the symlink to the store.
(mkdir-p (dirname store-link))
(false-if-exception (delete-file store-link))
(symlink-relative store store-link)
;; Prepare the symlink to the grub.cfg, which points into the store.
(mkdir-p (dirname grub-cfg-link))
(false-if-exception (delete-file grub-cfg-link))
(symlink-relative grub-cfg grub-cfg-link)
;; Install GRUB, which refers to the grub.cfg, with support for
;; encrypted partitions,
(setenv "GRUB_ENABLE_CRYPTODISK" "y")
(invoke/quiet (string-append bootloader "/bin/grub-mknetdir")
(string-append "--net-directory=" net-dir)
(string-append "--subdir=" #$subdir))
;; Prepare the bootloader symlink, which points to core.efi of GRUB.
(false-if-exception (delete-file boot-efi-link))
(symlink #$core-efi boot-efi-link))))))
@@ -834,7 +716,7 @@ symlink to the store is not needed in this case."
(package grub)
(installer install-grub)
(disk-image-installer install-grub-disk-image)
(configuration-file grub-cfg)
(configuration-file "/boot/grub/grub.cfg")
(configuration-file-generator grub-configuration-file)))
(define grub-minimal-bootloader
@@ -844,42 +726,17 @@ symlink to the store is not needed in this case."
(define grub-efi-bootloader
(bootloader
(name 'grub-efi)
(package grub-efi)
(inherit grub-bootloader)
(installer install-grub-efi)
(disk-image-installer #f)
(configuration-file grub-cfg)
(configuration-file-generator grub-configuration-file)))
(define grub-efi-removable-bootloader
(bootloader
(inherit grub-efi-bootloader)
(name 'grub-efi-removable-bootloader)
(installer install-grub-efi-removable)))
(define grub-efi32-bootloader
(bootloader
(inherit grub-efi-bootloader)
(installer install-grub-efi32)
(name 'grub-efi32)
(package grub-efi32)))
(define (make-grub-efi-netboot-bootloader name subdir)
(bootloader
(name name)
(package (make-grub-efi-netboot (symbol->string name) subdir))
(installer (make-grub-efi-netboot-installer grub-efi grub-cfg subdir))
(disk-image-installer #f)
(configuration-file grub-cfg)
(configuration-file-generator grub-efi-configuration-file)))
(name 'grub-efi)
(package grub-efi)))
(define grub-efi-netboot-bootloader
(make-grub-efi-netboot-bootloader 'grub-efi-netboot-bootloader
"efi/Guix"))
(define grub-efi-netboot-removable-bootloader
(make-grub-efi-netboot-bootloader 'grub-efi-netboot-removable-bootloader
"efi/boot"))
(bootloader
(inherit grub-efi-bootloader)
(name 'grub-efi-netboot-bootloader)
(installer (install-grub-efi-netboot "efi/Guix"))))
(define grub-mkrescue-bootloader
(bootloader
+2 -40
View File
@@ -3,8 +3,6 @@
;;; Copyright © 2017, 2019 Mathieu Othacehe <m.othacehe@gmail.com>
;;; Copyright © 2020 Julien Lepiller <julien@lepiller.eu>
;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
;;; Copyright © 2022 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;; Copyright © 2023 Efraim Flashner <efraim@flashner.co.il>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -44,8 +42,6 @@
u-boot-puma-rk3399-bootloader
u-boot-rock64-rk3328-bootloader
u-boot-rockpro64-rk3399-bootloader
u-boot-sifive-unmatched-bootloader
u-boot-ts7970-q-2g-1000mhz-c-bootloader
u-boot-wandboard-bootloader))
(define install-u-boot
@@ -77,12 +73,9 @@
(define install-allwinner64-u-boot
#~(lambda (bootloader root-index image)
(let ((spl (string-append bootloader "/libexec/u-boot-sunxi-with-spl.bin"))
(u-boot (string-append bootloader "/libexec/u-boot-sunxi-with-spl.fit.itb")))
(let ((spl (string-append bootloader "/libexec/u-boot-sunxi-with-spl.fit.itb")))
(write-file-on-device spl (stat:size (stat spl))
image (* 8 1024))
(write-file-on-device u-boot (stat:size (stat u-boot))
image (* 40 1024)))))
image (* 8 1024)))))
(define install-imx-u-boot
#~(lambda (bootloader root-index image)
@@ -131,21 +124,6 @@
(define install-pinebook-pro-rk3399-u-boot install-rockpro64-rk3399-u-boot)
(define install-u-boot-ts7970-q-2g-1000mhz-c-u-boot
#~(lambda (bootloader device mount-point)
(let ((u-boot.imx (string-append bootloader "/libexec/u-boot.imx"))
(install-dir (string-append mount-point "/boot")))
(install-file u-boot.imx install-dir))))
(define install-sifive-unmatched-u-boot
#~(lambda (bootloader root-index image)
(let ((spl (string-append bootloader "/libexec/spl/u-boot-spl.bin"))
(u-boot (string-append bootloader "/libexec/u-boot.itb")))
(write-file-on-device spl (stat:size (stat spl))
image (* 34 512))
(write-file-on-device u-boot (stat:size (stat u-boot))
image (* 2082 512)))))
;;;
@@ -274,19 +252,3 @@
(inherit u-boot-bootloader)
(package u-boot-pinebook-pro-rk3399)
(disk-image-installer install-pinebook-pro-rk3399-u-boot)))
(define u-boot-ts7970-q-2g-1000mhz-c-bootloader
;; This bootloader doesn't really need to be installed, as it is read from
;; an SPI memory chip, not the SD card. It is copied to /boot/u-boot.imx
;; for convenience and should be manually flashed at the U-Boot prompt.
(bootloader
(inherit u-boot-bootloader)
(package u-boot-ts7970-q-2g-1000mhz-c)
(installer install-u-boot-ts7970-q-2g-1000mhz-c-u-boot)
(disk-image-installer #f)))
(define u-boot-sifive-unmatched-bootloader
(bootloader
(inherit u-boot-bootloader)
(package u-boot-sifive-unmatched)
(disk-image-installer install-sifive-unmatched-u-boot)))
+2 -6
View File
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2019, 2021 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2019 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -490,11 +490,7 @@ new UIDs."
(uid id)
(directory directory)
(gid (if (number? group) group (group-id group)))
;; Users might change their name to something
;; other than what the sysadmin chose, with
;; 'chfn'. Thus consider it "stateful".
(real-name (if (and previous (not system?))
(real-name (if previous
(password-entry-real-name previous)
real-name))
+15 -38
View File
@@ -6,8 +6,6 @@
;;; Copyright © 2018 Arun Isaac <arunisaac@systemreboot.net>
;;; Copyright © 2018, 2019 Ricardo Wurmus <rekado@elephly.net>
;;; Copyright © 2021 Maxime Devos <maximedevos@telenet.be>
;;; Copyright © 2020 Christine Lemmer-Webber <cwebber@dustycloud.org>
;;; Copyright © 2021 Brice Waegeneire <brice@waegenei.re>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -26,7 +24,6 @@
(define-module (gnu build activation)
#:use-module (gnu system accounts)
#:use-module (gnu system setuid)
#:use-module (gnu build accounts)
#:use-module (gnu build linux-boot)
#:use-module (guix build utils)
@@ -282,17 +279,14 @@ they already exist."
"/run/setuid-programs")
(define (activate-setuid-programs programs)
"Turn PROGRAMS, a list of file setuid-programs record, into setuid programs
stored under %SETUID-DIRECTORY."
(define (make-setuid-program program setuid? setgid? uid gid)
"Turn PROGRAMS, a list of file names, into setuid programs stored under
%SETUID-DIRECTORY."
(define (make-setuid-program prog)
(let ((target (string-append %setuid-directory
"/" (basename program)))
(mode (+ #o0555 ; base permissions
(if setuid? #o4000 0) ; setuid bit
(if setgid? #o2000 0)))) ; setgid bit
(copy-file program target)
(chown target uid gid)
(chmod target mode)))
"/" (basename prog))))
(copy-file prog target)
(chown target 0 0)
(chmod target #o4555)))
(format #t "setting up setuid programs in '~a'...~%"
%setuid-directory)
@@ -308,27 +302,15 @@ stored under %SETUID-DIRECTORY."
(for-each (lambda (program)
(catch 'system-error
(lambda ()
(let* ((program-name (setuid-program-program program))
(setuid? (setuid-program-setuid? program))
(setgid? (setuid-program-setgid? program))
(user (setuid-program-user program))
(group (setuid-program-group program))
(uid (match user
((? string?) (passwd:uid (getpwnam user)))
((? integer?) user)))
(gid (match group
((? string?) (group:gid (getgrnam group)))
((? integer?) group))))
(make-setuid-program program-name setuid? setgid? uid gid)))
(make-setuid-program program))
(lambda args
;; If we fail to create a setuid program, better keep going
;; so that we don't leave %SETUID-DIRECTORY empty or
;; half-populated. This can happen if PROGRAMS contains
;; incorrect file names: <https://bugs.gnu.org/38800>.
(format (current-error-port)
"warning: failed to make ~s setuid/setgid: ~a~%"
(setuid-program-program program)
(strerror (system-error-errno args))))))
"warning: failed to make '~a' setuid-root: ~a~%"
program (strerror (system-error-errno args))))))
programs))
(define (activate-special-files special-files)
@@ -363,14 +345,9 @@ second element is the name it should appear at, such as:
"Tell the kernel to look for device firmware under DIRECTORY. This
mechanism bypasses udev: it allows Linux to handle firmware loading directly
by itself, without having to resort to a \"user helper\"."
;; If the kernel was built without firmware loading support, this file
;; does not exist. Do nothing in that case.
(let ((firmware-path "/sys/module/firmware_class/parameters/path"))
(when (file-exists? firmware-path)
(call-with-output-file firmware-path
(lambda (port)
(display directory port))))))
(call-with-output-file "/sys/module/firmware_class/parameters/path"
(lambda (port)
(display directory port))))
(define (activate-ptrace-attach)
"Allow users to PTRACE_ATTACH their own processes.
@@ -394,8 +371,8 @@ improvement."
"/run/current-system")
(define (boot-time-system)
"Return the 'gnu.system' argument passed on the kernel command line."
(find-long-option "gnu.system" (if (string-contains %host-type "linux-gnu")
"Return the '--system' argument passed on the kernel command line."
(find-long-option "--system" (if (string-contains %host-type "linux-gnu")
(linux-command-line)
(command-line))))
+13 -25
View File
@@ -1,8 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
;;; Copyright © 2019 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2022 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
;;; Copyright © 2022 Timothy Sample <samplet@ngyro.com>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -56,12 +54,8 @@
;;; EFI bootloader.
;;;
(define* (install-efi grub grub-config esp #:key targets)
"Write a self-contained GRUB EFI loader to the mounted ESP using
GRUB-CONFIG.
If TARGETS is set, use its car as the GRUB image format and its cdr as
the output filename. Otherwise, use defaults for the host platform."
(define (install-efi grub grub-config esp)
"Write a self-contained GRUB EFI loader to the mounted ESP using GRUB-CONFIG."
(let* ((system %host-type)
;; Hard code the output location to a well-known path recognized by
;; compliant firmware. See "3.5.1.1 Removable Media Boot Behaviour":
@@ -69,15 +63,14 @@ the output filename. Otherwise, use defaults for the host platform."
(grub-mkstandalone (string-append grub "/bin/grub-mkstandalone"))
(efi-directory (string-append esp "/EFI/BOOT"))
;; Map grub target names to boot file names.
(efi-targets (or targets
(cond ((string-prefix? "x86_64" system)
'("x86_64-efi" . "BOOTX64.EFI"))
((string-prefix? "i686" system)
'("i386-efi" . "BOOTIA32.EFI"))
((string-prefix? "armhf" system)
'("arm-efi" . "BOOTARM.EFI"))
((string-prefix? "aarch64" system)
'("arm64-efi" . "BOOTAA64.EFI"))))))
(efi-targets (cond ((string-prefix? "x86_64" system)
'("x86_64-efi" . "BOOTX64.EFI"))
((string-prefix? "i686" system)
'("i386-efi" . "BOOTIA32.EFI"))
((string-prefix? "armhf" system)
'("arm-efi" . "BOOTARM.EFI"))
((string-prefix? "aarch64" system)
'("arm64-efi" . "BOOTAA64.EFI")))))
;; grub-mkstandalone requires a TMPDIR to prepare the firmware image.
(setenv "TMPDIR" esp)
@@ -88,12 +81,9 @@ the output filename. Otherwise, use defaults for the host platform."
;; Graft the configuration file onto the image.
(string-append "boot/grub/grub.cfg=" grub-config))))
(define* (install-efi-loader grub-efi esp #:key targets)
(define (install-efi-loader grub-efi esp)
"Install in ESP directory the given GRUB-EFI bootloader. Configure it to
load the Grub bootloader located in the 'Guix_image' root partition.
If TARGETS is set, use its car as the GRUB image format and its cdr as
the output filename. Otherwise, use defaults for the host platform."
load the Grub bootloader located in the 'Guix_image' root partition."
(let ((grub-config "grub.cfg"))
(call-with-output-file grub-config
(lambda (port)
@@ -104,9 +94,7 @@ the output filename. Otherwise, use defaults for the host platform."
;; (not eliminate it).
(format port
"insmod part_msdos~@
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)))
+113 -76
View File
@@ -1,6 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2020, 2021 Marius Bakke <marius@gnu.org>
;;; Copyright © 2022 Nicolas Graves <ngraves@ngraves.fr>
;;; Copyright © 2020 Marius Bakke <marius@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -18,11 +17,17 @@
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (gnu build chromium-extension)
#:use-module (gcrypt base16)
#:use-module ((gcrypt hash) #:prefix hash:)
#:use-module (ice-9 iconv)
#:use-module (guix gexp)
#:use-module (guix packages)
#:use-module (gnu packages base)
#:use-module (gnu packages check)
#: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))
@@ -34,30 +39,28 @@
(define (make-signing-key seed)
"Return a derivation for a deterministic PKCS #8 private key using SEED."
(computed-file
(string-append seed "-signing-key.pem")
(with-extensions (list guile-gcrypt)
#~(begin
(use-modules (gcrypt base16) (gcrypt hash) (ice-9 iconv))
(let* ((sha256sum (bytevector->base16-string
(sha256 (string->bytevector #$seed "UTF-8"))))
;; certtool.c wants a 56 byte seed for a 2048 bit key.
(key-size 2048)
(normalized-seed (string-take sha256sum 56)))
(system* #$(file-append gnutls "/bin/certtool")
"--generate-privkey"
"--key-type=rsa"
"--pkcs8"
;; Use the provable FIPS-PUB186-4 algorithm for
;; deterministic results.
"--provable"
"--password="
"--no-text"
(string-append "--bits=" (number->string key-size))
(string-append "--seed=" normalized-seed)
"--outfile" #$output))))
#:local-build? #t))
(define sha256sum
(bytevector->base16-string (hash:sha256 (string->bytevector seed "UTF-8"))))
;; certtool.c wants a 56 byte seed for a 2048 bit key.
(define size 2048)
(define normalized-seed (string-take sha256sum 56))
(computed-file (string-append seed "-signing-key.pem")
#~(system* #$(file-append gnutls "/bin/certtool")
"--generate-privkey"
"--key-type=rsa"
"--pkcs8"
;; Use the provable FIPS-PUB186-4 algorithm for
;; deterministic results.
"--provable"
"--password="
"--no-text"
(string-append "--bits=" #$(number->string size))
(string-append "--seed=" #$normalized-seed)
"--outfile" #$output)
#:local-build? #t))
(define* (make-crx signing-key package #:optional (package-output "out"))
"Create a signed \".crx\" file from the unpacked Chromium extension residing
@@ -65,22 +68,37 @@ in PACKAGE-OUTPUT of PACKAGE. The extension will be signed with SIGNING-KEY."
(define name (package-name package))
(define version (package-version package))
(computed-file
(string-append name "-" version ".crx")
(with-imported-modules '((guix build utils))
(with-imported-modules '((guix build utils))
(computed-file
(string-append name "-" version ".crx")
#~(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"))
(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)
(copy-file (string-append packdir ".crx") #$output))))
#:local-build? #t))
(let ((chromium #$(file-append ungoogled-chromium "/bin/chromium"))
(xvfb #$(file-append xorg-server "/bin/Xvfb"))
(packdir "/tmp/extension"))
(mkdir-p (dirname packdir))
(copy-recursively (ungexp package package-output) packdir)
(system (string-append xvfb " :1 &"))
(setenv "DISPLAY" ":1")
(sleep 2) ;give Xorg some time to initialize...
;; Chromium stores the current time in the .crx Zip archive.
;; Use a fixed timestamp for deterministic behavior.
;; FIXME (core-updates): faketime is missing an absolute reference
;; to 'date', hence the need to set PATH.
(setenv "PATH" #$(file-append coreutils "/bin"))
(invoke #$(file-append libfaketime "/bin/faketime")
"2000-01-01 00:00:00"
chromium
"--user-data-dir=/tmp/signing-profile"
(string-append "--pack-extension=" packdir)
(string-append "--pack-extension-key=" #$signing-key))
(copy-file (string-append packdir ".crx") #$output)))
#:local-build? #t)))
(define (crx->chromium-json crx version)
(define* (crx->chromium-json crx version)
"Return a derivation that creates a Chromium JSON settings file for the
extension given as CRX. VERSION is used to signify the CRX version, and
must match the version listed in the extension manifest.json."
@@ -109,47 +127,66 @@ format."
"--outder")
#:local-build? #t))
(define (file-sha256sum file)
(with-extensions (list guile-gcrypt)
#~(begin
(use-modules (gcrypt base16) (gcrypt hash))
(bytevector->base16-string (file-sha256 #$file)))))
(define (chromium-json->profile-object json signing-key)
"Return a derivation that installs JSON to the directory searched by
Chromium, using a file name (aka extension ID) derived from SIGNING-KEY."
(define der (signing-key->public-der signing-key))
(define* (make-chromium-extension pkg #:optional (pkg-output "out"))
"Create a Chromium extension from package PKG and return a package that,
when installed, will make the extension contained in PKG available as a
Chromium browser extension. PKG-OUTPUT specifies which output of PKG to use."
(let* ((name (package-name pkg))
(version (package-version pkg))
(private-key (make-signing-key name))
(public-key (signing-key->public-der private-key))
(checksum (file-sha256sum public-key))
(crx (make-crx private-key pkg pkg-output))
(json (crx->chromium-json crx version)))
(with-extensions (list guile-gcrypt)
(with-imported-modules '((guix build utils))
(computed-file
"chromium-extension"
#~(begin
(use-modules (guix build utils)
(gcrypt base16)
(gcrypt hash))
(define (base16-string->chromium-base16 str)
;; Translate STR, a hexadecimal string, to a Chromium-style
;; representation using the letters a-p (where a=0, p=15).
(define s1 "0123456789abcdef")
(define s2 "abcdefghijklmnop")
(let loop ((chars (string->list str))
(converted '()))
(if (null? chars)
(list->string (reverse converted))
(loop (cdr chars)
(cons (string-ref s2 (string-index s1 (car chars)))
converted)))))
(let* ((checksum (bytevector->base16-string (file-sha256 #$der)))
(file-name (base16-string->chromium-base16
(string-take checksum 32)))
(extension-directory (string-append #$output
"/share/chromium/extensions")))
(mkdir-p extension-directory)
(symlink #$json (string-append extension-directory "/"
file-name ".json"))))
#:local-build? #t))))
(define* (make-chromium-extension p #:optional (output "out"))
"Create a Chromium extension from package P and return a package that,
when installed, will make the extension contained in P available as a
Chromium browser extension. OUTPUT specifies which output of P to use."
(let* ((pname (package-name p))
(version (package-version p))
(signing-key (make-signing-key pname)))
(package
(inherit pkg)
(name (string-append name "-chromium"))
(inherit p)
(name (string-append pname "-chromium"))
(source #f)
(build-system trivial-build-system)
(native-inputs '())
(inputs '())
(inputs
`(("extension" ,(chromium-json->profile-object
(crx->chromium-json (make-crx signing-key p output)
version)
signing-key))))
(propagated-inputs '())
(outputs '("out"))
(build-system trivial-build-system)
(arguments
(list #:modules '((guix build utils))
#:builder
#~(begin
(use-modules (guix build utils))
(define (base16-char->chromium-base16 char)
;; Translate CHAR, a hexadecimal character, to a Chromium-style
;; representation using the letters a-p (where a=0, p=15).
(string-ref "abcdefghijklmnop"
(string-index "0123456789abcdef" char)))
(let ((file-name (string-map base16-char->chromium-base16
(string-take #$checksum 32)))
(extension-directory
(string-append #$output
"/share/chromium/extensions")))
(mkdir-p extension-directory)
(symlink #$json (string-append extension-directory "/"
file-name ".json")))))))))
'(#:modules ((guix build utils))
#:builder
(begin
(use-modules (guix build utils))
(copy-recursively (assoc-ref %build-inputs "extension")
(assoc-ref %outputs "out"))))))))
-213
View File
@@ -1,213 +0,0 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2021, 2022 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;;
;;; This module contains procedures to interact with D-Bus via the 'dbus-send'
;;; command line utility. Before using any public procedure
;;;
;;; Code:
(define-module (gnu build dbus-service)
#:use-module (ice-9 match)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-19)
#:use-module (srfi srfi-26)
#:autoload (d-bus protocol connections) (d-bus-conn?
d-bus-conn-flush
d-bus-connect
d-bus-disconnect
d-bus-session-bus-address
d-bus-system-bus-address)
#:autoload (d-bus protocol messages) (MESSAGE_TYPE_METHOD_CALL
d-bus-headers-ref
d-bus-message-body
d-bus-message-headers
d-bus-read-message
d-bus-write-message
header-PATH
header-DESTINATION
header-INTERFACE
header-MEMBER
header-SIGNATURE
make-d-bus-message)
#:export (%dbus-query-timeout
initialize-dbus-connection!
%current-dbus-connection
send-dbus
call-dbus-method
dbus-available-services
dbus-service-available?
with-retries))
(define %dbus-query-timeout 2) ;in seconds
;;; Use Fibers' sleep to enable cooperative scheduling in Shepherd >= 0.9.0,
;;; which is required at least for the Jami service.
(define sleep*
(lambda () ;delay execution
(if (resolve-module '(fibers) #f #:ensure #f)
(module-ref (resolve-interface '(fibers)) 'sleep)
(begin
(format #t "Fibers not available -- blocking 'sleep' in use~%")
sleep))))
;;;
;;; Utilities.
;;;
(define-syntax-rule (with-retries n delay body ...)
"Retry the code in BODY up to N times until it doesn't raise an exception nor
return #f, else raise an error. A delay of DELAY seconds is inserted before
each retry."
(let loop ((attempts 0))
(catch #t
(lambda ()
(let ((result (begin body ...)))
(if (not result)
(error "failed attempt" attempts)
result)))
(lambda args
(if (< attempts n)
(begin
((sleep*) delay) ;else wait and retry
(loop (+ 1 attempts)))
(error "maximum number of retry attempts reached"
body ... args))))))
;;;
;;; Low level wrappers above AC/D-Bus.
;;;
;; The active D-Bus connection (a parameter) used by the other procedures.
(define %current-dbus-connection (make-parameter #f))
(define* (initialize-dbus-connection!
#:key (address (or (d-bus-session-bus-address)
(d-bus-system-bus-address))))
"Initialize the D-Bus connection. ADDRESS should be the address of the D-Bus
session, e.g. \"unix:path=/var/run/dbus/system_bus_socket\", the default value
if ADDRESS is not provided and DBUS_SESSION_BUS_ADDRESS is not set. Return
the initialized D-Bus connection."
;; Clear current correction if already active.
(when (d-bus-conn? (%current-dbus-connection))
(d-bus-disconnect (%current-dbus-connection)))
(let ((connection (d-bus-connect address)))
(%current-dbus-connection connection) ;update connection parameter
(call-dbus-method "Hello")) ;initial handshake
(%current-dbus-connection))
(define* (send-dbus message #:key
(connection (%current-dbus-connection))
timeout)
"Send a D-Bus MESSAGE to CONNECTION and return the body of its reply. Up to
READ-RETRIES replies are read until a matching reply is found, else an error
is raised. MESSAGE is to be constructed with `make-d-bus-message'. When the
body contains a single element, it is returned directly, else the body
elements are returned as a list. TIMEOUT is a timeout value in seconds."
(let ((serial (d-bus-write-message connection message))
(start-time (current-time time-monotonic))
(timeout* (or timeout %dbus-query-timeout)))
(d-bus-conn-flush connection)
(let retry ()
(when (> (time-second (time-difference (current-time time-monotonic)
start-time))
timeout*)
(error 'dbus "fail to get reply in timeout" timeout*))
(let* ((reply (d-bus-read-message connection))
(reply-headers (d-bus-message-headers reply))
(reply-serial (d-bus-headers-ref reply-headers 'REPLY_SERIAL))
(error-name (d-bus-headers-ref reply-headers 'ERROR_NAME))
(body (d-bus-message-body reply)))
;; Validate the reply matches the message.
(when error-name
(error 'dbus "method failed with error" error-name body))
;; Some replies do not include a serial header, such as the for the
;; org.freedesktop.DBus NameAcquired one.
(if (and reply-serial (= serial reply-serial))
(match body
((x x* ..1) ;contains 2 ore more elements
body)
((x)
x) ;single element; return it directly
(#f #f))
(retry))))))
(define (argument->signature-type argument)
"Infer the D-Bus signature type from ARGUMENT."
;; XXX: avoid ..1 when using vectors due to a bug (?) in (ice-9 match).
(match argument
((? boolean?) "b")
((? string?) "s")
(#((? string?) (? string?) ...) "as")
(#(((? string?) . (? string?))
((? string?) . (? string?)) ...) "a{ss}")
(_ (error 'dbus "no rule to infer type from argument" argument))))
(define* (call-dbus-method method
#:key
(path "/org/freedesktop/DBus")
(destination "org.freedesktop.DBus")
(interface "org.freedesktop.DBus")
(connection (%current-dbus-connection))
arguments
timeout)
"Call the D-Bus method specified by METHOD, PATH, DESTINATION and INTERFACE.
The currently active D-Bus CONNECTION is used unless explicitly provided.
Method arguments may be provided via ARGUMENTS sent as the message body.
TIMEOUT limit the maximum time to allow for the reply. Return the body of the
reply."
(let ((message (make-d-bus-message
MESSAGE_TYPE_METHOD_CALL 0 #f '()
`#(,(header-PATH path)
,(header-DESTINATION destination)
,(header-INTERFACE interface)
,(header-MEMBER method)
,@(if arguments
(list (header-SIGNATURE
(string-join
(map argument->signature-type arguments)
"")))
'()))
arguments)))
(send-dbus message #:connection connection #:timeout timeout)))
;;;
;;; Higher-level, D-Bus procedures.
;;;
(define (dbus-available-services)
"Return the list of available (acquired) D-Bus services."
(let ((names (vector->list (call-dbus-method "ListNames"))))
;; Remove entries such as ":1.7".
(remove (cut string-prefix? ":" <>) names)))
(define (dbus-service-available? service)
"Predicate to check for the D-Bus SERVICE availability."
(member service (dbus-available-services)))
;; Local Variables:
;; eval: (put 'with-retries 'scheme-indent-function 2)
;; End:
+89 -360
View File
@@ -1,12 +1,11 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2014-2018, 2020-2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2014, 2015, 2016, 2017, 2018, 2020, 2021 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2016, 2017 David Craven <david@craven.ch>
;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
;;; Copyright © 2019 Guillaume Le Vaillant <glv@posteo.net>
;;; Copyright © 20192021 Tobias Geerinckx-Rice <me@tobias.gr>
;;; Copyright © 2019, 2020 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.
;;;
@@ -30,8 +29,6 @@
#:use-module (guix build bournish)
#:use-module ((guix build syscalls)
#:hide (file-system-type))
#:use-module (guix diagnostics)
#:use-module (guix i18n)
#:use-module (rnrs io ports)
#:use-module (rnrs bytevectors)
#:use-module (ice-9 match)
@@ -53,16 +50,11 @@
read-partition-uuid
read-luks-partition-uuid
cleanly-unmounted-ext2?
bind-mount
system*/tty
mount-flags->bit-mask
check-file-system
mount-file-system
swap-space->flags-bit-mask))
mount-file-system))
;;; Commentary:
;;;
@@ -71,45 +63,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,55 +161,24 @@ 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))
(define (ext2-superblock-volume-name sblock)
"Return the volume name of ext2 superblock SBLOCK as a string of at most 16
characters, or #f if SBLOCK has no volume name."
"Return the volume name of SBLOCK as a string of at most 16 characters, or
#f if SBLOCK has no volume name."
(null-terminated-latin1->string (sub-bytevector sblock 120 16)))
(define (check-ext2-file-system device force? repair)
"Return the health of an unmounted ext2 file system on DEVICE. If FORCE? is
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."
(define (check-ext2-file-system device)
"Return the health of an ext2 file system on DEVICE."
(match (status:exit-val
(apply system*/tty "e2fsck" "-v" "-C" "0"
`(,@(if force? '("-f") '())
,@(match repair
(#f '("-n"))
(#t '("-y"))
(_ '("-p")))
,device)))
(system* "e2fsck" "-v" "-p" "-C" "0" 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.
@@ -296,36 +218,6 @@ if DEVICE does not contain an linux-swap file system."
"Return the label of Linux-swap superblock SBLOCK as a string."
(null-terminated-latin1->string
(sub-bytevector sblock (+ 1024 4 4 4 16) 16)))
(define (swap-space->flags-bit-mask swap)
"Return the number suitable for the 'flags' argument of 'mount'
that corresponds to the swap-space SWAP."
(define prio-flag
(let ((p (swap-space-priority swap))
(max (ash SWAP_FLAG_PRIO_MASK (- SWAP_FLAG_PRIO_SHIFT))))
(if p
(logior SWAP_FLAG_PREFER
(ash (cond
((< p 0)
(begin (warning
(G_ "Given swap priority ~a is
negative, defaulting to 0.~%") p)
0))
((> p max)
(begin (warning
(G_ "Limiting swap priority ~a to
~a.~%")
p max)
max))
(else p))
SWAP_FLAG_PRIO_SHIFT))
0)))
(define delayed-flag
(if (swap-space-discard? swap)
SWAP_FLAG_DISCARD
0))
(logior prio-flag delayed-flag))
;;;
@@ -347,15 +239,15 @@ negative, defaulting to 0.~%") p)
(define (read-bcachefs-superblock device)
"Return the raw contents of DEVICE's bcachefs superblock as a bytevector, or #f
if DEVICE does not contain a bcachefs file system."
;; Field offsets & lengths, in bytes. There are more (and the superblock is
;; extensible) but we need only some basic information here:
;; We completely ignore the back-up superblock & any checksum errors.
;; Superblock field names, with offset & length respectively, in bytes:
;; 0 16 bch_csum
;; 16 8 version
;; 24 16 magic
;; 40 16 uuid internal: you probably don't want this one
;; 56 16 user_uuid external: user-visible one by which to mount
;; 40 16 uuid ← internal UUID, you probably don't want this
;; 56 16 user_uuid ← external UUID, the one by which to mount
;; 72 32 label
;; Assume a sane file system: ignore the back-up superblock & checksums.
;; … there are more & the superblock is extensible, but we don't care yet.
(read-superblock device 4096 104 bcachefs-superblock?))
(define (bcachefs-superblock-external-uuid sblock)
@@ -364,28 +256,19 @@ bytevector."
(sub-bytevector sblock 56 16))
(define (bcachefs-superblock-volume-name sblock)
"Return the volume name of bcachefs superblock SBLOCK as a string of at most
32 characters, or #f if SBLOCK has no volume name."
"Return the volume name of SBLOCK as a string of at most 32 characters, or
#f if SBLOCK has no volume name."
(null-terminated-latin1->string (sub-bytevector sblock 72 32)))
(define (check-bcachefs-file-system device force? repair)
"Return the health of an unmounted bcachefs file system on DEVICE. If FORCE?
is 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."
(define (check-bcachefs-file-system device)
"Return the health of a bcachefs file system on DEVICE."
(let ((ignored-bits (logior 2)) ; DEVICE was mounted read-only
(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 #\:))))))
(match (and=> status (cut logand <> (lognot ignored-bits)))
(apply system* "bcachefs" "fsck" "-p" "-v"
;; Make each multi-device member a separate argument.
(string-split device #\:)))))
(match (logand (lognot ignored-bits) status)
(0 'pass)
(1 'errors-corrected)
(_ 'fatal-error))))
@@ -416,33 +299,16 @@ if DEVICE does not contain a btrfs file system."
(sub-bytevector sblock 32 16))
(define (btrfs-superblock-volume-name sblock)
"Return the volume name of btrfs superblock SBLOCK as a string of at most 256
characters, or #f if SBLOCK has no volume name."
"Return the volume name of SBLOCK as a string of at most 256 characters, or
#f if SBLOCK has no volume name."
(null-terminated-latin1->string (sub-bytevector sblock 299 256)))
(define (check-btrfs-file-system device force? repair)
"Return the health of an unmounted btrfs file system on DEVICE. If FORCE? is
false, return 'PASS unconditionally as btrfs claims no need for off-line checks.
When FORCE? is true, do perform a real check. This is not recommended! See
@uref{https://bugzilla.redhat.com/show_bug.cgi?id=625967#c8}. If REPAIR is
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)))
(0 'pass)
(_ 'fatal-error))
'pass))
(define (check-btrfs-file-system device)
"Return the health of a btrfs file system on DEVICE."
(match (status:exit-val
(system* "btrfs" "device" "scan"))
(0 'pass)
(_ 'fatal-error)))
;;;
@@ -466,22 +332,15 @@ fix only those considered safe to repair automatically."
(sub-bytevector sblock 67 4))
(define (fat32-superblock-volume-name sblock)
"Return the volume name of fat superblock SBLOCK as a string of at most 11
characters, or #f if SBLOCK has no volume name. The volume name is a latin1
string. Trailing spaces are trimmed."
"Return the volume name of SBLOCK as a string of at most 11 characters, or
#f if SBLOCK has no volume name. The volume name is a latin1 string.
Trailing spaces are trimmed."
(string-trim-right (latin1->string (sub-bytevector sblock 71 11) (lambda (c) #f)) #\space))
(define (check-fat-file-system device force? repair)
"Return the health of an unmounted FAT file system on DEVICE. FORCE? is
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."
(define (check-fat-file-system device)
"Return the health of a fat file system on DEVICE."
(match (status:exit-val
(system*/tty "fsck.vfat" "-v"
(match repair
(#f "-n")
(_ "-a")) ;no 'safe/#t distinction
device))
(system* "fsck.vfat" "-v" "-a" device))
(0 'pass)
(1 'errors-corrected)
(_ 'fatal-error)))
@@ -506,9 +365,9 @@ using the least destructive approach."
(sub-bytevector sblock 39 4))
(define (fat16-superblock-volume-name sblock)
"Return the volume name of fat superblock SBLOCK as a string of at most 11
characters, or #f if SBLOCK has no volume name. The volume name is a latin1
string. Trailing spaces are trimmed."
"Return the volume name of SBLOCK as a string of at most 11 characters, or
#f if SBLOCK has no volume name. The volume name is a latin1 string.
Trailing spaces are trimmed."
(string-trim-right (latin1->string (sub-bytevector sblock 43 11)
(lambda (c) #f))
#\space))
@@ -567,8 +426,8 @@ SBLOCK as a bytevector. If that's not set, returns the creation time."
(sub-bytevector time 0 16))) ; strips GMT offset.
(define (iso9660-superblock-volume-name sblock)
"Return the volume name of iso9660 superblock SBLOCK as a string. The volume
name is an ASCII string. Trailing spaces are trimmed."
"Return the volume name of SBLOCK as a string. The volume name is an ASCII
string. Trailing spaces are trimmed."
;; Note: Valid characters are of the set "[0-9][A-Z]_" (ECMA-119 Appendix A)
(string-trim-right (latin1->string (sub-bytevector sblock 40 32)
(lambda (c) #f)) #\space))
@@ -599,32 +458,14 @@ if DEVICE does not contain a JFS file system."
(sub-bytevector sblock 136 16))
(define (jfs-superblock-volume-name sblock)
"Return the volume name of JFS superblock SBLOCK as a string of at most 16
characters, or #f if SBLOCK has no volume name."
"Return the volume name of SBLOCK as a string of at most 16 characters, or
#f if SBLOCK has no volume name."
(null-terminated-latin1->string (sub-bytevector sblock 152 16)))
(define (check-jfs-file-system device force? repair)
"Return the health of an unmounted JFS file system on DEVICE. If FORCE? is
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, and replay the transaction log
only if FORCE? is true. Otherwise, replay the transaction log before checking
and automatically fix found errors."
(define (check-jfs-file-system device)
"Return the health of a JFS file system on DEVICE."
(match (status:exit-val
(apply system*/tty
`("jfs_fsck" "-v"
;; The LEVEL logic is convoluted. To quote fsck/xchkdsk.c
;; (-p, -a, and -r are aliases in every way):
;; “If -f was chosen, have it override [-p] by [forcing] a
;; check regardless of the outcome after the log is
;; replayed”.
;; “If -n is specified by itself, don't replay the journal.
;; If -n is specified with [-p], replay the journal but
;; don't make any other changes”.
,@(if force? '("-f") '())
,@(match repair
(#f '("-n"))
(_ '("-p"))) ; no 'safe/#t distinction
,device)))
(system* "jfs_fsck" "-p" "-v" device))
(0 'pass)
(1 'errors-corrected)
(2 'reboot-required)
@@ -669,28 +510,18 @@ if DEVICE does not contain an F2FS file system."
16))
(define (f2fs-superblock-volume-name sblock)
"Return the volume name of F2FS superblock SBLOCK as a string of at most 512
characters, or #f if SBLOCK has no volume name."
"Return the volume name of SBLOCK as a string of at most 512 characters, or
#f if SBLOCK has no volume name."
(null-terminated-utf16->string
(sub-bytevector sblock (- (+ #x470 12) #x400) 512)
%f2fs-endianness))
(define (check-f2fs-file-system device force? repair)
"Return the health of an unmuounted F2FS file system on DEVICE. If FORCE? is
true, check the file system even if it's marked as clean. If either FORCE? or
REPAIR are true, automatically fix found errors."
;; There's no -n equivalent (--dry-run does not disable writes).
;; -y is an alias of -f. The man page is bad: read main.c.
(when (and force? (not repair))
(format (current-error-port)
"warning: forced check of F2FS ~a implies repairing any errors~%"
device))
(define (check-f2fs-file-system device)
"Return the health of a F2FS file system on DEVICE."
(match (status:exit-val
(apply system*/tty "fsck.f2fs"
`(,@(if force? '("-f") '())
,@(if repair '("-p") '("--dry-run"))
,device)))
;; 0 and -1 are the only two possibilities according to the man page.
(system* "fsck.f2fs" "-p" device))
;; 0 and -1 are the only two possibilities
;; (according to the manpage)
(0 'pass)
(_ 'fatal-error)))
@@ -768,81 +599,13 @@ if DEVICE does not contain a NTFS file system."
;; in the BOOT SECTOR like the UUID, but in the MASTER FILE TABLE, which seems
;; way harder to access.
(define (check-ntfs-file-system device force? repair)
"Return the health of an unmounted NTFS file system on DEVICE. FORCE? is
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."
(define (check-ntfs-file-system device)
"Return the health of a NTFS file system on DEVICE."
(match (status:exit-val
(system*/tty "ntfsfix"
(if repair "--clear-dirty" "--no-action")
device))
(system* "ntfsfix" device))
(0 'pass)
(_ 'fatal-error)))
;;;
;;; XFS file systems.
;;;
;; <https://git.kernel.org/pub/scm/fs/xfs/xfs-documentation.git/tree/design/XFS_Filesystem_Structure/allocation_groups.asciidoc>
(define-syntax %xfs-endianness
;; Endianness of XFS file systems.
(identifier-syntax (endianness big)))
(define (xfs-superblock? sblock)
"Return #t when SBLOCK is an XFS superblock."
(bytevector=? (sub-bytevector sblock 0 4)
(string->utf8 "XFSB")))
(define (read-xfs-superblock device)
"Return the raw contents of DEVICE's XFS superblock as a bytevector, or #f
if DEVICE does not contain an XFS file system."
(read-superblock device 0 120 xfs-superblock?))
(define (xfs-superblock-uuid sblock)
"Return the UUID of XFS superblock SBLOCK as a 16-byte bytevector."
(sub-bytevector sblock 32 16))
(define (xfs-superblock-volume-name sblock)
"Return the volume name of XFS superblock SBLOCK as a string of at most 12
characters, or #f if SBLOCK has no volume name."
(null-terminated-latin1->string (sub-bytevector sblock 108 12)))
(define (check-xfs-file-system device force? repair)
"Return the health of an unmounted XFS file system on DEVICE. If FORCE? is
false, return 'PASS unconditionally as XFS claims no need for off-line checks.
When FORCE? is true, do perform a thorough check. If REPAIR is false, do not
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)))
(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
;; can replay the log by {,un}mounting it cleanly.
(match (let ((status (xfs_repair)))
(if (and repair (eq? 2 status))
(let ((target "/replay-XFS-log"))
;; The kernel helpfully prints a Mounting…’ notice for us.
(mkdir target)
(mount device target "xfs")
(umount target)
(rmdir target)
(xfs_repair))
status))
(0 'pass)
(4 'errors-corrected)
(_ 'fatal-error))
'pass))
;;;
;;; Partition lookup.
@@ -899,10 +662,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))))))))
@@ -940,9 +699,7 @@ partition field reader that returned a value."
(partition-field-reader read-jfs-superblock
jfs-superblock-volume-name)
(partition-field-reader read-f2fs-superblock
f2fs-superblock-volume-name)
(partition-field-reader read-xfs-superblock
xfs-superblock-volume-name)))
f2fs-superblock-volume-name)))
(define %partition-uuid-readers
(list (partition-field-reader read-iso9660-superblock
@@ -964,9 +721,7 @@ partition field reader that returned a value."
(partition-field-reader read-f2fs-superblock
f2fs-superblock-uuid)
(partition-field-reader read-ntfs-superblock
ntfs-superblock-uuid)
(partition-field-reader read-xfs-superblock
xfs-superblock-uuid)))
ntfs-superblock-uuid)))
(define read-partition-label
(cut read-partition-field <> %partition-label-readers))
@@ -1060,13 +815,8 @@ containing ':/')."
(uuid-bytevector spec)
uuid->string))))
(define (check-file-system device type force? repair)
"Check an unmounted TYPE file system on DEVICE. Do nothing but warn if it is
mounted. If FORCE? is true, check even when considered unnecessary. If REPAIR
is false, try not to write to DEVICE at all. If it's #t, try to fix all errors
found. Otherwise, fix only those considered safe to repair automatically. Not
all TYPEs support all values or combinations of FORCE? and REPAIR. Don't throw
an exception in such cases but perform the nearest sane action."
(define (check-file-system device type)
"Run a file system check of TYPE on DEVICE."
(define check-procedure
(cond
((string-prefix? "ext" type) check-ext2-file-system)
@@ -1077,44 +827,36 @@ an exception in such cases but perform the nearest sane action."
((string-prefix? "f2fs" type) check-f2fs-file-system)
((string-prefix? "ntfs" type) check-ntfs-file-system)
((string-prefix? "nfs" type) (const 'pass))
((string-prefix? "xfs" type) check-xfs-file-system)
(else #f)))
(if check-procedure
(let ((mount (find (lambda (mount)
(string=? device (mount-source mount)))
(mounts))))
(if mount
(format (current-error-port)
"Refusing to check ~a file system already mounted at ~a~%"
device (mount-point mount))
(match (check-procedure device force? repair)
('pass
#t)
('errors-corrected
(format (current-error-port)
"File system check corrected errors on ~a; continuing~%"
device))
('reboot-required
(format (current-error-port)
"File system check corrected errors on ~a; rebooting~%"
device)
(sleep 3)
(reboot))
('fatal-error
(format (current-error-port) "File system check on ~a failed~%"
device)
(match (check-procedure device)
('pass
#t)
('errors-corrected
(format (current-error-port)
"File system check corrected errors on ~a; continuing~%"
device))
('reboot-required
(format (current-error-port)
"File system check corrected errors on ~a; rebooting~%"
device)
(sleep 3)
(reboot))
('fatal-error
(format (current-error-port) "File system check on ~a failed~%"
device)
;; Spawn a REPL only if someone might interact with it.
(when (isatty? (current-input-port))
(format (current-error-port) "Spawning Bourne-like REPL.~%")
;; Spawn a REPL only if someone would be able to interact with it.
(when (isatty? (current-input-port))
(format (current-error-port) "Spawning Bourne-like REPL.~%")
;; 'current-output-port' is typically connected to /dev/klog
;; (in PID 1), but here we want to make sure we talk directly
;; to the user.
(with-output-to-file "/dev/console"
(lambda ()
(start-repl %bournish-language))))))))
;; 'current-output-port' is typically connected to /dev/klog (in
;; PID 1), but here we want to make sure we talk directly to the
;; user.
(with-output-to-file "/dev/console"
(lambda ()
(start-repl %bournish-language))))))
(format (current-error-port)
"No file system check procedure for ~a; skipping~%"
device)))
@@ -1123,12 +865,11 @@ an exception in such cases but perform the nearest sane action."
"Return the number suitable for the 'flags' argument of 'mount' that
corresponds to the symbols listed in FLAGS."
(let loop ((flags flags))
;; Note: Keep in sync with invalid-file-system-flags.
(match flags
(('read-only rest ...)
(logior MS_RDONLY (loop rest)))
(('bind-mount rest ...)
(logior MS_REC (logior MS_BIND (loop rest))))
(logior MS_BIND (loop rest)))
(('no-suid rest ...)
(logior MS_NOSUID (loop rest)))
(('no-dev rest ...)
@@ -1137,22 +878,14 @@ 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))))
(define* (mount-file-system fs #:key (root "/root")
(check? (file-system-check? fs))
(skip-check-if-clean?
(file-system-skip-check-if-clean? fs))
(repair (file-system-repair fs)))
(define* (mount-file-system fs #:key (root "/root"))
"Mount the file system described by FS, a <file-system> object, under ROOT."
(define (mount-nfs source mount-point type flags options)
@@ -1190,8 +923,8 @@ corresponds to the symbols listed in FLAGS."
(file-system-mount-flags (statfs source)))
0)))
(options (file-system-options fs)))
(when check?
(check-file-system source type (not skip-check-if-clean?) repair))
(when (file-system-check? fs)
(check-file-system source type))
(catch 'system-error
(lambda ()
@@ -1202,16 +935,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)))
+41 -72
View File
@@ -1,6 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2020-2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2020, 2023 Janneke Nieuwenhuizen <janneke@gnu.org>
;;; Copyright © 2020 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -105,7 +105,7 @@ Return the value associated with OPTION, or #f on failure."
;; TODO: Set the 'gnu.translator' extended attribute for passive translator
;; settings?
(mkdir-p (scope "servers/bus/pci")))
)
(define (passive-translator-xattr? file-name)
"Return true if FILE-NAME has an extended @code{gnu.translator} attribute
@@ -127,9 +127,6 @@ set."
(define (translated? file-name)
"Return true if a translator is installed on FILE-NAME."
;; On GNU/Hurd, 'getxattr' in glibc opens the file without O_NOTRANS, and
;; then, for "gnu.translator", it calls 'file_get_translator', resulting in
;; EOPNOTSUPP (conversely, 'showtrans' opens the file with O_NOTRANS).
(if (string-contains %host-type "linux-gnu")
(passive-translator-xattr? file-name)
(passive-translator-installed? file-name)))
@@ -183,19 +180,22 @@ set."
(mkdir-p dir))))
(define servers
'(("servers/bus/pci" ("/hurd/pci-arbiter"))
("servers/crash-dump-core" ("/hurd/crash" "--dump-core"))
'(("servers/crash-dump-core" ("/hurd/crash" "--dump-core"))
("servers/crash-kill" ("/hurd/crash" "--kill"))
("servers/crash-suspend" ("/hurd/crash" "--suspend"))
("servers/password" ("/hurd/password"))
("servers/socket/1" ("/hurd/pflocal"))
;; /servers/socket/2 and /26 are created by 'static-networking-service'.
;; XXX: Spawn pfinet without arguments on these nodes so that a DHCP
;; client has someone to talk to?
("servers/socket/2" ("/hurd/pfinet"
"--interface" "eth0"
"--address"
"10.0.2.15" ;the default QEMU guest IP
"--netmask" "255.255.255.0"
"--gateway" "10.0.2.2"
"--ipv6" "/servers/socket/16"))
("proc" ("/hurd/procfs" "--stat-mode=444"))))
(define devices
`(("dev/full" ("/hurd/null" "--full") #o666)
'(("dev/full" ("/hurd/null" "--full") #o666)
("dev/null" ("/hurd/null") #o666)
("dev/random" ("/hurd/random" "--seed-file" "/var/lib/random-seed")
#o644)
@@ -214,58 +214,31 @@ set."
;; 'fd_to_filename' in libc expects it.
("dev/fd" ("/hurd/magic" "--directory" "fd") #o555)
("dev/rumpdisk" ("/hurd/rumpdisk") #o660)
("dev/netdde" ("/hurd/netdde") #o660)
("dev/eth0" ("/hurd/devnode" "--master-device=/dev/net"
"eth0")
#o660)
("dev/eth1" ("/hurd/devnode" "--master-device=/dev/net"
"eth1")
#o660)
("dev/tty1" ("/hurd/term" "/dev/tty1" "hurdio" "/dev/vcs/1/console")
#o666)
("dev/tty2" ("/hurd/term" "/dev/tty2" "hurdio" "/dev/vcs/2/console")
#o666)
("dev/tty3" ("/hurd/term" "/dev/tty3" "hurdio" "/dev/vcs/3/console")
#o666)
;; Create a number of ttys; syslogd writes to tty12 by default.
;; FIXME: Creating /dev/tty12 leads the console client to switch to
;; tty12 when syslogd starts, which is confusing for users. Thus, do
;; not create tty12.
,@(map (lambda (n)
(let ((n (number->string n)))
`(,(string-append "dev/tty" n)
("/hurd/term" ,(string-append "/dev/tty" n)
"hurdio" ,(string-append "/dev/vcs/" n "/console"))
#o666)))
(iota 11 1))
("dev/ptyp0" ("/hurd/term" "/dev/ptyp0" "pty-master" "/dev/ttyp0")
#o666)
("dev/ptyp1" ("/hurd/term" "/dev/ptyp1" "pty-master" "/dev/ttyp1")
#o666)
("dev/ptyp2" ("/hurd/term" "/dev/ptyp2" "pty-master" "/dev/ttyp2")
#o666)
,@(append-map (lambda (n)
(let ((n (number->string n)))
`((,(string-append "dev/ptyp" n)
("/hurd/term" ,(string-append "/dev/ptyp" n)
"pty-master" ,(string-append "/dev/ttyp" n))
#o666)
(,(string-append "dev/ttyp" n)
("/hurd/term" ,(string-append "/dev/ttyp" n)
"pty-slave" ,(string-append "/dev/ptyp" n))
#o666))))
(iota 10 0))
,@(append-map (lambda (n)
(let* ((n (number->string n))
(drive (string-append "dev/wd" n))
(disk (string-append "@/dev/disk:wd" n)))
`((,drive ("/hurd/storeio" ,disk) #o600)
,@(map (lambda (p)
(let ((p (number->string p)))
`(,(string-append drive "s" p)
("/hurd/storeio"
"--store-type=typed"
,(string-append
"part:" p ":device:" disk))
#o660)))
(iota 4 1)))))
(iota 4 0))))
("dev/ttyp0" ("/hurd/term" "/dev/ttyp0" "pty-slave" "/dev/ptyp0")
#o666)
("dev/ttyp1" ("/hurd/term" "/dev/ttyp1" "pty-slave" "/dev/ptyp1")
#o666)
("dev/ttyp2" ("/hurd/term" "/dev/ttyp2" "pty-slave" "/dev/ptyp2")
#o666)))
(for-each scope-set-translator servers)
(mkdir* "dev/vcs/1")
(mkdir* "dev/vcs/2")
(mkdir* "dev/vcs/2")
(rename-file (scope "dev/console") (scope "dev/console-"))
(for-each scope-set-translator devices)
@@ -274,10 +247,6 @@ set."
(false-if-EEXIST (symlink "/dev/fd/1" (scope "dev/stdout")))
(false-if-EEXIST (symlink "/dev/fd/2" (scope "dev/stderr")))
(false-if-EEXIST (symlink "crash-dump-core" (scope "servers/crash")))
(false-if-EEXIST (symlink "/dev/rumpdisk" (scope "dev/disk")))
(false-if-EEXIST (symlink "/dev/netdde" (scope "dev/net")))
(false-if-EEXIST (symlink "/servers/socket/2" (scope "servers/socket/inet")))
(false-if-EEXIST (symlink "/servers/socket/26" (scope "servers/socket/inet6")))
;; Make sure /etc/mtab is a symlink to /proc/mounts.
(false-if-exception (delete-file (scope "etc/mtab")))
@@ -289,7 +258,7 @@ set."
"This procedure is meant to be called from an early RC script.
Install the relevant passive translators on the first boot. Then, run system
activation by using the kernel command-line options 'gnu.system' and 'gnu.load';
activation by using the kernel command-line options '--system' and '--load';
starting the Shepherd.
XXX TODO: see linux-boot.scm:boot-system.
@@ -300,28 +269,28 @@ XXX TODO: use Linux xattr/setxattr to remove (settrans in) /libexec/RUNSYSTEM
"
(display "Welcome, this is GNU's early boot Guile.\n")
(display "Use 'gnu.repl' for an initrd REPL.\n\n")
(display "Use '--repl' for an initrd REPL.\n\n")
(call-with-error-handling
(lambda ()
(let* ((args (command-line))
(system (find-long-option "gnu.system" args))
(to-load (find-long-option "gnu.load" args)))
(false-if-exception (delete-file "/hurd"))
(let ((hurd/hurd (readlink* (string-append system "/profile/hurd"))))
(symlink hurd/hurd "/hurd"))
(system (find-long-option "--system" args))
(to-load (find-long-option "--load" args)))
(format #t "Setting-up essential translators...\n")
(setenv "PATH" (string-append system "/profile/bin"))
(set-hurd-device-translators)
(false-if-exception (delete-file "/hurd"))
(let ((hurd/hurd (readlink* (string-append system "/profile/hurd"))))
(symlink hurd/hurd "/hurd"))
(format #t "Starting pager...\n")
(unless (zero? (system* "/hurd/mach-defpager"))
(format #t "FAILED...Good luck!\n"))
(cond ((member "gnu.repl" args)
(cond ((member "--repl" args)
(format #t "Starting repl...\n")
(start-repl))
(to-load
@@ -333,7 +302,7 @@ XXX TODO: use Linux xattr/setxattr to remove (settrans in) /libexec/RUNSYSTEM
(sleep 2)
(reboot))
(else
(display "no boot file passed via 'gnu.load'\n")
(display "no boot file passed via '--load'\n")
(display "entering a warm and cozy REPL\n")
(start-repl)))))
#:on-error on-error))
+27 -87
View File
@@ -1,13 +1,10 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2016 Christine Lemmer-Webber <cwebber@dustycloud.org>
;;; Copyright © 2016 Christopher Allan Webber <cwebber@dustycloud.org>
;;; Copyright © 2016, 2017 Leo Famulari <leo@famulari.name>
;;; Copyright © 2017 Marius Bakke <mbakke@fastmail.com>
;;; Copyright © 2020, 2022 Tobias Geerinckx-Rice <me@tobias.gr>
;;; Copyright © 2020 Tobias Geerinckx-Rice <me@tobias.gr>
;;; Copyright © 2020 Mathieu Othacehe <m.othacehe@gmail.com>
;;; Copyright © 2022 Pavel Shlyak <p.shlyak@pantherx.org>
;;; Copyright © 2022 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
;;; Copyright © 2023 Efraim Flashner <efraim@flashner.co.il>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -29,7 +26,6 @@
#:use-module (guix build syscalls)
#:use-module (guix build utils)
#:use-module (guix store database)
#:use-module (guix utils)
#:use-module (gnu build bootloader)
#:use-module (gnu build install)
#:use-module (gnu build linux-boot)
@@ -44,7 +40,6 @@
convert-disk-image
genimage
initialize-efi-partition
initialize-efi32-partition
initialize-root-partition
make-iso9660-image))
@@ -53,13 +48,12 @@
"Take SEXP, a tuple as returned by 'partition->gexp', and turn it into a
<partition> record."
(match sexp
((size file-system file-system-options label uuid flags)
((size file-system file-system-options label uuid)
(partition (size size)
(file-system file-system)
(file-system-options file-system-options)
(label label)
(uuid uuid)
(flags flags)))))
(uuid uuid)))))
(define (size-in-kib size)
"Convert SIZE expressed in bytes, to kilobytes and return it as a string."
@@ -67,11 +61,9 @@
(inexact->exact (ceiling (/ size 1024)))))
(define (estimate-partition-size root)
"Given the ROOT directory, evaluate and return its size. As this doesn't
take the partition metadata size into account, take a 25% margin. As this in
turn doesn't take any constant overhead into account, force a 1-MiB minimum."
(max (ash 1 20)
(* 1.25 (file-size root))))
"Given the ROOT directory, evalute and return its size. As this doesn't
take the partition metadata size into account, take a 25% margin."
(* 1.25 (file-size root)))
(define* (make-ext-image partition target root
#:key
@@ -87,10 +79,7 @@ turn doesn't take any constant overhead into account, force a 1-MiB minimum."
(journal-options "lazy_itable_init=1,lazy_journal_init=1"))
(apply invoke
`("fakeroot" "mke2fs" "-t" ,fs "-d" ,root
"-L" ,label
,@(if uuid
`("-U" ,(uuid->string uuid))
'())
"-L" ,label "-U" ,(uuid->string uuid)
"-E" ,(format #f "root_owner=~a:~a,~a"
owner-uid owner-gid journal-options)
,@fs-options
@@ -101,21 +90,16 @@ turn doesn't take any constant overhead into account, force a 1-MiB minimum."
(estimate-partition-size root)
size)))))))
(define* (make-vfat-image partition target root fs-bits)
(define* (make-vfat-image partition target root)
"Handle the creation of VFAT partition images. See 'make-partition-image'."
(let ((size (partition-size partition))
(label (partition-label partition))
(flags (partition-flags partition)))
(apply invoke "fakeroot" "mkdosfs" "-n" label "-C" target
"-F" (number->string fs-bits)
(size-in-kib
(if (eq? size 'guess)
(estimate-partition-size root)
size))
;; u-boot in particular needs the formatted block
;; size and the physical block size to be equal.
;; TODO: What about 4k blocks?
(if (member 'esp flags) (list "-S" "512") '()))
(label (partition-label partition)))
(invoke "fakeroot" "mkdosfs" "-n" label "-C" target
"-F" "16" "-S" "1024"
(size-in-kib
(if (eq? size 'guess)
(estimate-partition-size root)
size)))
(for-each (lambda (file)
(unless (member file '("." ".."))
(invoke "mcopy" "-bsp" "-i" target
@@ -123,14 +107,6 @@ turn doesn't take any constant overhead into account, force a 1-MiB minimum."
(string-append "::" file))))
(scandir root))))
(define* (make-unformatted-image partition target)
"Make an unformatted partition of a certain size."
(let ((size (partition-size partition)))
;; Create the file and then truncate it to the desired size.
(with-output-to-file target
(lambda _ (display "")))
(truncate-file target size)))
(define* (make-partition-image partition-sexp target root)
"Create and return the image of PARTITION-SEXP as TARGET. Use the given
ROOT directory to populate the image."
@@ -139,12 +115,8 @@ ROOT directory to populate the image."
(cond
((string-prefix? "ext" type)
(make-ext-image partition target root))
((or (string=? type "vfat") (string=? type "fat16"))
(make-vfat-image partition target root 16))
((string=? type "fat32")
(make-vfat-image partition target root 32))
((string=? type "unformatted")
(make-unformatted-image partition target))
((string=? type "vfat")
(make-vfat-image partition target root))
(else
(raise (condition
(&message
@@ -188,24 +160,12 @@ 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
bootcfg-location
bootloader-package
bootloader-installer
(copy-closures? #t)
(deduplicate? #t)
references-graphs
(register-closures? #t)
@@ -216,50 +176,30 @@ produced by #:references-graphs. Pass WAL-MODE? to call-with-database."
"Initialize the given ROOT directory. Use BOOTCFG and BOOTCFG-LOCATION to
install the bootloader configuration.
If COPY-CLOSURES? is true, copy all of REFERENCES-GRAPHS to the partition. If
REGISTER-CLOSURES? is true, register REFERENCES-GRAPHS in the store. If
If REGISTER-CLOSURES? is true, register REFERENCES-GRAPHS in the store. If
DEDUPLICATE? is true, then also deduplicate files common to CLOSURES and the
rest of the store when registering the closures. SYSTEM-DIRECTORY is the name
of the directory of the 'system' derivation. Pass WAL-MODE? to
register-closure."
(define root-store
(string-append root (%store-directory)))
(define tmp-store ".tmp-store")
(populate-root-file-system system-directory root)
(when copy-closures?
(populate-store references-graphs root
#:deduplicate? deduplicate?))
(populate-store references-graphs root
#:deduplicate? deduplicate?)
;; Populate /dev.
(when make-device-nodes
(make-device-nodes root))
(when register-closures?
(unless copy-closures?
;; XXX: 'register-closure' wants to palpate the things it registers, so
;; create a symlink to the store.
(rename-file root-store tmp-store)
(symlink (%store-directory) root-store))
(for-each (lambda (closure)
(register-closure root closure
#:wal-mode? wal-mode?))
references-graphs)
references-graphs))
(unless copy-closures?
(delete-file root-store)
(rename-file tmp-store root-store)))
;; There's no point installing a bootloader if we do not populate the store.
(when copy-closures?
(when bootloader-installer
(display "installing bootloader...\n")
(bootloader-installer bootloader-package #f root))
(when bootcfg
(install-boot-config bootcfg bootcfg-location root))))
(when bootloader-installer
(display "installing bootloader...\n")
(bootloader-installer bootloader-package #f root))
(when bootcfg
(install-boot-config bootcfg bootcfg-location root)))
(define* (make-iso9660-image xorriso grub-mkrescue-environment
grub bootcfg system-directory root target
+22 -61
View File
@@ -1,7 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2013-2020, 2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2016 Chris Marusich <cmmarusich@gmail.com>
;;; Copyright © 2022 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -57,24 +56,19 @@ that the fonts, background images, etc. referred to by BOOTCFG are not GC'd."
(define* (evaluate-populate-directive directive target
#:key
(default-gid 0)
(default-uid 0)
(error-on-dangling-symlink? #t))
(default-uid 0))
"Evaluate DIRECTIVE, an sexp describing a file or directory to create under
directory TARGET. DEFAULT-UID and DEFAULT-GID are the default UID and GID in
the context of the caller. If the directive matches those defaults then,
'chown' won't be run. When ERROR-ON-DANGLING-SYMLINK? is true, abort with an
error when a dangling symlink would be created."
(define target* (if (string-suffix? "/" target)
target
(string-append target "/")))
'chown' won't be run."
(let loop ((directive directive))
(catch 'system-error
(lambda ()
(match directive
(('directory name)
(mkdir-p (string-append target* name)))
(mkdir-p (string-append target name)))
(('directory name uid gid)
(let ((dir (string-append target* name)))
(let ((dir (string-append target name)))
(mkdir-p dir)
;; If called from a context without "root" permissions, "chown"
;; to root will fail. In that case, do not try to run "chown"
@@ -84,38 +78,27 @@ error when a dangling symlink would be created."
(chown dir uid gid))))
(('directory name uid gid mode)
(loop `(directory ,name ,uid ,gid))
(chmod (string-append target* name) mode))
(chmod (string-append target name) mode))
(('file name)
(call-with-output-file (string-append target* name)
(call-with-output-file (string-append target name)
(const #t)))
(('file name (? string? content))
(call-with-output-file (string-append target* name)
(call-with-output-file (string-append target name)
(lambda (port)
(display content port))))
((new '-> old)
(let ((new* (string-append target* new)))
(let try ()
(catch 'system-error
(lambda ()
(when error-on-dangling-symlink?
;; When the symbolic link points to a relative path,
;; checking if its target exists must be done relatively
;; to the link location.
(unless (if (string-prefix? "/" old)
(file-exists? old)
(with-directory-excursion (dirname new*)
(file-exists? old)))
(error (format #f "symlink `~a' points to nonexistent \
file `~a'" new* old))))
(symlink old new*))
(lambda args
;; When doing 'guix system init' on the current '/', some
;; symlinks may already exists. Override them.
(if (= EEXIST (system-error-errno args))
(begin
(delete-file new*)
(try))
(apply throw args)))))))))
(let try ()
(catch 'system-error
(lambda ()
(symlink old (string-append target new)))
(lambda args
;; When doing 'guix system init' on the current '/', some
;; symlinks may already exists. Override them.
(if (= EEXIST (system-error-errno args))
(begin
(delete-file (string-append target new))
(try))
(apply throw args))))))))
(lambda args
;; Usually we can only get here when installing to an existing root,
;; as with 'guix system init foo.scm /'.
@@ -159,10 +142,7 @@ STORE."
includes /etc, /var, /run, /bin/sh, etc., and all the symlinks to SYSTEM.
EXTRAS is a list of directives appended to the built-in directives to populate
TARGET."
;; It's expected that some symbolic link targets do not exist yet, so do not
;; error on dangling links.
(for-each (cut evaluate-populate-directive <> target
#:error-on-dangling-symlink? #f)
(for-each (cut evaluate-populate-directive <> target)
(append (directives (%store-directory)) extras))
;; Add system generation 1.
@@ -282,31 +262,12 @@ disk."
(mount "/.rw-store" (%store-directory) "" MS_MOVE)
(rmdir "/.rw-store")))
(define (umount* directory)
"Unmount DIRECTORY, but retry a few times upon EBUSY."
(let loop ((attempts 5))
(catch 'system-error
(lambda ()
(umount directory))
(lambda args
(if (and (= EBUSY (system-error-errno args))
(> attempts 0))
(begin
(sleep 1)
(loop (- attempts 1)))
(apply throw args))))))
(define (unmount-cow-store target backing-directory)
"Unmount copy-on-write store."
(let ((tmp-dir "/remove"))
(mkdir-p tmp-dir)
(mount (%store-directory) tmp-dir "" MS_MOVE)
;; We might get EBUSY at this point, possibly because of lingering
;; processes with open file descriptors. Use 'umount*' to retry upon
;; EBUSY, leaving a bit of time. See <https://issues.guix.gnu.org/59884>.
(umount* tmp-dir)
(umount tmp-dir)
(rmdir tmp-dir)
(delete-file-recursively
(string-append target backing-directory))))
-328
View File
@@ -1,328 +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 helpers used as part of the jami-service-type
;;; definition.
;;;
;;; 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 rdelim)
#:use-module (ice-9 regex)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-26)
#:export (jami-service-available?
account-fingerprint?
account-details->recutil
get-accounts
get-usernames
set-account-details
add-account
account->username
username->account
username->contacts
enable-account
disable-account
add-contact
remove-contact
set-all-moderators
set-moderator
username->all-moderators?
username->moderators))
;;;
;;; Utilities.
;;;
(define (alist->list alist)
"Flatten ALIST into a list."
(append-map (match-lambda
(() '())
((key . value)
(list key value)))
alist))
(define account-fingerprint-rx (make-regexp "[0-9A-Fa-f]{40}"))
(define (account-fingerprint? val)
"A Jami account fingerprint is 40 characters long and only contains
hexadecimal characters."
(and (string? val)
(regexp-exec account-fingerprint-rx val)))
(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"))
;;;
;;; Bindings for the Jami D-Bus API.
;;;
(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))
;;; 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
;;; concerned with.
(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")))
(define (id->account-details id)
"Retrieve the account data associated with the given account ID."
(vector->list (call-configuration-manager-method "getAccountDetails"
(list 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))))
(define (id->account id)
"Retrieve the complete account data associated with the given account ID."
(append (id->volatile-account-details id)
(id->account-details id)))
(define %username-to-id-cache #f)
(define (invalidate-username-to-id-cache!)
(set! %username-to-id-cache #f))
(define (username->id username)
"Return the first account ID corresponding to USERNAME."
(unless (assoc-ref %username-to-id-cache username)
(set! %username-to-id-cache
(append-map
(lambda (id)
(let* ((account (id->account id))
(username (assoc-ref account "Account.username"))
(registered-name (assoc-ref account
"Account.registeredName")))
`(,@(if username
(list (cons username id))
'())
,@(if registered-name
(list (cons registered-name id))
'()))))
(get-account-ids))))
(or (assoc-ref %username-to-id-cache username)
(let ((message (format #f "no 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"))
(define (id->username id)
"Return the public key fingerprint corresponding to account with ID, else #f."
(account->username (id->account id)))
(define (get-accounts)
"Return the list of all accounts, as a list of alists."
(map id->account (get-account-ids)))
(define (get-usernames)
"Return the list of the usernames associated with the present accounts."
(map account->username (get-accounts)))
(define (username->account username)
"Return the first account associated with USERNAME, else #f.
USERNAME can be either the account 40 characters public key fingerprint or a
registered username."
(find (lambda (account)
(member username
(list (assoc-ref account "Account.username")
(assoc-ref account "Account.registeredName"))))
(get-accounts)))
(define (add-account archive)
"Import the Jami account ARCHIVE and return its account ID. The archive
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"))))))
;; 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)))))
(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)))
(invalidate-username-to-id-cache!))
(define* (username->contacts username)
"Return the contacts associated with the account of USERNAME as two values;
the first one being the regular contacts and the second one the banned
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)))))
(banned? (lambda (contact)
(and=> (assoc-ref contact "banned")
(cut string=? "true" <>))))
(banned (filter banned? contacts))
(not-banned (filter (negate banned?) contacts))
(fingerprint (cut assoc-ref <> "id")))
(values (map fingerprint not-banned)
(map fingerprint banned))))
(define* (remove-contact contact username #:key ban?)
"Remove CONTACT, the 40 characters public key fingerprint of a contact, from
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?))))
(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))))
(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."
(let* ((id (username->id username))
(current-details (id->account-details id))
(updated-details (map (match-lambda
((key . value)
(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)))
(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?))))
(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))))
(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)))))
(define (set-moderator contact enabled? username)
"Set the moderator flag to ENABLED? for CONTACT, the 40 characters public
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?))))
(define (disable-account username)
"Disable the account known by USERNAME, a registered username or account
fingerprint."
(set-account-details '(("Account.enable" . "false")) username
;; 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))
(define (enable-account username)
"Enable the account known by USERNAME, a registered username or account
fingerprint."
(set-account-details '(("Account.enable" . "true")) username))
;;;
;;; Presentation procedures.
;;;
(define (.->_ text)
"Map each period character to underscore characters."
(string-map (match-lambda
(#\. #\_)
(c c))
text))
(define (account-details->recutil account-details)
"Serialize the account-details alist into a recutil string. Period
characters in the keys are normalized to underscore to meet Recutils' format
requirements."
(define (pair->recutil-property pair)
(match pair
((key . value)
(string-append (.->_ key) ": " value))))
(define sorted-account-details
;; Have the account username, display name and alias appear first, for
;; convenience.
(let ((first-items '("Account.username"
"Account.displayName"
"Account.alias")))
(append (map (cut assoc <> account-details) first-items)
(fold alist-delete account-details first-items))))
(string-join (map pair->recutil-property sorted-account-details) "\n"))
+66 -114
View File
@@ -1,9 +1,8 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2016, 2017, 20192021 Tobias Geerinckx-Rice <me@tobias.gr>
;;; Copyright © 2016, 2017, 2019, 2020 Tobias Geerinckx-Rice <me@tobias.gr>
;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
;;; Copyright © 2019 Guillaume Le Vaillant <glv@posteo.net>
;;; Copyright © 2020, 2022 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -26,7 +25,6 @@
#:autoload (system repl repl) (start-repl)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-9)
#:use-module (srfi srfi-11)
#:use-module (srfi srfi-26)
#:use-module (ice-9 match)
#:use-module (ice-9 rdelim)
@@ -46,6 +44,7 @@
make-static-device-nodes
configure-qemu-networking
device-number
boot-system))
;;; Commentary:
@@ -94,7 +93,7 @@
get-string-all)))
(define (find-long-option option arguments)
"Find OPTION among ARGUMENTS, where OPTION is something like \"gnu.load\".
"Find OPTION among ARGUMENTS, where OPTION is something like \"--load\".
Return the value associated with OPTION, or #f on failure."
(let ((opt (string-append option "=")))
(and=> (find (cut string-prefix? opt <>)
@@ -135,9 +134,14 @@ succeeds. Return nothing otherwise. The kernel logs any details to dmesg."
;; is found on the command line; our canonicalize-device-spec gives
;; up after 20 seconds. We could emulate the former by looping…
(device (canonicalize-device-spec spec))
(rdev (stat:rdev (stat device))))
(let-values (((major minor) (device-number->major+minor rdev)))
(format #f "~a:~a" major minor))))
(rdev (stat:rdev (stat device)))
;; For backwards compatibility, device numbering is a baroque affair.
;; This is the full 64-bit scheme used by glibc's <sys/sysmacros.h>.
(major (logior (ash (logand #x00000000000fff00 rdev) -8)
(ash (logand #xfffff00000000000 rdev) -32)))
(minor (logior (logand #x00000000000000ff rdev)
(ash (logand #x00000ffffff00000 rdev) -12))))
(format #f "~a:~a" major minor)))
;; Write the resume DEVICE to this magic file, using the MAJOR:MINOR device
;; numbers if possible. The kernel will immediately try to resume from it.
@@ -386,8 +390,17 @@ networking values.) Return #t if INTERFACE is up, #f otherwise."
(set-network-interface-address sock interface address)
(set-network-interface-flags sock interface (logior flags IFF_UP))
;; Hello! We used to create /etc/resolv.conf here, with "nameserver
;; 10.0.2.3\n". However, with Linux-libre 3.16, we're getting ENOSPC.
;; And since it's actually unnecessary, it's gone.
(logand (network-interface-flags sock interface) IFF_UP)))
(define (device-number major minor)
"Return the device number for the device with MAJOR and MINOR, for use as
the last argument of `mknod'."
(+ (* major 256) minor))
(define (pidof program)
"Return the PID of the first presumed instance of PROGRAM."
(let ((program (basename program)))
@@ -398,18 +411,11 @@ networking values.) Return #t if INTERFACE is up, #f otherwise."
(filter-map string->number (scandir "/proc")))))
(define* (mount-root-file-system root type
#:key volatile-root? (flags 0) options
check? skip-check-if-clean? repair)
#:key volatile-root? (flags 0) options)
"Mount the root file system of type TYPE at device ROOT. If VOLATILE-ROOT? is
true, mount ROOT read-only and make it an overlay with a writable tmpfs using
the kernel built-in overlayfs. FLAGS and OPTIONS indicates the options to use
to mount ROOT, and behave the same as for the `mount' procedure.
If CHECK? is true, first run ROOT's fsck tool (if any) non-interactively.
If SKIP-CHECK-IF-CLEAN? is true, ask fsck to return immediately if ROOT is
marked as clean. If REPAIR is true, fsck may write to ROOT to perform repairs.
If REPAIR is also 'PREEN, ask fsck to perform only those repairs that it
considers safe."
to mount ROOT, and behave the same as for the `mount' procedure."
(if volatile-root?
(begin
@@ -430,8 +436,7 @@ considers safe."
(mount "none" "/root" "overlay" 0
"lowerdir=/real-root,upperdir=/rw-root/upper,workdir=/rw-root/work"))
(begin
(when check?
(check-file-system root type (not skip-check-if-clean?) repair))
(check-file-system root type)
(mount root "/root" type flags options)))
;; Make sure /root/etc/mtab is a symlink to /proc/self/mounts.
@@ -500,12 +505,10 @@ LINUX-MODULE-DIRECTORY, then installing KEYMAP-FILE with 'loadkeys' (if
KEYMAP-FILE is true), then setting up QEMU guest networking if
QEMU-GUEST-NETWORKING? is true, calling PRE-MOUNT, mounting the file systems
specified in MOUNTS, and finally booting into the new root if any. The initrd
supports the kernel command-line options 'gnu.load' and 'gnu.repl'. It also
honors a subset of the Linux kernel command-line parameters such as
'fsck.mode', 'resume', 'rootdelay', rootflags and rootfstype.
supports kernel command-line options '--load', '--root', and '--repl'.
Mount the root file system, specified by the 'root' command-line argument, if
any.
Mount the root file system, specified by the '--root' command-line argument,
if any.
MOUNTS must be a list of <file-system> objects.
@@ -518,77 +521,54 @@ upon error."
(string=? (file-system-mount-point fs) "/"))
(define (device-string->file-system-device device-string)
;; The "root=SPEC" kernel command-line option always provides a string,
;; but the string can represent a device, an nfs-root, a UUID, or a label.
;; So check for all four.
;; The "--root=SPEC" kernel command-line option always provides a
;; string, but the string can represent a device, an nfs-root, a UUID, or a
;; label. So check for all four.
(cond ((string-prefix? "/" device-string) device-string)
((string-contains device-string ":/") device-string) ; nfs-root
((uuid device-string) => identity)
(else (file-system-label device-string))))
(display "Welcome, this is GNU's early boot Guile.\n")
(display "Use 'gnu.repl' for an initrd REPL.\n\n")
(display "Use '--repl' for an initrd REPL.\n\n")
(call-with-error-handling
(lambda ()
(mount-essential-file-systems)
(let* ((args (linux-command-line))
(to-load (find-long-option "gnu.load" args))
;; If present, root on the kernel command line takes precedence
;; over the device field of the root <file-system> record.
(root-device (and=> (find-long-option "root" args)
device-string->file-system-device))
(rootfstype (find-long-option "rootfstype" args))
(rootflags (find-long-option "rootflags" args))
(root-fs* (find root-mount-point? mounts))
(fsck.mode (find-long-option "fsck.mode" args)))
(to-load (find-long-option "--load" args))
(root-fs (find root-mount-point? mounts))
(root-fs-type (or (and=> root-fs file-system-type)
"ext4"))
(root-fs-device (and=> root-fs file-system-device))
(root-fs-flags (mount-flags->bit-mask
(or (and=> root-fs file-system-flags)
'())))
(root-options (if root-fs
(file-system-options root-fs)
#f))
;; --root takes precedence over the 'device' field of the root
;; <file-system> record.
(root-device (or (and=> (find-long-option "--root" args)
device-string->file-system-device)
root-fs-device)))
(unless (or root-fs* (and root-device rootfstype))
(error "no root file system or 'root' and 'rootfstype' parameters"))
;; If present, root on the kernel command line takes precedence over
;; the device field of the root <file-system> record; likewise for
;; the 'rootfstype' and 'rootflags' arguments.
(define root-fs
(if root-fs*
(file-system
(inherit root-fs*)
(device (or root-device (file-system-device root-fs*)))
(type (or rootfstype (file-system-type root-fs*)))
(options (or rootflags (file-system-options root-fs*))))
(file-system
(device root-device)
(mount-point "/")
(type rootfstype)
(options rootflags))))
(define (check? fs)
(match fsck.mode
("skip" #f)
("force" #t)
(_ (file-system-check? fs)))) ; assume "auto"
(define (skip-check-if-clean? fs)
(match fsck.mode
("force" #f)
(_ (file-system-skip-check-if-clean? fs))))
(define (repair fs)
(let ((arg (find-long-option "fsck.repair" args)))
(if arg
(match arg
("no" #f)
("yes" #t)
(_ 'preen))
(file-system-repair fs))))
(when (member "gnu.repl" args)
(when (member "--repl" args)
(start-repl))
(display "loading kernel modules...\n")
(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)
@@ -602,15 +582,6 @@ upon error."
(unless (configure-qemu-networking)
(display "network interface is DOWN\n")))
;; A big ugly hammer, to be used only for debugging and in desperate
;; situations where no proper device synchonisation is possible.
(let ((root-delay (and=> (find-long-option "rootdelay" args)
string->number)))
(when root-delay
(format #t "Pausing for rootdelay=~a seconds before mounting \
the root file system...\n" root-delay)
(sleep root-delay)))
;; Prepare the real root file system under /root.
(unless (file-exists? "/root")
(mkdir "/root"))
@@ -622,37 +593,18 @@ 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.
(mount-root-file-system (canonicalize-device-spec
(file-system-device root-fs))
(file-system-type root-fs)
#:volatile-root? volatile-root?
#:flags (mount-flags->bit-mask
(file-system-flags root-fs))
#:options (file-system-options root-fs)
#:check? (check? root-fs)
#:skip-check-if-clean?
(skip-check-if-clean? root-fs)
#:repair (repair root-fs))
(if root-device
(mount-root-file-system (canonicalize-device-spec root-device)
root-fs-type
#:volatile-root? volatile-root?
#:flags root-fs-flags
#:options root-options)
(mount "none" "/root" "tmpfs"))
;; Mount the specified non-root file systems.
(for-each (lambda (fs)
(mount-file-system fs
#:check? (check? fs)
#:skip-check-if-clean?
(skip-check-if-clean? fs)
#:repair (repair fs)))
;; Mount the specified file systems.
(for-each mount-file-system
(remove root-mount-point? mounts))
(setenv "EXT2FS_NO_MTAB_OK" #f)
@@ -670,7 +622,7 @@ the root file system...\n" root-delay)
(sleep 2)
(reboot))
(begin
(display "no boot file passed via 'gnu.load'\n")
(display "no boot file passed via '--load'\n")
(display "entering a warm and cozy REPL\n")
(start-repl)))))
#:on-error on-error))
+13 -91
View File
@@ -1,6 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2015 David Thompson <davet@gnu.org>
;;; Copyright © 2017-2019, 2022, 2023 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2017, 2018, 2019 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -52,7 +52,7 @@ exists."
(file-exists? "/proc/self/setgroups"))
(define %namespaces
'(cgroup mnt pid ipc uts user net))
'(mnt pid ipc uts user net))
(define (call-with-clean-exit thunk)
"Apply THUNK, but exit with a status code of 1 if it fails."
@@ -210,7 +210,6 @@ corresponds to the symbols in NAMESPACES."
;; Use the same flags as fork(3) in addition to the namespace flags.
(apply logior SIGCHLD
(map (match-lambda
('cgroup CLONE_NEWCGROUP)
('mnt CLONE_NEWNS)
('uts CLONE_NEWUTS)
('ipc CLONE_NEWIPC)
@@ -233,7 +232,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 +300,8 @@ delete it when leaving the dynamic extent of this call."
(lambda ()
(false-if-exception (delete-file-recursively tmp-dir))))))
(define (wait-child-process)
"Wait for one child process and return a pair, like 'waitpid', or return #f
if there are no child processes left."
(catch 'system-error
(lambda ()
(waitpid WAIT_ANY))
(lambda args
(if (= ECHILD (system-error-errno args))
#f
(apply throw args)))))
(define (status->exit-status status)
"Reify STATUS as an exit status."
(or (status:exit-val status)
;; See <http://www.tldp.org/LDP/abs/html/exitcodes.html#EXITCODESREF>.
(+ 128 (or (status:term-sig status)
(status:stop-sig status)))))
(define* (call-with-container mounts thunk #:key (namespaces %namespaces)
(host-uids 1) (guest-uid 0) (guest-gid 0)
(relayed-signals (list SIGINT SIGTERM))
(child-is-pid1? #t)
(process-spawned-hook (const #t)))
"Run THUNK in a new container process and return its exit status; call
PROCESS-SPAWNED-HOOK with the PID of the new process that has been spawned.
@@ -340,71 +319,27 @@ can map more than a single uid/gid.
GUEST-UID and GUEST-GID specify the first UID (respectively GID) that host
UIDs (respectively GIDs) map to in the namespace.
RELAYED-SIGNALS is the list of signals that are \"relayed\" to the container
process when caught by its parent.
When CHILD-IS-PID1? is true, and if NAMESPACES contains 'pid', then the child
process runs directly as PID 1. As such, it is responsible for (1) installing
signal handlers and (2) reaping terminated processes by calling 'waitpid'.
When CHILD-IS-PID1? is false, a new intermediate process is created instead
that takes this responsibility.
Note that if THUNK needs to load any additional Guile modules, the relevant
module files must be present in one of the mappings in MOUNTS and the Guile
load path must be adjusted as needed."
(define thunk*
(if (and (memq 'pid namespaces)
(not child-is-pid1?))
(lambda ()
;; Behave like an init process: create a sub-process that calls
;; THUNK, and wait for child processes. Furthermore, forward
;; RELAYED-SIGNALS to the child process.
(match (primitive-fork)
(0
(call-with-clean-exit thunk))
(pid
(install-signal-handlers pid)
(let loop ()
(match (wait-child-process)
((child . status)
(if (= child pid)
(primitive-exit (status->exit-status status))
(loop)))
(#f
(primitive-exit 128))))))) ;cannot happen
thunk))
(define (periodically-schedule-asyncs)
;; XXX: In Guile there's a time window where a signal-handling async could
;; be queued without being processed by the time we enter a blocking
;; syscall like waitpid(2) (info "(guile) Signals"). This terrible hack
;; ensures pending asyncs get a chance to run periodically.
(sigaction SIGALRM (lambda _ (alarm 1)))
(alarm 1))
(define (install-signal-handlers pid)
;; Install handlers that forward signals to PID.
(define (relay-signal signal)
(false-if-exception (kill pid signal)))
(periodically-schedule-asyncs)
(for-each (lambda (signal)
(sigaction signal relay-signal))
relayed-signals))
(call-with-temporary-directory
(lambda (root)
(let ((pid (run-container root mounts namespaces host-uids thunk*
(let ((pid (run-container root mounts namespaces host-uids thunk
#:guest-uid guest-uid
#:guest-gid guest-gid)))
(install-signal-handlers pid)
;; Catch SIGINT and kill the container process.
(sigaction SIGINT
(lambda (signum)
(false-if-exception
(kill pid SIGKILL))))
(process-spawned-hook pid)
(match (waitpid pid)
((_ . status) status))))))
(define (container-excursion pid thunk)
"Run THUNK as a child process within the namespaces of process PID and
return the exit status, an integer as returned by 'waitpid'."
return the exit status."
(define (namespace-file pid namespace)
(string-append "/proc/" (number->string pid) "/ns/" namespace))
@@ -432,29 +367,16 @@ return the exit status, an integer as returned by 'waitpid'."
'("user" "ipc" "uts" "net" "pid" "mnt"))
(purify-environment)
(chdir "/")
;; Per setns(2), changing the PID namespace only applies to child
;; processes, not to the process itself. Thus fork so that THUNK runs
;; in the right PID namespace, which also gives it access to /proc.
(match (primitive-fork)
(0 (call-with-clean-exit thunk))
(pid (primitive-exit
(match (waitpid pid)
((_ . status)
(or (status:exit-val status) 127)))))))))
(thunk))))
(pid
(match (waitpid pid)
((_ . status)
status)))))
(status:exit-val status))))))
(define (container-excursion* pid thunk)
"Like 'container-excursion', but return the return value of THUNK."
(match (pipe)
((in . out)
;; Make sure IN and OUT are not inherited if THUNK forks + execs.
(fcntl in F_SETFD FD_CLOEXEC)
(fcntl out F_SETFD FD_CLOEXEC)
(match (container-excursion pid
(lambda ()
(close-port in)
+5 -140
View File
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2014, 2016, 2018, 2019, 2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2014, 2016, 2018, 2019 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
;;; Copyright © 2018 Danny Milosavljevic <dannym@scratchpost.org>
;;;
@@ -28,7 +28,6 @@
#:use-module (rnrs io ports)
#:use-module (rnrs bytevectors)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-9 gnu)
#:use-module (srfi srfi-11)
#:use-module (srfi srfi-26)
#:use-module (ice-9 ftw)
@@ -51,17 +50,6 @@
load-linux-module*
load-linux-modules-from-directory
pci-devices
pci-device?
pci-device-vendor
pci-device-id
pci-device-class
pci-device-module-alias
storage-pci-device?
network-pci-device?
display-pci-device?
load-pci-device-database
current-module-debugging-port
device-module-aliases
@@ -366,13 +354,11 @@ appears in BLACK-LIST are not loaded."
(close-fdes fd)
#t)
(lambda args
;; If this module was already loaded and we're in modprobe style, ignore
;; the error.
(when fd (close-fdes fd))
(let ((errno (system-error-errno args)))
(or (and recursive? ; we're operating in modprobe style
(member errno
(list EEXIST ; already loaded
EINVAL))) ; unsupported by hardware
(apply throw args))))))))
(or (and recursive? (= EEXIST (system-error-errno args)))
(apply throw args)))))))
(define (load-linux-modules-from-directory modules directory)
"Load MODULES and their dependencies from DIRECTORY, a directory containing
@@ -441,127 +427,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:
+59 -225
View File
@@ -1,8 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2016-2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2016, 2017, 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2018 Chris Marusich <cmmarusich@gmail.com>
;;; Copyright © 2022, 2023 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;; Copyright © 2023 Bruno Victal <mirai@makinata.eu>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -22,27 +20,20 @@
(define-module (gnu build marionette)
#:use-module (srfi srfi-9)
#:use-module (srfi srfi-26)
#:use-module (srfi srfi-64)
#:use-module (srfi srfi-71)
#:use-module (rnrs io ports)
#:use-module (ice-9 match)
#:use-module (ice-9 popen)
#:use-module (ice-9 regex)
#:export (marionette?
marionette-pid
make-marionette
marionette-eval
wait-for-file
wait-for-tcp-port
wait-for-unix-socket
marionette-control
marionette-screen-text
wait-for-screen-text
%default-ocrad-arguments
%qwerty-us-keystrokes
marionette-type
system-test-runner
qemu-command))
marionette-type))
;;; Commentary:
;;;
@@ -109,14 +100,11 @@ QEMU monitor and to the guest's backdoor REPL."
"-monitor" (string-append "unix:" socket-directory "/monitor")
"-chardev" (string-append "socket,id=repl,path=" socket-directory
"/repl")
"-chardev" (string-append "socket,id=qga,server=on,wait=off,path="
socket-directory "/qemu-ga")
;; See
;; <http://www.linux-kvm.org/page/VMchannel_Requirements#Invocation>.
"-device" "virtio-serial"
"-device" "virtserialport,chardev=repl,name=org.gnu.guix.port.0"
"-device" "virtserialport,chardev=qga,name=org.qemu.guest_agent.0"))
"-device" "virtserialport,chardev=repl,name=org.gnu.guix.port.0"))
(define (accept* port)
(match (select (list port) '() (list port) timeout)
@@ -181,18 +169,7 @@ QEMU monitor and to the guest's backdoor REPL."
(($ <marionette> command pid monitor (= force repl))
(write exp repl)
(newline repl)
(with-exception-handler
(lambda (exn)
(simple-format
(current-error-port)
"error reading marionette response: ~A
remaining response: ~A\n"
exn
(get-line repl))
(raise-exception exn))
(lambda ()
(read repl))
#:unwind? #t))))
(read repl))))
(define* (wait-for-file file marionette
#:key (timeout 10) (read 'read))
@@ -201,14 +178,7 @@ FILE has not shown up after TIMEOUT seconds, raise an error."
(match (marionette-eval
`(let loop ((i ,timeout))
(cond ((file-exists? ,file)
(cons 'success
(let ((content
(call-with-input-file ,file ,read)))
(if (eof-object? content)
;; #<eof> can't be read, so convert to the
;; empty string
""
content))))
(cons 'success (call-with-input-file ,file ,read)))
((> i 0)
(sleep 1)
(loop (- i 1)))
@@ -221,38 +191,31 @@ FILE has not shown up after TIMEOUT seconds, raise an error."
(error "file didn't show up" file))))
(define* (wait-for-tcp-port port marionette
#:key
(timeout 20)
(address `(make-socket-address AF_INET
INADDR_LOOPBACK
,port)))
#:key (timeout 20))
"Wait for up to TIMEOUT seconds for PORT to accept connections in
MARIONETTE. ADDRESS must be an expression that returns a socket address,
typically a call to 'make-socket-address'. Raise an error on failure."
MARIONETTE. Raise an error on failure."
;; Note: The 'connect' loop has to run within the guest because, when we
;; forward ports to the host, connecting to the host never raises
;; ECONNREFUSED.
(match (marionette-eval
`(let* ((address ,address)
(sock (socket (sockaddr:fam address) SOCK_STREAM 0)))
(let loop ((i 0))
(catch 'system-error
(lambda ()
(connect sock address)
(close-port sock)
'success)
(lambda args
(if (< i ,timeout)
(begin
(sleep 1)
(loop (+ 1 i)))
(list 'failure address))))))
`(begin
(let ((sock (socket PF_INET SOCK_STREAM 0)))
(let loop ((i 0))
(catch 'system-error
(lambda ()
(connect sock AF_INET INADDR_LOOPBACK ,port)
(close-port sock)
'success)
(lambda args
(if (< i ,timeout)
(begin
(sleep 1)
(loop (+ 1 i)))
'failure))))))
marionette)
('success #t)
(('failure address)
(error "nobody's listening on port"
(list (inet-ntop (sockaddr:fam address) (sockaddr:addr address))
(sockaddr:port address))))))
('failure
(error "nobody's listening on port" port))))
(define* (wait-for-unix-socket file-name marionette
#:key (timeout 20))
@@ -280,8 +243,8 @@ accept connections in MARIONETTE. Raise an error on failure."
(define (marionette-control command marionette)
"Run COMMAND in the QEMU monitor of MARIONETTE. COMMAND is a string such as
\"sendkey ctrl-alt-f1\" or \"screendump foo.ppm\" (info \"(QEMU) QEMU
Monitor\")."
\"sendkey ctrl-alt-f1\" or \"screendump foo.ppm\" (info \"(qemu-doc)
pcsys_monitor\")."
(match marionette
(($ <marionette> _ _ monitor)
(display command monitor)
@@ -289,106 +252,54 @@ Monitor\")."
;; The "quit" command terminates QEMU immediately, with no output.
(unless (string=? command "quit") (wait-for-monitor-prompt monitor)))))
(define %default-ocrad-arguments
'("--invert" "--scale=10"))
(define* (marionette-screen-text marionette
#:key
(ocrad "ocrad"))
"Take a screenshot of MARIONETTE, perform optical character
recognition (OCR), and return the text read from the screen as a string. Do
this by invoking OCRAD (file name for GNU Ocrad's command)"
(define (random-file-name)
(string-append "/tmp/marionette-screenshot-"
(number->string (random (expt 2 32)) 16)
".ppm"))
(define* (invoke-ocrad-ocr image #:key (ocrad "ocrad")
(ocr-arguments %default-ocrad-arguments))
"Invoke the OCRAD command on image, and return the recognized text."
(let* ((command (string-join `(,ocrad ,@ocr-arguments ,image)))
(pipe (open-input-pipe command))
(text (get-string-all pipe)))
(unless (zero? (close-pipe pipe))
(error "'ocrad' failed" ocrad))
text))
(define* (invoke-tesseract-ocr image #:key (tesseract "tesseract")
(ocr-arguments '()))
"Invoke the TESSERACT command on IMAGE, and return the recognized text."
(let* ((output-basename (tmpnam))
(output-basename* (string-append output-basename ".txt"))
(arguments (cons* image output-basename ocr-arguments)))
(let ((image (random-file-name)))
(dynamic-wind
(const #t)
(lambda ()
(let ((exit-val (status:exit-val
(apply system* tesseract arguments))))
(unless (zero? exit-val)
(error "'tesseract' failed" tesseract))
(call-with-input-file output-basename* get-string-all)))
(lambda ()
(false-if-exception (delete-file output-basename))
(false-if-exception (delete-file output-basename*))))))
(marionette-control (string-append "screendump " image)
marionette)
(define* (marionette-screen-text marionette #:key (ocr "ocrad")
ocr-arguments)
"Take a screenshot of MARIONETTE, perform optical character
recognition (OCR), and return the text read from the screen as a string, along
the screen dump image used. Do this by invoking OCR, which should be the file
name of GNU Ocrad's@command{ocrad} or Tesseract OCR's @command{tesseract}
command. The screen dump image returned as the second value should be deleted
if it is not needed."
(define image (string-append (tmpnam) ".ppm"))
;; Use the QEMU Monitor to save an image of the screen to the host.
(marionette-control (string-append "screendump " image) marionette)
;; Process it via the OCR.
(cond
((string-contains ocr "ocrad")
(values (invoke-ocrad-ocr image
#:ocrad ocr
#:ocr-arguments
(or ocr-arguments %default-ocrad-arguments))
image))
((string-contains ocr "tesseract")
(values (invoke-tesseract-ocr image
#:tesseract ocr
#:ocr-arguments (or ocr-arguments '()))
image))
(else (error "unsupported ocr command"))))
;; Tell Ocrad to invert the image colors (make it black on white) and
;; to scale the image up, which significantly improves the quality of
;; the result. In spite of this, be aware that OCR confuses "y" and
;; "V" and sometimes erroneously introduces white space.
(let* ((pipe (open-pipe* OPEN_READ ocrad
"-i" "-s" "10" image))
(text (get-string-all pipe)))
(unless (zero? (close-pipe pipe))
(error "'ocrad' failed" ocrad))
text))
(lambda ()
(false-if-exception (delete-file image))))))
(define* (wait-for-screen-text marionette predicate
#:key
(ocr "ocrad")
ocr-arguments
(timeout 30)
pre-action
post-action)
#:key (timeout 30) (ocrad "ocrad"))
"Wait for TIMEOUT seconds or until the screen text on MARIONETTE matches
PREDICATE, whichever comes first. Raise an error when TIMEOUT is exceeded.
The error contains the recognized text along the preserved file name of the
screen dump, which is relative to the current working directory. If
PRE-ACTION is provided, it should be a thunk to call before each OCR attempt.
Likewise for POST-ACTION, except it runs at the end of a successful OCR."
PREDICATE, whichever comes first. Raise an error when TIMEOUT is exceeded."
(define start
(car (gettimeofday)))
(define end
(+ start timeout))
(let loop ((last-text #f)
(last-screendump #f))
(let loop ()
(if (> (car (gettimeofday)) end)
(let ((screendump-backup (string-drop last-screendump 5)))
;; Move the file from /tmp/fileXXXXXX.pmm to the current working
;; directory, so that it is preserved in the test derivation output.
(copy-file last-screendump screendump-backup)
(delete-file last-screendump)
(error "'wait-for-screen-text' timeout"
'ocr-text: last-text
'screendump: screendump-backup))
(let* ((_ (and (procedure? pre-action) (pre-action)))
(text screendump
(marionette-screen-text marionette
#:ocr ocr
#:ocr-arguments ocr-arguments))
(_ (and (procedure? post-action) (post-action)))
(result (predicate text)))
(cond (result
(delete-file screendump)
result)
(else
(sleep 1)
(loop text screendump)))))))
(error "'wait-for-screen-text' timeout" predicate)
(or (predicate (marionette-screen-text marionette #:ocrad ocrad))
(begin
(sleep 1)
(loop))))))
(define %qwerty-us-keystrokes
;; Maps "special" characters to their keystrokes.
@@ -410,10 +321,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")
@@ -449,79 +358,4 @@ to actual keystrokes."
(for-each (cut marionette-control <> marionette)
(string->keystroke-commands str keystrokes)))
;;;
;;; Test helper.
;;;
(define* (system-test-runner #:optional log-directory)
"Return a SRFI-64 test runner that calls 'exit' upon 'test-end'. When
LOG-DIRECTORY is specified, create log file within it."
(let ((runner (test-runner-simple)))
;; Log to a file under LOG-DIRECTORY.
(test-runner-on-group-begin! runner
(let ((on-begin (test-runner-on-group-begin runner)))
(lambda (runner suite-name count)
(when log-directory
(catch 'system-error
(lambda ()
(mkdir log-directory))
(lambda args
(unless (= (system-error-errno args) EEXIST)
(apply throw args))))
(set! test-log-to-file
(string-append log-directory "/" suite-name ".log")))
(on-begin runner suite-name count))))
;; The default behavior on 'test-end' is to only write a line if the test
;; failed. Arrange to also write a line on success.
(test-runner-on-test-end! runner
(let ((on-end (test-runner-on-test-end runner)))
(lambda (runner)
(let* ((kind (test-result-ref runner 'result-kind))
(results (test-result-alist runner))
(test-name (assq-ref results 'test-name)))
(unless (memq kind '(fail xpass))
(format (current-output-port) "~a: ~a~%"
(string-upcase (symbol->string kind))
test-name)))
(on-end runner))))
;; On 'test-end', display test results and exit with zero if and only if
;; there were no test failures.
(test-runner-on-final! runner
(lambda (runner)
(let ((success? (= (test-runner-fail-count runner) 0)))
(test-on-final-simple runner)
(when (not success?)
(let* ((log-port (test-runner-aux-value runner))
(log-file (port-filename log-port)))
(format (current-error-port)
"\nTests failed, dumping log file '~a'.\n\n"
log-file)
;; At this point LOG-PORT is not closed yet; flush it.
(force-output log-port)
;; Brute force to avoid dependency on (guix build utils) for
;; 'dump-port'.
(let ((content (call-with-input-file log-file
get-bytevector-all)))
(put-bytevector (current-error-port) content))))
(exit success?))))
runner))
(define* (qemu-command #:optional (system %host-type))
"Return the default name of the QEMU command for SYSTEM."
(let ((cpu (substring system 0
(string-index system #\-))))
(string-append "qemu-system-"
(cond
((string-match "^i[3456]86$" cpu) "i386")
((string-match "armhf" cpu) "arm")
(else cpu)))))
;;; marionette.scm ends here
+21 -88
View File
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2020-2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2020 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
;;;
;;; This file is part of GNU Guix.
@@ -47,52 +47,6 @@
;; to syslog.
#'(format (current-output-port) fmt args ...))))))
(define-syntax with-modules
(syntax-rules ()
"Dynamically load the given MODULEs at run time, making the chosen
bindings available within the lexical scope of BODY."
((_ ((module #:select (bindings ...)) rest ...) body ...)
(let* ((iface (resolve-interface 'module))
(bindings (module-ref iface 'bindings))
...)
(with-modules (rest ...) body ...)))
((_ () body ...)
(begin body ...))))
(define (wait-for-readable-fd port timeout)
"Wait until PORT has data available for reading or TIMEOUT has expired.
Return #t in the former case and #f in the latter case."
(match (resolve-module '(fibers) #f #:ensure #f) ;using Fibers?
(#f
(log "blocking on socket...~%")
(match (select (list port) '() '() timeout)
(((_) () ()) #t)
((() () ()) #f)))
(fibers
;; We're running on the Shepherd 0.9+ with Fibers. Arrange to make a
;; non-blocking wait so that other fibers can be scheduled in while we
;; wait for PORT.
(with-modules (((fibers) #:select (spawn-fiber sleep))
((fibers channels)
#:select (make-channel put-message get-message)))
;; Make PORT non-blocking.
(let ((flags (fcntl port F_GETFL)))
(fcntl port F_SETFL (logior O_NONBLOCK flags)))
(let ((channel (make-channel)))
(spawn-fiber
(lambda ()
(sleep timeout) ;suspends the fiber
(put-message channel 'timeout)))
(spawn-fiber
(lambda ()
(lookahead-u8 port) ;suspends the fiber
(put-message channel 'readable)))
(log "suspending fiber on socket...~%")
(match (get-message channel)
('readable #t)
('timeout #f)))))))
(define* (secret-service-send-secrets port secret-root
#:key (retry 60)
(handshake-timeout 120))
@@ -119,11 +73,8 @@ wait for at most HANDSHAKE-TIMEOUT seconds for handshake to complete. Return
files)))
(log "sending secrets to ~a~%" port)
(let ((sock (socket AF_INET (logior SOCK_CLOEXEC SOCK_STREAM) 0))
(addr (make-socket-address AF_INET INADDR_LOOPBACK port))
(sleep (if (resolve-module '(fibers) #f)
(module-ref (resolve-interface '(fibers)) 'sleep)
sleep)))
(let ((sock (socket AF_INET SOCK_STREAM 0))
(addr (make-socket-address AF_INET INADDR_LOOPBACK port)))
;; Connect to QEMU on the forwarded port. The 'connect' call succeeds as
;; soon as QEMU is ready, even if there's no server listening on the
;; forward port inside the guest.
@@ -142,31 +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))))
(define (delete-file* file)
"Ensure FILE does not exist."
(catch 'system-error
(lambda ()
(delete-file file))
(lambda args
(unless (= ENOENT (system-error-errno args))
(apply throw args)))))
(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 (secret-service-receive-secrets port)
"Listen to local PORT and wait for a secret service client to send secrets.
@@ -177,7 +120,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)
@@ -227,12 +170,6 @@ and #f otherwise."
(log "installing file '~a' (~a bytes)...~%"
file size)
(mkdir-p (dirname file))
;; It could be that FILE already exists, for instance
;; because it has been created by a service's activation
;; snippet (e.g., SSH host keys). Delete it.
(delete-file* file)
(call-with-output-file file
(lambda (output)
(dump port output size)
@@ -250,8 +187,4 @@ and #f otherwise."
(close-port port))
result))
;;; Local Variables:
;;; eval: (put 'with-modules 'scheme-indent-function 1)
;;; End:
;;; secret-service.scm ends here
+39 -70
View File
@@ -1,8 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2017, 2018, 2019, 2020, 2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2017, 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2020 Mathieu Othacehe <othacehe@gnu.org>
;;; Copyright © 2022 Leo Nikkilä <hello@lnikki.la>
;;; Copyright © 2022 Arun Isaac <arunisaac@systemreboot.net>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -26,14 +24,7 @@
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-26)
#:use-module (ice-9 match)
;; XXX: Lazy-bind the Shepherd to avoid a compile-time dependency.
#:autoload (shepherd service) (fork+exec-command
read-pid-file
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:
@@ -101,18 +92,21 @@
(file-exists? (file-system-mapping-source mapping)))
mappings)))))
;; XXX: Lazy-bind the Shepherd to avoid a compile-time dependency.
(module-autoload! (current-module)
'(shepherd service)
'(fork+exec-command read-pid-file exec-command
%precious-signals))
(module-autoload! (current-module)
'(shepherd system) '(unblock-signals))
(define* (read-pid-file/container pid pid-file #:key (max-delay 5))
"Read PID-FILE in the container namespaces of PID, which exists in a
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 +116,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 +123,6 @@ shepherd (PID 1)."
(mappings '())
(user #f)
(group #f)
(supplementary-groups '())
(log-file #f)
pid-file
(pid-file-timeout 5)
@@ -187,7 +158,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 +166,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 +211,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)
+500
View File
@@ -0,0 +1,500 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2016 Christopher Allan Webber <cwebber@dustycloud.org>
;;; Copyright © 2016, 2017 Leo Famulari <leo@famulari.name>
;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
;;; Copyright © 2017 Marius Bakke <mbakke@fastmail.com>
;;; Copyright © 2018 Chris Marusich <cmmarusich@gmail.com>
;;; Copyright © 2020 Tobias Geerinckx-Rice <me@tobias.gr>
;;;
;;; 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 build vm)
#:use-module (guix build utils)
#:use-module (guix build store-copy)
#:use-module (guix build syscalls)
#:use-module (guix store database)
#:use-module (gnu build bootloader)
#:use-module (gnu build linux-boot)
#:use-module (gnu build install)
#:use-module (gnu system uuid)
#:use-module (guix records)
#:use-module ((guix combinators) #:select (fold2))
#:use-module (ice-9 format)
#:use-module (ice-9 ftw)
#:use-module (ice-9 match)
#:use-module (ice-9 regex)
#:use-module (ice-9 popen)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-9)
#:use-module (srfi srfi-19)
#:use-module (srfi srfi-26)
#:export (qemu-command
load-in-linux-vm
format-partition
partition
partition?
partition-device
partition-size
partition-file-system
partition-label
partition-flags
partition-initializer
estimated-partition-size
root-partition-initializer
initialize-partition-table
initialize-hard-disk))
;;; Commentary:
;;;
;;; This module provides supporting code to run virtual machines and build
;;; virtual machine images using QEMU.
;;;
;;; Code:
(define* (qemu-command #:optional (system %host-type))
"Return the default name of the QEMU command for SYSTEM."
(let ((cpu (substring system 0
(string-index system #\-))))
(string-append "qemu-system-"
(cond
((string-match "^i[3456]86$" cpu) "i386")
((string-match "armhf" cpu) "arm")
(else cpu)))))
(define* (load-in-linux-vm builder
#:key
output
(qemu (qemu-command)) (memory-size 512)
linux initrd
make-disk-image?
single-file-output?
(disk-image-size (* 100 (expt 2 20)))
(disk-image-format "qcow2")
(references-graphs '()))
"Run BUILDER, a Scheme file, into a VM running LINUX with INITRD, and copy
the result to OUTPUT. If SINGLE-FILE-OUTPUT? is true, copy a single file from
/xchg to OUTPUT. Otherwise, copy the contents of /xchg to a new directory
OUTPUT.
When MAKE-DISK-IMAGE? is true, OUTPUT will contain a VM image of
DISK-IMAGE-SIZE bytes resulting from the execution of BUILDER, which may
access it via /dev/hda.
REFERENCES-GRAPHS can specify a list of reference-graph files as produced by
the #:references-graphs parameter of 'derivation'."
(define target-arm32?
(string-prefix? "arm-" %host-type))
(define target-aarch64?
(string-prefix? "aarch64-" %host-type))
(define target-arm?
(or target-arm32? target-aarch64?))
(define arch-specific-flags
`(;; On ARM, a machine has to be specified. Use "virt" machine to avoid
;; hardware limits imposed by other machines.
,@(if target-arm?
'("-M" "virt")
'())
;; On ARM32, if the kernel is built without LPAE support, ECAM conflicts
;; with VIRT_PCIE_MMIO causing PCI devices not to show up. Disable
;; explicitely highmem to fix it.
;; See: https://bugs.launchpad.net/qemu/+bug/1790975.
,@(if target-arm32?
'("-machine" "highmem=off")
'())
;; Only enable kvm if we see /dev/kvm exists. This allows users without
;; hardware virtualization to still use these commands. KVM support is
;; still buggy on some ARM boards. Do not use it even if available.
,@(if (and (file-exists? "/dev/kvm")
(not target-arm?))
'("-enable-kvm")
'())
;; Pass "panic=1" so that the guest dies upon error.
"-append"
,(string-append "panic=1 --load=" builder
;; The serial port name differs between emulated
;; architectures/machines.
" console="
(if target-arm? "ttyAMA0" "ttyS0"))))
(when make-disk-image?
(format #t "creating ~a image of ~,2f MiB...~%"
disk-image-format (/ disk-image-size (expt 2 20)))
(force-output)
(invoke "qemu-img" "create" "-f" disk-image-format output
(number->string disk-image-size)))
(mkdir "xchg")
(mkdir "tmp")
(match references-graphs
((graph-files ...)
;; Copy the reference-graph files under xchg/ so EXP can access it.
(map (lambda (file)
(copy-file file (string-append "xchg/" file)))
graph-files))
(_ #f))
(apply invoke qemu "-nographic" "-no-reboot"
;; CPU "max" behaves as "host" when KVM is enabled, and like a system
;; CPU with the maximum possible feature set otherwise.
"-cpu" "max"
"-m" (number->string memory-size)
"-nic" "user,model=virtio-net-pci"
"-object" "rng-random,filename=/dev/urandom,id=guixsd-vm-rng"
"-device" "virtio-rng-pci,rng=guixsd-vm-rng"
"-virtfs"
(string-append "local,id=store_dev,path="
(%store-directory)
",security_model=none,mount_tag=store")
"-virtfs"
(string-append "local,id=xchg_dev,path=xchg"
",security_model=none,mount_tag=xchg")
"-virtfs"
;; Some programs require more space in /tmp than is normally
;; available in the guest. Accommodate such programs by sharing a
;; temporary directory.
(string-append "local,id=tmp_dev,path=tmp"
",security_model=none,mount_tag=tmp")
"-kernel" linux
"-initrd" initrd
(append
(if make-disk-image?
`("-device" "virtio-blk,drive=myhd"
"-drive" ,(string-append "if=none,file=" output
",format=" disk-image-format
",id=myhd"))
'())
arch-specific-flags))
(unless (file-exists? "xchg/.exit-status")
(error "VM did not produce an exit code"))
(match (call-with-input-file "xchg/.exit-status" read)
(0 #t)
(status (error "guest VM code exited with a non-zero status" status)))
(delete-file "xchg/.exit-status")
;; When MAKE-DISK-IMAGE? is true, the image is in OUTPUT already.
(unless make-disk-image?
(if single-file-output?
(let ((graph? (lambda (name stat)
(member (basename name) references-graphs))))
(match (find-files "xchg" (negate graph?))
((result)
(copy-file result output))
(x
(error "did not find a single result file" x))))
(begin
(mkdir output)
(copy-recursively "xchg" output)))))
(define* (register-closure prefix closure
#:key
(schema (sql-schema)))
"Register CLOSURE in PREFIX, where PREFIX is the directory name of the
target store and CLOSURE is the name of a file containing a reference graph as
produced by #:references-graphs."
(let ((items (call-with-input-file closure read-reference-graph)))
(parameterize ((sql-schema schema))
(with-database (store-database-file #:prefix prefix) db
(register-items db items
#:prefix prefix
#:registration-time %epoch)))))
;;;
;;; Partitions.
;;;
(define-record-type* <partition> partition make-partition
partition?
(device partition-device (default #f))
(size partition-size)
(file-system partition-file-system (default "ext4"))
(file-system-options partition-file-system-options ;passed to 'mkfs.FS'
(default '()))
(label partition-label (default #f))
(uuid partition-uuid (default #f))
(flags partition-flags (default '()))
(initializer partition-initializer (default (const #t))))
(define (estimated-partition-size graphs)
"Return the estimated size of a partition that can store the store items
given by GRAPHS, a list of file names produced by #:references-graphs."
;; Simply add a 25% overhead.
(round (* 1.25 (closure-size graphs))))
(define* (initialize-partition-table device partitions
#:key
(label-type "msdos")
(offset (expt 2 20)))
"Create on DEVICE a partition table of type LABEL-TYPE, containing the given
PARTITIONS (a list of <partition> objects), starting at OFFSET bytes. On
success, return PARTITIONS with their 'device' field changed to reflect their
actual /dev name based on DEVICE."
(define (partition-options part offset index)
(cons* "mkpart" "primary" "ext2"
(format #f "~aB" offset)
(format #f "~aB" (+ offset (partition-size part)))
(append-map (lambda (flag)
(list "set" (number->string index)
(symbol->string flag) "on"))
(partition-flags part))))
(define (options partitions offset)
(let loop ((partitions partitions)
(offset offset)
(index 1)
(result '()))
(match partitions
(()
(concatenate (reverse result)))
((head tail ...)
(loop tail
;; Leave one sector (512B) between partitions to placate
;; Parted.
(+ offset 512 (partition-size head))
(+ 1 index)
(cons (partition-options head offset index)
result))))))
(format #t "creating partition table with ~a partitions (~a)...\n"
(length partitions)
(string-join (map (compose (cut string-append <> " MiB")
number->string
(lambda (size)
(round (/ size (expt 2. 20))))
partition-size)
partitions)
", "))
(apply invoke "parted" "--script"
device "mklabel" label-type
(options partitions offset))
;; Set the 'device' field of each partition.
(reverse
(fold2 (lambda (part result index)
(values (cons (partition
(inherit part)
(device (string-append device
(number->string index))))
result)
(+ 1 index)))
'()
1
partitions)))
(define MS_BIND 4096) ; <sys/mounts.h> again!
(define* (create-ext-file-system partition type
#:key label uuid (options '()))
"Create an ext-family file system of TYPE on PARTITION. If LABEL is true,
use that as the volume name. If UUID is true, use it as the partition UUID."
(format #t "creating ~a partition... ~@[label: ~s~] ~@[uuid: ~s~]\n"
type label (and uuid (uuid->string uuid)))
(apply invoke (string-append "mkfs." type)
"-F" partition
`(,@(if label
`("-L" ,label)
'())
,@(if uuid
`("-U" ,(uuid->string uuid))
'())
,@options)))
(define* (create-fat-file-system partition
#:key label uuid (options '()))
"Create a FAT file system on PARTITION. The number of File Allocation Tables
will be determined based on file system size. If LABEL is true, use that as the
volume name."
;; FIXME: UUID is ignored!
(format #t "creating FAT partition...\n")
(apply invoke "mkfs.fat" partition
(append (if label `("-n" ,label) '()) options)))
(define* (format-partition partition type
#:key label uuid (options '()))
"Create a file system TYPE on PARTITION. If LABEL is true, use that as the
volume name. Options is a list of command-line options passed to 'mkfs.FS'."
(cond ((string-prefix? "ext" type)
(create-ext-file-system partition type #:label label #:uuid uuid
#:options options))
((or (string-prefix? "fat" type) (string= "vfat" type))
(create-fat-file-system partition #:label label #:uuid uuid
#:options options))
(else (error "Unsupported file system."))))
(define (initialize-partition partition)
"Format PARTITION, a <partition> object with a non-#f 'device' field, mount
it, run its initializer, and unmount it."
(let ((target "/fs"))
(format-partition (partition-device partition)
(partition-file-system partition)
#:label (partition-label partition)
#:uuid (partition-uuid partition)
#:options (partition-file-system-options partition))
(mkdir-p target)
(mount (partition-device partition) target
(partition-file-system partition))
((partition-initializer partition) target)
(umount target)
partition))
(define* (root-partition-initializer #:key (closures '())
copy-closures?
(register-closures? #t)
system-directory
(deduplicate? #t)
(make-device-nodes
make-essential-device-nodes)
(extra-directives '()))
"Return a procedure to initialize a root partition.
If REGISTER-CLOSURES? is true, register all of CLOSURES in the partition's
store. If DEDUPLICATE? is true, then also deduplicate files common to
CLOSURES and the rest of the store when registering the closures. If
COPY-CLOSURES? is true, copy all of CLOSURES to the partition.
SYSTEM-DIRECTORY is the name of the directory of the 'system' derivation.
EXTRA-DIRECTIVES is an optional list of directives to populate the root file
system that is passed to 'populate-root-file-system'."
(lambda (target)
(define target-store
(string-append target (%store-directory)))
(when copy-closures?
;; Populate the store.
(populate-store (map (cut string-append "/xchg/" <>) closures)
target
#:deduplicate? deduplicate?))
;; Populate /dev.
(make-device-nodes target)
;; Optionally, register the inputs in the image's store.
(when register-closures?
(unless copy-closures?
;; XXX: 'register-closure' wants to palpate the things it registers, so
;; bind-mount the store on the target.
(mkdir-p target-store)
(mount (%store-directory) target-store "" MS_BIND))
(display "registering closures...\n")
(for-each (lambda (closure)
(register-closure target
(string-append "/xchg/" closure)))
closures)
(unless copy-closures?
(umount target-store)))
;; Add the non-store directories and files.
(display "populating...\n")
(populate-root-file-system system-directory target
#:extras extra-directives)
;; 'register-closure' resets timestamps and everything, so no need to do it
;; once more in that case.
(unless register-closures?
;; 'reset-timestamps' also resets file permissions; do that everywhere
;; except on /dev so that /dev/null remains writable, etc.
(for-each (lambda (directory)
(reset-timestamps (string-append target "/" directory)))
(scandir target
(match-lambda
((or "." ".." "dev") #f)
(_ #t))))
(reset-timestamps (string-append target "/dev")
#:preserve-permissions? #t))))
(define (register-bootcfg-root target bootcfg)
"On file system TARGET, register BOOTCFG as a GC root."
(let ((directory (string-append target "/var/guix/gcroots")))
(mkdir-p directory)
(symlink bootcfg (string-append directory "/bootcfg"))))
(define* (initialize-hard-disk device
#:key
bootloader-package
bootcfg
bootcfg-location
bootloader-installer
(grub-efi #f)
(partitions '()))
"Initialize DEVICE as a disk containing all the <partition> objects listed
in PARTITIONS, and using BOOTCFG as its bootloader configuration file.
Each partition is initialized by calling its 'initializer' procedure,
passing it a directory name where it is mounted."
(define (partition-bootable? partition)
"Return the first partition found with the boot flag set."
(member 'boot (partition-flags partition)))
(define (partition-esp? partition)
"Return the first EFI System Partition."
(member 'esp (partition-flags partition)))
(let* ((partitions (initialize-partition-table device partitions))
(root (find partition-bootable? partitions))
(esp (find partition-esp? partitions))
(target "/fs"))
(unless root
(error "no bootable partition specified" partitions))
(for-each initialize-partition partitions)
(display "mounting root partition...\n")
(mkdir-p target)
(mount (partition-device root) target (partition-file-system root))
(install-boot-config bootcfg bootcfg-location target)
(when bootloader-installer
(display "installing bootloader...\n")
(bootloader-installer bootloader-package device target))
(when esp
;; Mount the ESP somewhere and install GRUB UEFI image.
(let ((mount-point (string-append target "/boot/efi")))
(display "mounting EFI system partition...\n")
(mkdir-p mount-point)
(mount (partition-device esp) mount-point
(partition-file-system esp))
(display "creating EFI firmware image...")
(install-efi-loader grub-efi mount-point)
(display "done.\n")
(umount mount-point)))
;; Register BOOTCFG as a GC root.
(register-bootcfg-root target bootcfg)
(umount target)))
;;; vm.scm ends here
+134 -149
View File
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2012-2023 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2017, 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
;;; Copyright © 2018, 2019 Clément Lassieur <clement@lassieur.org>
;;; Copyright © 2020 Julien Lepiller <julien@lepiller.eu>
@@ -21,17 +21,17 @@
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (gnu ci)
#:use-module (guix build-system channel)
#:use-module (guix channels)
#:use-module (guix config)
#:autoload (guix describe) (package-channels)
#:use-module (guix memoization)
#:use-module (guix describe)
#:use-module (guix store)
#:use-module (guix grafts)
#:use-module (guix profiles)
#:use-module (guix packages)
#:autoload (guix transformations) (tunable-package? tuned-package)
#:use-module (guix channels)
#:use-module (guix config)
#:use-module (guix derivations)
#:use-module (guix build-system)
#:use-module (guix monads)
#:use-module (guix gexp)
#:use-module (guix ui)
@@ -40,14 +40,12 @@
#:use-module ((guix utils) #:select (%current-system))
#:use-module ((guix scripts system) #:select (read-operating-system))
#:use-module ((guix scripts pack)
#:select (self-contained-tarball))
#:select (lookup-compressor self-contained-tarball))
#:use-module (gnu bootloader)
#:use-module (gnu bootloader u-boot)
#:use-module (gnu compression)
#:use-module (gnu image)
#:use-module (gnu packages)
#:use-module (gnu packages gcc)
#:use-module (gnu packages gdb)
#:use-module (gnu packages base)
#:use-module (gnu packages gawk)
#:use-module (gnu packages guile)
@@ -56,7 +54,6 @@
#:use-module (gnu packages multiprecision)
#:use-module (gnu packages make-bootstrap)
#:use-module (gnu packages package-management)
#:use-module (guix platform)
#:use-module (gnu system)
#:use-module (gnu system image)
#:use-module (gnu system vm)
@@ -73,6 +70,8 @@
image->job
%core-packages
%cross-targets
channel-source->package
arguments->systems
cuirass-jobs))
@@ -86,7 +85,7 @@
(define* (derivation->job name drv
#:key
(max-silent-time 3600)
(timeout (* 5 3600)))
(timeout 3600))
"Return a Cuirass job called NAME and describing DRV.
MAX-SILENT-TIME and TIMEOUT are build options passed to the daemon when
@@ -108,9 +107,9 @@ building the derivation."
(#:timeout . ,timeout)))
(define* (package-job store job-name package system
#:key cross? target (suffix ""))
#:key cross? target)
"Return a job called JOB-NAME that builds PACKAGE on SYSTEM."
(let ((job-name (string-append job-name "." system suffix)))
(let ((job-name (string-append job-name "." system)))
(parameterize ((%graft? #f))
(let* ((drv (if cross?
(package-cross-derivation store package target system
@@ -130,7 +129,7 @@ building the derivation."
(define (package-cross-job store job-name package target system)
"Return a job called TARGET.JOB-NAME that cross-builds PACKAGE for TARGET on
SYSTEM."
(let ((name (string-append target "." job-name)))
(let ((name (string-append target "." job-name "." system)))
(package-job store name package system
#:cross? #t
#:target target)))
@@ -139,9 +138,9 @@ SYSTEM."
;; Note: Don't put the '-final' package variants because (1) that's
;; implicit, and (2) they cannot be cross-built (due to the explicit input
;; chain.)
(list gcc-10 gcc-11 gcc-12 glibc binutils gdb-minimal
(list gcc-7 gcc-8 gcc-9 gcc-10 glibc binutils
gmp mpfr mpc coreutils findutils diffutils patch sed grep
gawk gnu-gettext hello guile-2.2 guile-3.0 zlib gzip xz guix
gawk gnu-gettext hello guile-2.0 guile-2.2 zlib gzip xz
%bootstrap-binaries-tarball
%binutils-bootstrap-tarball
(%glibc-bootstrap-tarball)
@@ -149,19 +148,6 @@ SYSTEM."
%guile-bootstrap-tarball
%bootstrap-tarballs))
(define (commencement-packages system)
"Return the list of bootstrap packages from the commencement module for
SYSTEM."
;; Only include packages supported on SYSTEM. For example, the Mes
;; bootstrap graph is currently not supported on ARM so it should be
;; excluded.
(filter (lambda (obj)
(and (package? obj)
(supported-package? obj system)))
(module-map (lambda (sym var)
(variable-ref var))
(resolve-module '(gnu packages commencement)))))
(define (packages-to-cross-build target)
"Return the list of packages to cross-build for TARGET."
;; Don't cross-build the bootstrap tarballs for MinGW.
@@ -169,6 +155,17 @@ SYSTEM."
(drop-right %core-packages 6)
%core-packages))
(define %cross-targets
'("mips64el-linux-gnu"
"arm-linux-gnueabihf"
"aarch64-linux-gnu"
"powerpc-linux-gnu"
"powerpc64le-linux-gnu"
"riscv64-linux-gnu"
"i586-pc-gnu" ;aka. GNU/Hurd
"i686-w64-mingw32"
"x86_64-w64-mingw32"))
(define (cross-jobs store system)
"Return a list of cross-compilation jobs for SYSTEM."
(define (from-32-to-64? target)
@@ -210,7 +207,7 @@ SYSTEM."
package target system))
(packages-to-cross-build target)))
(remove (either from-32-to-64? same? pointless?)
(targets))))
%cross-targets)))
(define* (guix-jobs store systems #:key source commit)
"Return a list of jobs for Guix itself."
@@ -253,44 +250,81 @@ 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* (store name inputs
#:key source commit system
#:allow-other-keys)
(run-with-store store
;; SOURCE can be a lowerable object such as <local-file>
;; or a file name. Adjust accordingly.
(mlet* %store-monad ((source (if (string? source)
(return source)
(lower-object source)))
(instance
-> (checkout->channel-instance
source #:commit commit)))
(channel-instances->derivation (list instance)))
#:system system)))
(lower (lambda* (name #:key system source commit
#:allow-other-keys)
(bag
(name name)
(system system)
(build build)
(arguments `(#:source ,source
#:commit ,commit))))))
(build-system (name 'channel)
(description "Turn a channel instance into a package.")
(lower lower))))
(define* (channel-source->package source #:key commit)
"Return a package for the given channel SOURCE, a lowerable object."
(package
(inherit guix)
(version (string-append (package-version guix) "+"))
(build-system channel-build-system)
(arguments `(#:source ,source
#:commit ,commit))
(inputs '())
(native-inputs '())
(propagated-inputs '())))
(define* (system-test-jobs store system
#:key source commit)
@@ -343,50 +377,29 @@ otherwise use the IMAGE name."
;; Return the name of a package's job.
package-name)
(define base-packages
(mlambda (system)
"Return the set of packages considered to be part of the base for SYSTEM."
(delete-duplicates
(append-map (match-lambda
((_ package _ ...)
(match (package-transitive-inputs package)
(((_ inputs _ ...) ...)
inputs))))
(%final-inputs system)))))
(define package->job
(lambda* (store package system #:key (suffix ""))
"Return a job for PACKAGE on SYSTEM, or #f if this combination is not
valid. Append SUFFIX to the job name."
(cond ((member package (base-packages system))
(package-job store (string-append "base." (job-name package))
package system #:suffix suffix))
((supported-package? package system)
(let ((drv (package-derivation store package system
#:graft? #f)))
(and (substitutable-derivation? drv)
(package-job store (job-name package)
package system #:suffix suffix))))
(else
#f))))
(define %x86-64-micro-architectures
;; Micro-architectures for which we build tuned variants.
'("westmere" "ivybridge" "haswell" "skylake" "skylake-avx512"))
(define (tuned-package-jobs store package system)
"Return a list of jobs for PACKAGE tuned for SYSTEM's micro-architectures."
(filter-map (lambda (micro-architecture)
(define suffix
(string-append "." micro-architecture))
(package->job store
(tuned-package package micro-architecture)
system
#:suffix suffix))
(match system
("x86_64-linux" %x86-64-micro-architectures)
(_ '()))))
(let ((base-packages
(delete-duplicates
(append-map (match-lambda
((_ package _ ...)
(match (package-transitive-inputs package)
(((_ inputs _ ...) ...)
inputs))))
(%final-inputs)))))
(lambda (store package system)
"Return a job for PACKAGE on SYSTEM, or #f if this combination is not
valid."
(cond ((member package base-packages)
(package-job store (string-append "base." (job-name package))
package system))
((supported-package? package system)
(let ((drv (package-derivation store package system
#:graft? #f)))
(and (substitutable-derivation? drv)
(package-job store (job-name package)
package system))))
(else
#f)))))
(define (all-packages)
"Return the list of packages to build."
@@ -421,43 +434,19 @@ valid. Append SUFFIX to the job name."
(map channel-url channels)))
arguments))
(define (manifests->jobs store manifests systems)
"Return the list of jobs for the entries in MANIFESTS, a list of file
names, for each one of SYSTEMS."
(define (manifests->packages store manifests)
"Return the list of packages found in MANIFESTS."
(define (load-manifest manifest)
(save-module-excursion
(lambda ()
(set-current-module (make-user-module '((guix profiles) (gnu))))
(primitive-load manifest))))
(define (manifest-entry-job-name entry)
(string-append (manifest-entry-name entry) "-"
(manifest-entry-version entry)))
(define (manifest-entry->job entry system)
(let* ((obj (manifest-entry-item entry))
(drv (parameterize ((%graft? #f))
(run-with-store store
(lower-object obj system)
#:system system)))
(max-silent-time (or (and (package? obj)
(assoc-ref (package-properties obj)
'max-silent-time))
3600))
(timeout (or (and (package? obj)
(assoc-ref (package-properties obj) 'timeout))
(* 5 3600))))
(derivation->job (manifest-entry-job-name entry) drv
#:max-silent-time max-silent-time
#:timeout timeout)))
(let ((entries (delete-duplicates
(append-map (compose manifest-entries load-manifest)
manifests)
manifest-entry=?)))
(append-map (lambda (system)
(map (cut manifest-entry->job <> system) entries))
systems)))
(delete-duplicates!
(map manifest-entry-item
(append-map (compose manifest-entries
load-manifest)
manifests))))
(define (arguments->systems arguments)
"Return the systems list from ARGUMENTS."
@@ -508,16 +497,10 @@ names, for each one of SYSTEMS."
('all
;; Build everything, including replacements.
(let ((all (all-packages))
(jobs (lambda (package)
(match (package->job store package system)
(#f '())
(main-job
(cons main-job
(if (tunable-package? package)
(tuned-package-jobs store package system)
'())))))))
(job (lambda (package)
(package->job store package system))))
(append
(append-map jobs all)
(filter-map job all)
(cross-jobs store system))))
('core
;; Build core packages only.
@@ -525,7 +508,7 @@ names, for each one of SYSTEMS."
(map (lambda (package)
(package-job store (job-name package)
package system))
(append (commencement-packages system) %core-packages))
%core-packages)
(cross-jobs store system)))
('guix
;; Build Guix modules only.
@@ -539,9 +522,7 @@ names, for each one of SYSTEMS."
hello system))))
('images
;; Build Guix System images only.
(image-jobs store system
#:source source
#:commit commit))
(image-jobs store system))
('system-tests
;; Build Guix System tests only.
(system-test-jobs store system
@@ -578,8 +559,12 @@ names, for each one of SYSTEMS."
packages)))
(('manifests . rest)
;; Build packages in the list of manifests.
(let ((manifests (arguments->manifests rest channels)))
(manifests->jobs store manifests systems)))
(let* ((manifests (arguments->manifests rest channels))
(packages (manifests->packages store manifests)))
(map (lambda (package)
(package-job store (job-name package)
package system))
packages)))
(else
(error "unknown subset" subset))))
systems)))

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