forked from tribes/guix
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| aa34d4d28d | |||
| 6110751b53 | |||
| a8509d8d43 | |||
| 0961807915 |
+26
-60
@@ -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))))
|
||||
|
||||
@@ -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
|
||||
@@ -1,3 +0,0 @@
|
||||
*.scm diff=scheme
|
||||
*.scm.in diff=scheme
|
||||
*.texi diff=texinfo
|
||||
@@ -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
@@ -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"))))
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
((debbugs-host . "debbugs.gnu.org")
|
||||
(patch-email-address . "guix-patches@gnu.org")
|
||||
(mumi-host . "issues.guix.gnu.org"))
|
||||
@@ -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
@@ -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
|
||||
Mozilla’s 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 project’s 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
@@ -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
|
||||
|
||||
|
||||
@@ -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’
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
@@ -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))
|
||||
|
||||
@@ -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)))
|
||||
@@ -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))))
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
File diff suppressed because it is too large
Load Diff
+2837
-14357
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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/
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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))))))
|
||||
@@ -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
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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 © 2019–2020, 2022 Tobias Geerinckx-Rice <me@tobias.gr>
|
||||
# Copyright © 2019, 2020 Tobias Geerinckx-Rice <me@tobias.gr>
|
||||
# Copyright © 2020 Morgan Smith <Morgan.J.Smith@outlook.com>
|
||||
# Copyright © 2020 Simon Tournier <zimon.toutoune@gmail.com>
|
||||
# Copyright © 2020 Daniel Brooks <db48x@db48x.net>
|
||||
# Copyright © 2021 Jakub Kądziołka <kuba@kadziolka.net>
|
||||
# Copyright © 2021 Chris Marusich <cmmarusich@gmail.com>
|
||||
# Copyright © 2021, 2022, 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}"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Executable
+117
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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"
|
||||
@@ -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")")
|
||||
@@ -1,158 +0,0 @@
|
||||
-*- mode: lisp-data -*-
|
||||
|
||||
text-mode :when (bound-and-true-p git-commit-mode)
|
||||
|
||||
(add\ "gnu: Add "
|
||||
(p (with-temp-buffer
|
||||
(magit-git-wash #'magit-diff-wash-diffs
|
||||
"diff" "--staged")
|
||||
(goto-char (point-min))
|
||||
(when (re-search-forward "\\+(define-public \\(\\S-+\\)"
|
||||
nil 'noerror)
|
||||
(match-string-no-properties 1)))
|
||||
var)
|
||||
"." n n
|
||||
"* " (p (or (car (magit-staged-files)) ""))
|
||||
" (" (s var ) "): New variable.")
|
||||
|
||||
(remove\ "gnu: Remove "
|
||||
(p (with-temp-buffer
|
||||
(magit-git-wash #'magit-diff-wash-diffs
|
||||
"diff" "--staged")
|
||||
(goto-char (point-min))
|
||||
(when (re-search-forward "\\-(define-public \\(\\S-+\\)"
|
||||
nil 'noerror)
|
||||
(match-string-no-properties 1)))
|
||||
var)
|
||||
"." n n
|
||||
"* " (p (or (car (magit-staged-files)) ""))
|
||||
" (" (s var) "): Delete variable.")
|
||||
|
||||
(rename\ "gnu: "
|
||||
(p (with-temp-buffer
|
||||
(magit-git-wash #'magit-diff-wash-diffs
|
||||
"diff" "--staged")
|
||||
(beginning-of-buffer)
|
||||
(when (search-forward "-(define-public " nil 'noerror)
|
||||
(thing-at-point 'sexp 'no-properties)))
|
||||
prev-var)
|
||||
": Rename package to "
|
||||
(p (with-temp-buffer
|
||||
(magit-git-wash #'magit-diff-wash-diffs
|
||||
"diff" "--staged")
|
||||
(beginning-of-buffer)
|
||||
(when (search-forward "+(define-public " nil 'noerror)
|
||||
(thing-at-point 'sexp 'no-properties)))
|
||||
new-var)
|
||||
"." n n
|
||||
"* " (p (or (car (magit-staged-files)) "")) " (" (s prev-var) "): "
|
||||
"Define in terms of" n
|
||||
"'deprecated-package'." n
|
||||
"(" (s new-var) "): New variable, formerly known as \""
|
||||
(s prev-var) "\".")
|
||||
|
||||
(update\ "gnu: "
|
||||
(p (with-temp-buffer
|
||||
(magit-git-wash #'magit-diff-wash-diffs
|
||||
"diff" "--staged")
|
||||
(goto-char (point-min))
|
||||
(when (re-search-forward "^[ ]*(define-public \\(\\S-+\\)"
|
||||
nil 'noerror)
|
||||
(match-string-no-properties 1)))
|
||||
var)
|
||||
": Update to "
|
||||
(p (with-temp-buffer
|
||||
(magit-git-wash #'magit-diff-wash-diffs
|
||||
"diff" "--staged")
|
||||
(goto-char (point-min))
|
||||
(search-forward "name" nil 'noerror)
|
||||
(search-forward "+" nil 'noerror) ; first change
|
||||
(when (and (search-forward "version " nil 'noerror)
|
||||
(looking-at-p "\""))
|
||||
(let ((end (save-excursion (search-forward "\")"
|
||||
nil 'noerror))))
|
||||
(when end
|
||||
(forward-char)
|
||||
(buffer-substring-no-properties (point) (- end 2))))))
|
||||
version)
|
||||
"." n n
|
||||
"* " (p (or (car (magit-staged-files)) "")) " (" (s var) "): "
|
||||
"Update to " (s version) "." n
|
||||
(mapconcat (lambda (file) (concat "* " file))
|
||||
(cdr (magit-staged-files))
|
||||
"\n"))
|
||||
|
||||
(addcl\ "gnu: Add cl-"
|
||||
(p (replace-regexp-in-string
|
||||
"^cl-" "" (with-temp-buffer
|
||||
(magit-git-wash #'magit-diff-wash-diffs
|
||||
"diff" "--staged")
|
||||
(beginning-of-buffer)
|
||||
(when (search-forward "+(define-public " nil 'noerror)
|
||||
(replace-regexp-in-string
|
||||
"^sbcl-" ""
|
||||
(thing-at-point 'sexp 'no-properties)))))
|
||||
var)
|
||||
"." n n
|
||||
"* " (p (or (car (magit-staged-files)) ""))
|
||||
" (cl-" (s var)
|
||||
", ecl-" (s var)
|
||||
", sbcl-" (s var) "): New variables.")
|
||||
|
||||
(https\ "gnu: "
|
||||
(p (with-temp-buffer
|
||||
(magit-git-wash #'magit-diff-wash-diffs
|
||||
"diff" "--staged")
|
||||
(goto-char (point-min))
|
||||
(when (re-search-forward "^[ ]*(define-public \\(\\S-+\\)"
|
||||
nil 'noerror)
|
||||
(match-string-no-properties 1)))
|
||||
var)
|
||||
": Use HTTPS home page." n n
|
||||
"* " (p (or (car (magit-staged-files)) ""))
|
||||
" (" (s var) ")[home-page]: Use HTTPS."
|
||||
n
|
||||
(mapconcat (lambda (file) (concat "* " file))
|
||||
(cdr (magit-staged-files))
|
||||
"\n"))
|
||||
|
||||
(move\ "gnu: "
|
||||
(p (with-temp-buffer
|
||||
(magit-git-wash #'magit-diff-wash-diffs
|
||||
"diff" "--staged")
|
||||
(goto-char (point-min))
|
||||
(when (re-search-forward "\\-(define-public \\(\\S-+\\)"
|
||||
nil 'noerror)
|
||||
(match-string-no-properties 1)))
|
||||
var)
|
||||
": Move to ("
|
||||
(p (with-temp-buffer
|
||||
(magit-git-wash #'magit-diff-wash-diffs
|
||||
"diff" "--staged")
|
||||
(goto-char (point-min))
|
||||
(when (and
|
||||
(re-search-forward "\\+(define-public \\(\\S-+\\)"
|
||||
nil 'noerror)
|
||||
(re-search-backward "modified[ ]*\\(\\S-+\\)"
|
||||
nil 'noerror))
|
||||
(string-replace
|
||||
"\.scm" ""
|
||||
(string-replace "/" " "
|
||||
(match-string-no-properties 1)))))
|
||||
new-module)
|
||||
")." n
|
||||
n
|
||||
"* " (p (with-temp-buffer
|
||||
(magit-git-wash #'magit-diff-wash-diffs
|
||||
"diff" "--staged")
|
||||
(goto-char (point-min))
|
||||
(when (and
|
||||
(re-search-forward "\\-(define-public \\(\\S-+\\)"
|
||||
nil 'noerror)
|
||||
(re-search-backward "modified[ ]*\\(\\S-+\\)"
|
||||
nil 'noerror))
|
||||
(match-string-no-properties 1)))
|
||||
source)
|
||||
" (" (s var) "): Move from here…" n
|
||||
"* " (concat (string-replace " " "/" new-module) ".scm")
|
||||
" (" (s var) "): …to here.")
|
||||
+1
-1
@@ -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.
|
||||
@@ -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
@@ -1,5 +1,5 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2016, 2018-2020, 2022 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2016, 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
@@ -18,8 +18,7 @@
|
||||
|
||||
(use-modules (gnu tests)
|
||||
(gnu packages package-management)
|
||||
(guix monads)
|
||||
(guix store)
|
||||
((gnu ci) #:select (channel-source->package))
|
||||
((guix git-download) #:select (git-predicate))
|
||||
((guix utils) #:select (current-source-directory))
|
||||
(git)
|
||||
@@ -49,19 +48,15 @@ instance."
|
||||
;; of tests to run in the usual way:
|
||||
;;
|
||||
;; make check-system TESTS=installed-os
|
||||
(let ((guix (channel-source->package source #:commit commit)))
|
||||
(map (lambda (test)
|
||||
(system-test
|
||||
(inherit test)
|
||||
(value (mparameterize %store-monad ((current-guix-package guix))
|
||||
(system-test-value test)))))
|
||||
(match (getenv "TESTS")
|
||||
(#f
|
||||
(all-system-tests))
|
||||
((= string-tokenize (tests ...))
|
||||
(filter (lambda (test)
|
||||
(member (system-test-name test) tests))
|
||||
(all-system-tests)))))))
|
||||
(parameterize ((current-guix-package
|
||||
(channel-source->package source #:commit commit)))
|
||||
(match (getenv "TESTS")
|
||||
(#f
|
||||
(all-system-tests))
|
||||
((= string-tokenize (tests ...))
|
||||
(filter (lambda (test)
|
||||
(member (system-test-name test) tests))
|
||||
(all-system-tests))))))
|
||||
|
||||
(define (system-test->manifest-entry test)
|
||||
"Return a manifest entry for TEST, a system test."
|
||||
|
||||
@@ -1,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)))
|
||||
@@ -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)))
|
||||
'()))))
|
||||
@@ -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)
|
||||
@@ -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")
|
||||
@@ -1,84 +0,0 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2022 Ludovic Courtès <ludo@gnu.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
;;; GNU Guix is free software; you can redistribute it and/or modify it
|
||||
;;; under the terms of the GNU General Public License as published by
|
||||
;;; the Free Software Foundation; either version 3 of the License, or (at
|
||||
;;; your option) any later version.
|
||||
;;;
|
||||
;;; GNU Guix is distributed in the hope that it will be useful, but
|
||||
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;;; GNU General Public License for more details.
|
||||
;;;
|
||||
;;; You should have received a copy of the GNU General Public License
|
||||
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; This file returns a manifest containing entries to build past Guix
|
||||
;;; releases from the current Guix, as per 'guix time-machine'.
|
||||
|
||||
(use-modules (srfi srfi-9) (ice-9 match)
|
||||
(guix channels) (guix gexp)
|
||||
((guix store) #:select (%store-monad))
|
||||
((guix monads) #:select (mparameterize return))
|
||||
((guix git) #:select (%repository-cache-directory))
|
||||
((guix build utils) #:select (mkdir-p)))
|
||||
|
||||
;; Representation of the latest channels. This type exists just so we can
|
||||
;; refer to such records in a gexp.
|
||||
(define-record-type <guix-instance>
|
||||
(guix-instance channels)
|
||||
guix-instance?
|
||||
(channels guix-instance-channels))
|
||||
|
||||
(define-gexp-compiler (guix-instance-compiler (instance <guix-instance>)
|
||||
system target)
|
||||
(match instance
|
||||
(($ <guix-instance> channels)
|
||||
;; When this manifest is evaluated by Cuirass, make sure it does not
|
||||
;; fiddle with the cached checkout that Cuirass is also using since
|
||||
;; concurrent accesses are unsafe.
|
||||
(mparameterize %store-monad ((%repository-cache-directory
|
||||
(string-append (%repository-cache-directory)
|
||||
"/time-travel/" system)))
|
||||
(return (mkdir-p (%repository-cache-directory)))
|
||||
(latest-channel-derivation channels)))))
|
||||
|
||||
(define (guix-instance->manifest-entry instance)
|
||||
"Return a manifest entry for INSTANCE."
|
||||
(define (shorten commit)
|
||||
(string-take commit 7))
|
||||
|
||||
(manifest-entry
|
||||
(name "guix")
|
||||
(version (string-join (map (compose shorten channel-commit)
|
||||
(guix-instance-channels instance))
|
||||
"-"))
|
||||
(item instance)))
|
||||
|
||||
(define (commit->guix-instance commit)
|
||||
"Return a Guix instance for COMMIT."
|
||||
(guix-instance (list (channel
|
||||
(inherit %default-guix-channel)
|
||||
(commit commit)))))
|
||||
|
||||
(define %release-commits
|
||||
;; Release commits: the list of version/commit pairs.
|
||||
'(("1.3.0" . "a0178d34f582b50e9bdbb0403943129ae5b560ff")
|
||||
("1.2.0" . "a099685659b4bfa6b3218f84953cbb7ff9e88063")
|
||||
("1.1.0" . "d62c9b2671be55ae0305bebfda17b595f33797f2")
|
||||
("1.0.1" . "d68de958b60426798ed62797ff7c96c327a672ac")
|
||||
("1.0.0" . "6298c3ffd9654d3231a6f25390b056483e8f407c")
|
||||
("0.16.0" . "4a0b87f0ec5b6c2dcf82b372dd20ca7ea6acdd9c")))
|
||||
|
||||
(manifest
|
||||
(map (match-lambda
|
||||
((version . commit)
|
||||
(let ((entry (guix-instance->manifest-entry
|
||||
(commit->guix-instance commit))))
|
||||
(manifest-entry
|
||||
(inherit entry)
|
||||
(version version)))))
|
||||
%release-commits))
|
||||
+2
-2
@@ -29,7 +29,7 @@
|
||||
;;; Code:
|
||||
|
||||
(define %artwork-repository
|
||||
(let ((commit "4c7f2ce6428a63e202cd2a9474a06f68a946934d"))
|
||||
(let ((commit "2f2fe74c1078be605a6a93c2193fd6c715cebbb0"))
|
||||
(origin
|
||||
(method git-fetch)
|
||||
(uri (git-reference
|
||||
@@ -39,6 +39,6 @@
|
||||
"-checkout"))
|
||||
(sha256
|
||||
(base32
|
||||
"1rl569759q9wm1dxn7nkq3873d2k92giic7aa6jwzwr3n16prc7y")))))
|
||||
"0c8r0phvm3wgf914n2kw1461cwdjl2zbzqvzq9x7d9pwkgv7xmq7")))))
|
||||
|
||||
;;; artwork.scm ends here
|
||||
|
||||
+88
-179
@@ -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")))))))
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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
@@ -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
@@ -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)))
|
||||
|
||||
|
||||
@@ -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"))))))))
|
||||
|
||||
@@ -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
@@ -1,12 +1,11 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2014-2018, 2020-2022 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2014, 2015, 2016, 2017, 2018, 2020, 2021 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2016, 2017 David Craven <david@craven.ch>
|
||||
;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
|
||||
;;; Copyright © 2019 Guillaume Le Vaillant <glv@posteo.net>
|
||||
;;; Copyright © 2019–2021 Tobias Geerinckx-Rice <me@tobias.gr>
|
||||
;;; Copyright © 2019, 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
@@ -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
@@ -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
@@ -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))))
|
||||
|
||||
@@ -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
@@ -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, 2019–2021 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))
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
Reference in New Issue
Block a user