mirror of
https://git.savannah.gnu.org/git/guix.git
synced 2026-07-07 17:44:03 +02:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2c2631658c | |||
| 054ee2038e | |||
| e086dcfcf9 |
+1
-17
@@ -3,7 +3,6 @@
|
||||
((nil
|
||||
. ((fill-column . 78)
|
||||
(tab-width . 8)
|
||||
(sentence-end-double-space . t)
|
||||
|
||||
;; For use with 'bug-reference-prog-mode'.
|
||||
(bug-reference-url-format . "http://bugs.gnu.org/%s")
|
||||
@@ -17,21 +16,13 @@
|
||||
(eval . (put 'call-with-prompt 'scheme-indent-function 1))
|
||||
(eval . (put 'test-assert 'scheme-indent-function 1))
|
||||
(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 'guard 'scheme-indent-function 1))
|
||||
(eval . (put 'lambda* 'scheme-indent-function 1))
|
||||
(eval . (put 'substitute* 'scheme-indent-function 1))
|
||||
|
||||
;; 'modify-phases' and its keywords.
|
||||
(eval . (put 'modify-phases 'scheme-indent-function 1))
|
||||
(eval . (put 'replace 'scheme-indent-function 1))
|
||||
(eval . (put 'add-before 'scheme-indent-function 2))
|
||||
(eval . (put 'add-after 'scheme-indent-function 2))
|
||||
|
||||
(eval . (put 'modify-services 'scheme-indent-function 1))
|
||||
(eval . (put 'with-directory-excursion 'scheme-indent-function 1))
|
||||
(eval . (put 'package 'scheme-indent-function 0))
|
||||
(eval . (put 'origin 'scheme-indent-function 0))
|
||||
@@ -49,8 +40,6 @@
|
||||
(eval . (put 'with-atomic-file-output 'scheme-indent-function 1))
|
||||
(eval . (put 'call-with-compressed-output-port 'scheme-indent-function 2))
|
||||
(eval . (put 'call-with-decompressed-port 'scheme-indent-function 2))
|
||||
(eval . (put 'call-with-gzip-input-port 'scheme-indent-function 1))
|
||||
(eval . (put 'call-with-gzip-output-port 'scheme-indent-function 1))
|
||||
(eval . (put 'signature-case 'scheme-indent-function 1))
|
||||
(eval . (put 'emacs-batch-eval 'scheme-indent-function 0))
|
||||
(eval . (put 'emacs-batch-edit-file 'scheme-indent-function 1))
|
||||
@@ -59,8 +48,6 @@
|
||||
(eval . (put 'with-derivation-narinfo 'scheme-indent-function 1))
|
||||
(eval . (put 'with-derivation-substitute 'scheme-indent-function 2))
|
||||
|
||||
(eval . (put 'mlambda 'scheme-indent-function 1))
|
||||
(eval . (put 'mlambdaq 'scheme-indent-function 1))
|
||||
(eval . (put 'syntax-parameterize 'scheme-indent-function 1))
|
||||
(eval . (put 'with-monad 'scheme-indent-function 1))
|
||||
(eval . (put 'mbegin 'scheme-indent-function 1))
|
||||
@@ -71,14 +58,11 @@
|
||||
(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 'with-imported-modules 'scheme-indent-function 1))
|
||||
|
||||
(eval . (put 'call-with-container 'scheme-indent-function 1))
|
||||
(eval . (put 'container-excursion 'scheme-indent-function 1))
|
||||
(eval . (put 'eventually 'scheme-indent-function 1))
|
||||
|
||||
(eval . (put 'call-with-progress-reporter 'scheme-indent-function 1))
|
||||
|
||||
;; Recognize '~', '+', and '$', as used for gexps, as quotation symbols.
|
||||
;; This notably allows '(' in Paredit to not insert a space when the
|
||||
;; preceding symbol is one of these.
|
||||
(eval . (modify-syntax-entry ?~ "'"))
|
||||
|
||||
+83
-79
@@ -1,19 +1,9 @@
|
||||
*.eps
|
||||
*.go
|
||||
*.log
|
||||
*.pdf
|
||||
*.png
|
||||
*.tar.xz
|
||||
*.tmp
|
||||
*~
|
||||
.#*
|
||||
\#*\#
|
||||
,*
|
||||
/ABOUT-NLS
|
||||
/INSTALL
|
||||
/aclocal.m4
|
||||
/autom4te.cache
|
||||
/build-aux/ar-lib
|
||||
*.tmp
|
||||
*.go
|
||||
tmp
|
||||
*.log
|
||||
/build-aux/compile
|
||||
/build-aux/config.guess
|
||||
/build-aux/config.rpath
|
||||
@@ -24,40 +14,14 @@
|
||||
/build-aux/missing
|
||||
/build-aux/test-driver
|
||||
/build-aux/texinfo.tex
|
||||
/config.status
|
||||
/configure
|
||||
/doc/*.1
|
||||
/doc/.dirstamp
|
||||
/doc/guix.aux
|
||||
/doc/guix.cp
|
||||
/doc/guix.cps
|
||||
/doc/guix.fn
|
||||
/doc/guix.fns
|
||||
/doc/guix.html
|
||||
/doc/guix.info
|
||||
/doc/guix.info-[0-9]
|
||||
/doc/guix.ky
|
||||
/doc/guix.pg
|
||||
/doc/guix.toc
|
||||
/doc/guix.t2p
|
||||
/doc/guix.tp
|
||||
/doc/guix.vr
|
||||
/doc/guix.vrs
|
||||
/doc/os-config-bare-bones.texi
|
||||
/doc/os-config-desktop.texi
|
||||
/doc/stamp-vti
|
||||
/doc/version.texi
|
||||
/etc/guix-daemon.conf
|
||||
/etc/guix-daemon.service
|
||||
/etc/guix-publish.conf
|
||||
/etc/guix-publish.service
|
||||
/guix-daemon
|
||||
/guix-register
|
||||
/guix/config.scm
|
||||
/libformat.a
|
||||
/libstore.a
|
||||
/libutil.a
|
||||
/m4/*
|
||||
Makefile.in
|
||||
Makefile
|
||||
/autom4te.cache
|
||||
config.cache
|
||||
/aclocal.m4
|
||||
/config.status
|
||||
/ABOUT-NLS
|
||||
/m4/ChangeLog
|
||||
/m4/gettext.m4
|
||||
/m4/iconv.m4
|
||||
@@ -67,20 +31,6 @@
|
||||
/m4/nls.m4
|
||||
/m4/po.m4
|
||||
/m4/progtest.m4
|
||||
/nix-setuid-helper
|
||||
/nix/AUTHORS
|
||||
/nix/COPYING
|
||||
/nix/config.h
|
||||
/nix/config.h.in
|
||||
/nix/nix-daemon/nix-daemon.cc
|
||||
/nix/nix-setuid-helper/nix-setuid-helper.cc
|
||||
/nix/scripts/guix-authenticate
|
||||
/nix/scripts/list-runtime-roots
|
||||
/nix/scripts/offload
|
||||
/nix/scripts/substitute
|
||||
/po/guix/*.gmo
|
||||
/po/guix/*.insert-header
|
||||
/po/guix/*.mo
|
||||
/po/guix/ChangeLog
|
||||
/po/guix/Makefile.in.in
|
||||
/po/guix/Makevars.template
|
||||
@@ -89,15 +39,15 @@
|
||||
/po/guix/boldquot.sed
|
||||
/po/guix/en@boldquot.*
|
||||
/po/guix/en@quot.*
|
||||
/po/guix/guix.pot
|
||||
/po/guix/insert-header.sin
|
||||
/po/guix/*.insert-header
|
||||
/po/guix/quot.sed
|
||||
/po/guix/remove-potcdate.sed
|
||||
/po/guix/remove-potcdate.sin
|
||||
/po/guix/stamp-po
|
||||
/po/packages/*.gmo
|
||||
/po/packages/*.insert-header
|
||||
/po/packages/*.mo
|
||||
/po/guix/guix.pot
|
||||
/po/guix/*.mo
|
||||
/po/guix/*.gmo
|
||||
/po/packages/ChangeLog
|
||||
/po/packages/Makefile.in.in
|
||||
/po/packages/Makevars.template
|
||||
@@ -106,26 +56,80 @@
|
||||
/po/packages/boldquot.sed
|
||||
/po/packages/en@boldquot.*
|
||||
/po/packages/en@quot.*
|
||||
/po/packages/guix-packages.pot
|
||||
/po/packages/insert-header.sin
|
||||
/po/packages/*.insert-header
|
||||
/po/packages/quot.sed
|
||||
/po/packages/remove-potcdate.sed
|
||||
/po/packages/remove-potcdate.sin
|
||||
/po/packages/stamp-po
|
||||
/pre-inst-env
|
||||
/scripts/guix
|
||||
/test-env
|
||||
/test-tmp
|
||||
/po/packages/guix-packages.pot
|
||||
/po/packages/*.mo
|
||||
/po/packages/*.gmo
|
||||
/tests/*.trs
|
||||
/INSTALL
|
||||
/m4/*
|
||||
/pre-inst-env
|
||||
/doc/.dirstamp
|
||||
/doc/guix.info
|
||||
/doc/guix.info-[0-9]
|
||||
/doc/guix.pdf
|
||||
/doc/stamp-vti
|
||||
/doc/version.texi
|
||||
/gnu/packages/bootstrap/x86_64-linux/guile-2.0.9.tar.xz
|
||||
/gnu/packages/bootstrap/i686-linux/guile-2.0.9.tar.xz
|
||||
/gnu/packages/bootstrap/armhf-linux/guile-2.0.11.tar.xz
|
||||
/gnu/packages/bootstrap/mips64el-linux/guile-2.0.9.tar.xz
|
||||
/guix/config.scm
|
||||
/nix/nix-daemon/nix-daemon.cc
|
||||
/nix/config.h
|
||||
/nix/config.h.in
|
||||
stamp-h[0-9]
|
||||
/nix/AUTHORS
|
||||
/nix/COPYING
|
||||
/libformat.a
|
||||
/libstore.a
|
||||
/libutil.a
|
||||
/guix-daemon
|
||||
/test-tmp
|
||||
/nix/scripts/list-runtime-roots
|
||||
/test-env
|
||||
/nix/nix-setuid-helper/nix-setuid-helper.cc
|
||||
/scripts/guix
|
||||
/doc/guix.aux
|
||||
/doc/guix.cp
|
||||
/doc/guix.cps
|
||||
/doc/guix.fn
|
||||
/doc/guix.fns
|
||||
/doc/guix.ky
|
||||
/doc/guix.pg
|
||||
/doc/guix.toc
|
||||
/doc/guix.tp
|
||||
/doc/guix.vr
|
||||
/doc/guix.vrs
|
||||
/nix/scripts/substitute
|
||||
/doc/images/bootstrap-graph.png
|
||||
/doc/images/bootstrap-graph.eps
|
||||
/guix-register
|
||||
GPATH
|
||||
GRTAGS
|
||||
GTAGS
|
||||
Makefile
|
||||
Makefile.in
|
||||
config.cache
|
||||
stamp-h[0-9]
|
||||
tmp
|
||||
/doc/os-config-lightweight-desktop.texi
|
||||
/nix/scripts/download
|
||||
/etc/indent-code.el
|
||||
/.version
|
||||
/nix-setuid-helper
|
||||
/nix/scripts/guix-authenticate
|
||||
/nix/scripts/offload
|
||||
/emacs/Makefile.in
|
||||
/emacs/Makefile
|
||||
/emacs/guix-autoloads.el
|
||||
/emacs/guix-helper.scm
|
||||
/emacs/guix-config.el
|
||||
/doc/os-config-bare-bones.texi
|
||||
/doc/os-config-desktop.texi
|
||||
/doc/*.1
|
||||
/etc/guix-daemon.service
|
||||
/doc/images/bootstrap-graph.pdf
|
||||
/doc/images/coreutils-bag-graph.png
|
||||
/doc/images/coreutils-graph.png
|
||||
/doc/images/coreutils-size-map.eps
|
||||
/doc/images/service-graph.png
|
||||
/doc/images/service-graph.eps
|
||||
/doc/images/service-graph.pdf
|
||||
/doc/images/dmd-graph.png
|
||||
|
||||
@@ -1,73 +1,29 @@
|
||||
# This list is used to avoid multiple name/email instances of the same
|
||||
# contributors reported by "git log" and "git shortlog" commands.
|
||||
|
||||
Adriano Peluso <catonano@gmail.com>
|
||||
Al McElrath <hello@yrns.org> <hello@atonesir.com>
|
||||
Alex Sassmannshausen <alex@pompo.co> <alex.sassmannshausen@gmail.com>
|
||||
Alexander I. Grafov <grafov@gmail.com>
|
||||
Alírio Eyng <alirioeyng@gmail.com>
|
||||
Amirouche Boubekki <amirouche@hypermove.net>
|
||||
Andreas Enge <andreas@enge.fr> <andreas.enge@inria.fr>
|
||||
Andreas Enge <andreas@enge.fr> <privat@xobs-novena>
|
||||
Andy Wingo <wingo@igalia.com> <wingo@pobox.com>
|
||||
Ben Woodcroft <donttrustben@gmail.com>
|
||||
Ben Woodcroft <donttrustben@gmail.com> <b.woodcroft@uq.edu.au>
|
||||
Ben Woodcroft <donttrustben@gmail.com> <donttrustben near gmail.com>
|
||||
Ben Woodcroft <b.woodcroft@uq.edu.au> <donttrustben@gmail.com>
|
||||
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>
|
||||
Danny Milosavljevic <dannym@scratchpost.org> <dannym+a@scratchpost.org>
|
||||
David Hashe <david.hashe@dhashe.com> <address@hidden>
|
||||
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@member.fsf.org> <ericbavier@gmail.com>
|
||||
Eric Dvorsak <eric@dvorsak.fr> <yenda1@gmail.com>
|
||||
George Clemmer <myglc2@gmail.com>
|
||||
Ivan Vilata i Balaguer <ivan@selidor.net>
|
||||
Jeff Mickey <j@codemac.net> <jm@igneous.io>
|
||||
John Darrington <jmd@gnu.org> <john@darrington.wattle.id.au>
|
||||
John J. Foerch <jjfoerch@earthlink.net>
|
||||
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>
|
||||
Kei Kebreau <kei@openmailbox.org> <kkebreau@posteo.net>
|
||||
Leo Famulari <leo@famulari.name> <lfamular@gmail.com>
|
||||
Ludovic Courtès <ludo@gnu.org> <ludovic.courtes@inria.fr>
|
||||
Marek Benc <dusxmt@gmx.com> <merkur32@gmail.com>
|
||||
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 Lirzin <mthl@openmailbox.org> <mathieu.lirzin@openmailbox.org>
|
||||
Nikita Karetnikov <nikita@karetnikov.org> <nikita.karetnikov@gmail.com>
|
||||
ng0 <ng0@n0.is>
|
||||
ng0 <ng0@n0.is> <ng0@infotropique.org>
|
||||
ng0 <ng0@n0.is> <ng0@no-reply.infotropique.org>
|
||||
ng0 <ng0@n0.is> <ng0@no-reply.pragmatique.xyz>
|
||||
ng0 <ng0@n0.is> <ng0@pragmatique.xyz>
|
||||
ng0 <ng0@n0.is> <contact.ng0@cryptolab.net>
|
||||
ng0 <ng0@n0.is> <ng0@we.make.ritual.n0.is>
|
||||
ng0 <ng0@n0.is> <ngillmann@runbox.com>
|
||||
ng0 <ng0@n0.is> <niasterisk@grrlz.net>
|
||||
ng0 <ng0@n0.is> <ng@niasterisk.space>
|
||||
ng0 <ng0@n0.is> <ng0@libertad.pw>
|
||||
Pjotr Prins <pjotr.guix@thebird.nl> <pjotr.public01@thebird.nl>
|
||||
Pjotr Prins <pjotr.guix@thebird.nl> <pjotr.public12@thebird.nl>
|
||||
Pjotr Prins <pjotr.guix@thebird.nl> <pjotr.public12@email>
|
||||
Raimon Grau <raimonster@gmail.com> <raimon@3scale.net>
|
||||
Raoul Jean Pierre Bonnal <ilpuccio.febo@gmail.com>
|
||||
Raymond Nicholson <rain1@openmailbox.org>
|
||||
Rene Saavedra <rennes@openmailbox.org>
|
||||
Pjotr Prins <pjotr.public01@thebird.nl>
|
||||
Pjotr Prins <pjotr.public01@thebird.nl> <pjotr.public12@thebird.nl>
|
||||
Ricardo Wurmus <rekado@elephly.net>
|
||||
Ricardo Wurmus <rekado@elephly.net> <ricardo.wurmus@mdc-berlin.de>
|
||||
Sou Bunnbu (宋文武) <iyzsong@gmail.com>
|
||||
Sou Bunnbu (宋文武) <iyzsong@gmail.com> <iyzsong@member.fsf.org>
|
||||
Stefan Reichör <stefan@xsteve.at>
|
||||
Taylan Ulrich Bayırlı/Kammer <taylanbayirli@gmail.com>
|
||||
Theodoros Foradis <theodoros.for@openmailbox.org> <theodoros@foradis.org>
|
||||
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>
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
Contributor Code of Conduct
|
||||
|
||||
Note: In the sequel, "project" refers to GNU Guix, and "project
|
||||
maintainer(s)" refers to maintainer(s) of GNU Guix.
|
||||
|
||||
As contributors and maintainers of this project, and in the interest of
|
||||
fostering an open and welcoming community, we pledge to respect all
|
||||
people who contribute through reporting issues, posting feature
|
||||
requests, updating documentation, submitting pull requests or patches,
|
||||
and other activities.
|
||||
|
||||
We are committed to making participation in this project a
|
||||
harassment-free experience for everyone, regardless of level of
|
||||
experience, gender, gender identity and expression, sexual orientation,
|
||||
disability, personal appearance, body size, race, ethnicity, age,
|
||||
religion, or nationality.
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery
|
||||
* Personal attacks
|
||||
* Trolling or insulting/derogatory comments
|
||||
* Public or private harassment
|
||||
* Publishing other's private information, such as physical or electronic
|
||||
addresses, without explicit permission
|
||||
* Other unethical or unprofessional conduct
|
||||
|
||||
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.
|
||||
|
||||
By adopting this Code of Conduct, project maintainers commit themselves
|
||||
to fairly and consistently applying these principles to every aspect of
|
||||
managing this project. Project maintainers who do not follow or enforce
|
||||
the Code of Conduct may be permanently removed from the project team.
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public
|
||||
spaces when an individual is representing the project or its community.
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may
|
||||
be reported by contacting a project maintainer 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. Maintainers are obligated to maintain confidentiality
|
||||
with regard to the reporter of an incident.
|
||||
|
||||
This Code of Conduct is adapted from the Contributor Covenant
|
||||
(http://contributor-covenant.org), version 1.3.0, available at
|
||||
http://contributor-covenant.org/version/1/3/0/
|
||||
@@ -2,10 +2,8 @@
|
||||
|
||||
#+TITLE: Hacking GNU Guix and Its Incredible Distro
|
||||
|
||||
Copyright © 2012, 2013, 2014, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
|
||||
Copyright © 2015, 2017 Mathieu Lirzin <mthl@gnu.org>
|
||||
Copyright © 2017 Leo Famulari <leo@famulari.name>
|
||||
Copyright © 2017 Arun Isaac <arunisaac@systemreboot.net>
|
||||
Copyright © 2012, 2013, 2014 Ludovic Courtès <ludo@gnu.org>
|
||||
Copyright © 2015 Mathieu Lirzin <mthl@openmailbox.org>
|
||||
|
||||
Copying and distribution of this file, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
@@ -15,7 +13,7 @@ Copyright © 2017 Arun Isaac <arunisaac@systemreboot.net>
|
||||
|
||||
See the manual for useful hacking informations, either by running
|
||||
|
||||
info -f doc/guix.info "Contributing"
|
||||
info -f doc/guix.info "(guix) Contributing"
|
||||
|
||||
or by checking the [[http://www.gnu.org/software/guix/manual/guix.html#Contributing][web copy of the manual]].
|
||||
|
||||
@@ -26,10 +24,8 @@ convenient. When you deem it necessary, feel free to ask for it on the
|
||||
mailing list. When you get commit access, please make sure to follow the
|
||||
policy below (discussions of the policy can take place on guix-devel@gnu.org.)
|
||||
|
||||
Non-trivial patches should always be posted to guix-patches@gnu.org (trivial
|
||||
patches include fixing typos, etc.) This mailing list fills the
|
||||
patch-tracking database at [[https://bugs.gnu.org/guix-patches]]; see
|
||||
"Contributing" in the manual for details.
|
||||
Non-trivial patches should always be posted to guix-devel@gnu.org (trivial
|
||||
patches include fixing typos, etc.)
|
||||
|
||||
For patches that just add a new package, and a simple one, it’s OK to commit,
|
||||
if you’re confident (which means you successfully built it in a chroot setup,
|
||||
@@ -39,35 +35,9 @@ upgrading GnuTLS or GLib.) We have a mailing list for commit notifications
|
||||
(guix-commits@gnu.org), so people can notice. Before pushing your changes,
|
||||
make sure to run ‘git pull --rebase’.
|
||||
|
||||
All commits that are pushed to the central repository on Savannah must be
|
||||
signed with an OpenPGP key, and the public key should be uploaded to your user
|
||||
account on Savannah and to public key servers, such as ‘pgp.mit.edu’. To
|
||||
configure Git to automatically sign commits, run:
|
||||
|
||||
git config commit.gpgsign true
|
||||
git config user.signingkey CABBA6EA1DC0FF33
|
||||
|
||||
You can prevent yourself from accidentally pushing unsigned commits to
|
||||
Savannah by using the pre-push Git hook called located at ‘etc/git/pre-push’:
|
||||
|
||||
cp etc/git/pre-push .git/hooks/pre-push
|
||||
|
||||
When pushing a commit on behalf of somebody else, please add a Signed-off-by
|
||||
line at the end of the commit log message (e.g. with ‘git am --signoff’).
|
||||
This improves tracking of who did what.
|
||||
|
||||
For anything else, please post to guix-patches@gnu.org and leave time for a
|
||||
For anything else, please post to guix-devel@gnu.org and leave time for a
|
||||
review, without committing anything. If you didn’t receive any reply
|
||||
after two weeks, and if you’re confident, it’s OK to commit.
|
||||
|
||||
That last part is subject to being adjusted, allowing individuals to commit
|
||||
directly on non-controversial changes on parts they’re familiar with.
|
||||
|
||||
* Using emacs-debbugs
|
||||
|
||||
Bug reports and patches are tracked using debbugs. If you are on emacs, you
|
||||
can use emacs-debbugs.
|
||||
|
||||
List all open bug reports on guix-patches with
|
||||
|
||||
C-u M-x debbugs-gnu <RET> <RET> guix-patches <RET> n y
|
||||
|
||||
+103
-401
@@ -1,14 +1,7 @@
|
||||
# GNU Guix --- Functional package management for GNU
|
||||
# Copyright © 2012, 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
|
||||
# Copyright © 2012, 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
|
||||
# Copyright © 2013 Andreas Enge <andreas@enge.fr>
|
||||
# Copyright © 2015, 2017 Alex Kost <alezost@gmail.com>
|
||||
# Copyright © 2016 Mathieu Lirzin <mthl@gnu.org>
|
||||
# Copyright © 2016, 2017 Mark H Weaver <mhw@netris.org>
|
||||
# Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
|
||||
# Copyright © 2017 Leo Famulari <leo@famulari.name>
|
||||
# Copyright © 2017 Ricardo Wurmus <rekado@elephly.net>
|
||||
# Copyright © 2017 Jan Nieuwenhuizen <janneke@gnu.org>
|
||||
# Copyright © 2017 Arun Isaac <arunisaac@systemreboot.net>
|
||||
# Copyright © 2015 Alex Kost <alezost@gmail.com>
|
||||
#
|
||||
# This file is part of GNU Guix.
|
||||
#
|
||||
@@ -32,14 +25,9 @@ nodist_noinst_SCRIPTS = \
|
||||
pre-inst-env \
|
||||
test-env
|
||||
|
||||
# Modules that are not compiled but are installed nonetheless, such as
|
||||
# build-side modules with unusual dependencies.
|
||||
MODULES_NOT_COMPILED =
|
||||
|
||||
include gnu/local.mk
|
||||
include gnu-system.am
|
||||
|
||||
MODULES = \
|
||||
guix/base16.scm \
|
||||
guix/base32.scm \
|
||||
guix/base64.scm \
|
||||
guix/cpio.scm \
|
||||
@@ -48,16 +36,10 @@ MODULES = \
|
||||
guix/hash.scm \
|
||||
guix/pk-crypto.scm \
|
||||
guix/pki.scm \
|
||||
guix/progress.scm \
|
||||
guix/combinators.scm \
|
||||
guix/memoization.scm \
|
||||
guix/utils.scm \
|
||||
guix/sets.scm \
|
||||
guix/modules.scm \
|
||||
guix/download.scm \
|
||||
guix/discovery.scm \
|
||||
guix/git-download.scm \
|
||||
guix/hg-download.scm \
|
||||
guix/monads.scm \
|
||||
guix/monad-repl.scm \
|
||||
guix/gexp.scm \
|
||||
@@ -65,38 +47,20 @@ MODULES = \
|
||||
guix/serialization.scm \
|
||||
guix/nar.scm \
|
||||
guix/derivations.scm \
|
||||
guix/grafts.scm \
|
||||
guix/gnu-maintenance.scm \
|
||||
guix/upstream.scm \
|
||||
guix/licenses.scm \
|
||||
guix/git.scm \
|
||||
guix/graph.scm \
|
||||
guix/cache.scm \
|
||||
guix/cve.scm \
|
||||
guix/workers.scm \
|
||||
guix/zlib.scm \
|
||||
guix/build-system.scm \
|
||||
guix/build-system/ant.scm \
|
||||
guix/build-system/cargo.scm \
|
||||
guix/build-system/cmake.scm \
|
||||
guix/build-system/dub.scm \
|
||||
guix/build-system/emacs.scm \
|
||||
guix/build-system/font.scm \
|
||||
guix/build-system/go.scm \
|
||||
guix/build-system/meson.scm \
|
||||
guix/build-system/minify.scm \
|
||||
guix/build-system/asdf.scm \
|
||||
guix/build-system/glib-or-gtk.scm \
|
||||
guix/build-system/gnu.scm \
|
||||
guix/build-system/haskell.scm \
|
||||
guix/build-system/perl.scm \
|
||||
guix/build-system/python.scm \
|
||||
guix/build-system/ocaml.scm \
|
||||
guix/build-system/waf.scm \
|
||||
guix/build-system/r.scm \
|
||||
guix/build-system/ruby.scm \
|
||||
guix/build-system/scons.scm \
|
||||
guix/build-system/texlive.scm \
|
||||
guix/build-system/trivial.scm \
|
||||
guix/ftp-client.scm \
|
||||
guix/http-client.scm \
|
||||
@@ -105,55 +69,33 @@ MODULES = \
|
||||
guix/store.scm \
|
||||
guix/cvs-download.scm \
|
||||
guix/svn-download.scm \
|
||||
guix/i18n.scm \
|
||||
guix/ui.scm \
|
||||
guix/build/ant-build-system.scm \
|
||||
guix/build/download.scm \
|
||||
guix/build/download-nar.scm \
|
||||
guix/build/cargo-build-system.scm \
|
||||
guix/build/cmake-build-system.scm \
|
||||
guix/build/dub-build-system.scm \
|
||||
guix/build/emacs-build-system.scm \
|
||||
guix/build/meson-build-system.scm \
|
||||
guix/build/minify-build-system.scm \
|
||||
guix/build/font-build-system.scm \
|
||||
guix/build/go-build-system.scm \
|
||||
guix/build/asdf-build-system.scm \
|
||||
guix/build/git.scm \
|
||||
guix/build/hg.scm \
|
||||
guix/build/glib-or-gtk-build-system.scm \
|
||||
guix/build/gnu-build-system.scm \
|
||||
guix/build/gnu-dist.scm \
|
||||
guix/build/perl-build-system.scm \
|
||||
guix/build/python-build-system.scm \
|
||||
guix/build/ocaml-build-system.scm \
|
||||
guix/build/r-build-system.scm \
|
||||
guix/build/ruby-build-system.scm \
|
||||
guix/build/scons-build-system.scm \
|
||||
guix/build/texlive-build-system.scm \
|
||||
guix/build/waf-build-system.scm \
|
||||
guix/build/haskell-build-system.scm \
|
||||
guix/build/store-copy.scm \
|
||||
guix/build/utils.scm \
|
||||
guix/build/union.scm \
|
||||
guix/build/profiles.scm \
|
||||
guix/build/compile.scm \
|
||||
guix/build/pull.scm \
|
||||
guix/build/rpath.scm \
|
||||
guix/build/cvs.scm \
|
||||
guix/build/svn.scm \
|
||||
guix/build/syscalls.scm \
|
||||
guix/build/gremlin.scm \
|
||||
guix/build/emacs-utils.scm \
|
||||
guix/build/java-utils.scm \
|
||||
guix/build/lisp-utils.scm \
|
||||
guix/build/graft.scm \
|
||||
guix/build/bournish.scm \
|
||||
guix/build/qt-utils.scm \
|
||||
guix/build/make-bootstrap.scm \
|
||||
guix/search-paths.scm \
|
||||
guix/packages.scm \
|
||||
guix/import/print.scm \
|
||||
guix/import/utils.scm \
|
||||
guix/import/gnu.scm \
|
||||
guix/import/snix.scm \
|
||||
@@ -161,23 +103,19 @@ MODULES = \
|
||||
guix/import/cran.scm \
|
||||
guix/import/hackage.scm \
|
||||
guix/import/elpa.scm \
|
||||
guix/import/texlive.scm \
|
||||
guix/scripts.scm \
|
||||
guix/scripts/download.scm \
|
||||
guix/scripts/perform-download.scm \
|
||||
guix/scripts/build.scm \
|
||||
guix/scripts/archive.scm \
|
||||
guix/scripts/import.scm \
|
||||
guix/scripts/package.scm \
|
||||
guix/scripts/gc.scm \
|
||||
guix/scripts/hash.scm \
|
||||
guix/scripts/pack.scm \
|
||||
guix/scripts/pull.scm \
|
||||
guix/scripts/substitute.scm \
|
||||
guix/scripts/authenticate.scm \
|
||||
guix/scripts/refresh.scm \
|
||||
guix/scripts/system.scm \
|
||||
guix/scripts/system/search.scm \
|
||||
guix/scripts/lint.scm \
|
||||
guix/scripts/challenge.scm \
|
||||
guix/scripts/import/cran.scm \
|
||||
@@ -185,10 +123,8 @@ MODULES = \
|
||||
guix/scripts/import/nix.scm \
|
||||
guix/scripts/import/hackage.scm \
|
||||
guix/scripts/import/elpa.scm \
|
||||
guix/scripts/import/texlive.scm \
|
||||
guix/scripts/environment.scm \
|
||||
guix/scripts/publish.scm \
|
||||
guix/scripts/weather.scm \
|
||||
guix/scripts/edit.scm \
|
||||
guix/scripts/size.scm \
|
||||
guix/scripts/graph.scm \
|
||||
@@ -197,35 +133,13 @@ MODULES = \
|
||||
guix.scm \
|
||||
$(GNU_SYSTEM_MODULES)
|
||||
|
||||
if HAVE_GUILE_JSON
|
||||
if BUILD_SYSCALLS_MODULE
|
||||
|
||||
MODULES += \
|
||||
guix/docker.scm \
|
||||
guix/import/cpan.scm \
|
||||
guix/import/crate.scm \
|
||||
guix/import/gem.scm \
|
||||
guix/import/github.scm \
|
||||
guix/import/gnome.scm \
|
||||
guix/import/json.scm \
|
||||
guix/import/pypi.scm \
|
||||
guix/import/stackage.scm \
|
||||
guix/scripts/import/crate.scm \
|
||||
guix/scripts/import/gem.scm \
|
||||
guix/scripts/import/json.scm \
|
||||
guix/scripts/import/pypi.scm \
|
||||
guix/scripts/import/stackage.scm
|
||||
guix/build/syscalls.scm
|
||||
|
||||
endif
|
||||
|
||||
if HAVE_GUILE_SSH
|
||||
|
||||
MODULES += \
|
||||
guix/ssh.scm \
|
||||
guix/scripts/copy.scm \
|
||||
guix/store/ssh.scm
|
||||
|
||||
endif HAVE_GUILE_SSH
|
||||
|
||||
if BUILD_DAEMON_OFFLOAD
|
||||
|
||||
MODULES += \
|
||||
@@ -233,74 +147,61 @@ MODULES += \
|
||||
|
||||
endif BUILD_DAEMON_OFFLOAD
|
||||
|
||||
# Internal modules with test suite support.
|
||||
dist_noinst_DATA = guix/tests.scm guix/tests/http.scm
|
||||
# Internal module with test suite support.
|
||||
dist_noinst_DATA = guix/tests.scm
|
||||
|
||||
# Auxiliary files for packages.
|
||||
AUX_FILES = \
|
||||
gnu/packages/aux-files/emacs/guix-emacs.el \
|
||||
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/linux-libre/4.1-i686.conf \
|
||||
gnu/packages/aux-files/linux-libre/4.1-x86_64.conf
|
||||
# Because of the autoload hack in (guix build download), we must build it
|
||||
# first to avoid errors on systems where (gnutls) is unavailable.
|
||||
guix/scripts/download.go: guix/build/download.go
|
||||
guix/download.go: guix/build/download.go
|
||||
|
||||
# Linux-Libre configurations.
|
||||
KCONFIGS = \
|
||||
gnu/packages/linux-libre-i686.conf \
|
||||
gnu/packages/linux-libre-x86_64.conf
|
||||
|
||||
# Templates, examples.
|
||||
EXAMPLES = \
|
||||
gnu/system/examples/bare-bones.tmpl \
|
||||
gnu/system/examples/desktop.tmpl \
|
||||
gnu/system/examples/lightweight-desktop.tmpl \
|
||||
gnu/system/examples/vm-image.tmpl
|
||||
gnu/system/examples/desktop.tmpl
|
||||
|
||||
GOBJECTS = $(MODULES:%.scm=%.go) guix/config.go $(dist_noinst_DATA:%.scm=%.go)
|
||||
GOBJECTS = $(MODULES:%.scm=%.go) guix/config.go guix/tests.go
|
||||
|
||||
nobase_dist_guilemodule_DATA = \
|
||||
$(MODULES) $(MODULES_NOT_COMPILED) $(AUX_FILES) $(EXAMPLES) \
|
||||
nobase_dist_guilemodule_DATA = \
|
||||
$(MODULES) $(KCONFIGS) $(EXAMPLES) \
|
||||
$(MISC_DISTRO_FILES)
|
||||
nobase_nodist_guilemodule_DATA = guix/config.scm
|
||||
nobase_nodist_guileobject_DATA = $(GOBJECTS)
|
||||
nobase_nodist_guilemodule_DATA = $(GOBJECTS) guix/config.scm
|
||||
|
||||
# Do we need to provide our own non-broken (srfi srfi-37) module?
|
||||
if INSTALL_SRFI_37
|
||||
|
||||
nobase_nodist_guilemodule_DATA += srfi/srfi-37.scm
|
||||
GOBJECTS += srfi/srfi-37.go
|
||||
|
||||
srfi/srfi-37.scm: srfi/srfi-37.scm.in
|
||||
$(MKDIR_P) srfi
|
||||
cp "$<" "$@"
|
||||
|
||||
endif INSTALL_SRFI_37
|
||||
|
||||
# Handy way to remove the .go files without removing all the rest.
|
||||
clean-go:
|
||||
-$(RM) -f $(GOBJECTS)
|
||||
@find . -name '*.go' -print | \
|
||||
if test -t 1; then \
|
||||
xargs -r echo -e "\033[31mwarning:\033[0m stray .go files:"; \
|
||||
else \
|
||||
xargs -r echo "warning: stray .go files:"; \
|
||||
fi
|
||||
|
||||
|
||||
# Test extensions; has to be unconditional.
|
||||
TEST_EXTENSIONS = .scm .sh
|
||||
|
||||
if CAN_RUN_TESTS
|
||||
|
||||
SCM_TESTS = \
|
||||
tests/base16.scm \
|
||||
tests/base32.scm \
|
||||
tests/base64.scm \
|
||||
tests/cpio.scm \
|
||||
tests/hash.scm \
|
||||
tests/pk-crypto.scm \
|
||||
tests/pki.scm \
|
||||
tests/print.scm \
|
||||
tests/sets.scm \
|
||||
tests/modules.scm \
|
||||
tests/gnu-maintenance.scm \
|
||||
tests/substitute.scm \
|
||||
tests/builders.scm \
|
||||
tests/derivations.scm \
|
||||
tests/grafts.scm \
|
||||
tests/ui.scm \
|
||||
tests/records.scm \
|
||||
tests/upstream.scm \
|
||||
tests/combinators.scm \
|
||||
tests/discovery.scm \
|
||||
tests/utils.scm \
|
||||
tests/build-utils.scm \
|
||||
tests/packages.scm \
|
||||
@@ -308,43 +209,38 @@ SCM_TESTS = \
|
||||
tests/hackage.scm \
|
||||
tests/cran.scm \
|
||||
tests/elpa.scm \
|
||||
tests/texlive.scm \
|
||||
tests/store.scm \
|
||||
tests/monads.scm \
|
||||
tests/gexp.scm \
|
||||
tests/nar.scm \
|
||||
tests/union.scm \
|
||||
tests/profiles.scm \
|
||||
tests/search-paths.scm \
|
||||
tests/syscalls.scm \
|
||||
tests/gremlin.scm \
|
||||
tests/bournish.scm \
|
||||
tests/lint.scm \
|
||||
tests/publish.scm \
|
||||
tests/scripts.scm \
|
||||
tests/size.scm \
|
||||
tests/graph.scm \
|
||||
tests/challenge.scm \
|
||||
tests/cache.scm \
|
||||
tests/cve.scm \
|
||||
tests/workers.scm \
|
||||
tests/zlib.scm \
|
||||
tests/file-systems.scm \
|
||||
tests/uuid.scm \
|
||||
tests/system.scm \
|
||||
tests/services.scm \
|
||||
tests/scripts-build.scm \
|
||||
tests/containers.scm \
|
||||
tests/pack.scm \
|
||||
tests/import-utils.scm
|
||||
tests/containers.scm
|
||||
|
||||
if HAVE_GUILE_JSON
|
||||
|
||||
MODULES += \
|
||||
guix/import/json.scm \
|
||||
guix/import/pypi.scm \
|
||||
guix/scripts/import/pypi.scm \
|
||||
guix/import/cpan.scm \
|
||||
guix/scripts/import/gem.scm \
|
||||
guix/import/gem.scm
|
||||
|
||||
SCM_TESTS += \
|
||||
tests/pypi.scm \
|
||||
tests/cpan.scm \
|
||||
tests/gem.scm \
|
||||
tests/crate.scm
|
||||
tests/gem.scm
|
||||
|
||||
endif
|
||||
|
||||
@@ -372,14 +268,12 @@ endif BUILD_DAEMON
|
||||
|
||||
TESTS = $(SCM_TESTS) $(SH_TESTS)
|
||||
|
||||
AM_TESTS_ENVIRONMENT = abs_top_srcdir="$(abs_top_srcdir)" GUILE_AUTO_COMPILE=0
|
||||
TEST_EXTENSIONS = .scm .sh
|
||||
|
||||
SCM_LOG_DRIVER = \
|
||||
$(top_builddir)/test-env --quiet-stderr \
|
||||
$(GUILE) --no-auto-compile -e main \
|
||||
$(top_srcdir)/build-aux/test-driver.scm
|
||||
AM_TESTS_ENVIRONMENT = abs_top_srcdir="$(abs_top_srcdir)"
|
||||
|
||||
AM_SCM_LOG_DRIVER_FLAGS = --brief=yes
|
||||
SCM_LOG_COMPILER = $(top_builddir)/test-env $(GUILE)
|
||||
AM_SCM_LOG_FLAGS = --no-auto-compile -L "$(top_srcdir)"
|
||||
|
||||
SH_LOG_COMPILER = $(top_builddir)/test-env $(SHELL)
|
||||
AM_SH_LOG_FLAGS = -x -e
|
||||
@@ -391,67 +285,32 @@ tests/guix-gc.log: \
|
||||
$(patsubst %.sh,%.log,$(filter-out tests/guix-gc.sh,$(SH_TESTS))) \
|
||||
$(SCM_TESTS:%.scm=%.log)
|
||||
|
||||
else !CAN_RUN_TESTS
|
||||
|
||||
TESTS =
|
||||
SH_TESTS =
|
||||
SCM_TESTS =
|
||||
|
||||
# Automake always generates a 'check' target, so better not override it.
|
||||
check-local:
|
||||
@echo
|
||||
@echo "Cannot run tests because file name limits would be exceeded." >&2
|
||||
@echo "Look for 'length' in the 'config.log' file for details." >&2
|
||||
@echo
|
||||
@exit 1
|
||||
|
||||
endif !CAN_RUN_TESTS
|
||||
|
||||
check-system: $(GOBJECTS) $(BOOTSTRAP_GUILE_TARBALLS)
|
||||
$(AM_V_at)$(top_builddir)/pre-inst-env \
|
||||
$(GUILE) --no-auto-compile \
|
||||
-e '(@@ (run-system-tests) run-system-tests)' \
|
||||
$(top_srcdir)/build-aux/run-system-tests.scm
|
||||
|
||||
# Public key used to sign substitutes from hydra.gnu.org & co.
|
||||
dist_pkgdata_DATA = \
|
||||
hydra.gnu.org.pub \
|
||||
berlin.guixsd.org.pub
|
||||
# Public key used to sign substitutes from hydra.gnu.org.
|
||||
dist_pkgdata_DATA = hydra.gnu.org.pub
|
||||
|
||||
# Bash completion file.
|
||||
dist_bashcompletion_DATA = etc/completion/bash/guix
|
||||
|
||||
# Zsh completion file.
|
||||
dist_zshcompletion_DATA = etc/completion/zsh/_guix
|
||||
|
||||
EXTRA_DIST = \
|
||||
HACKING \
|
||||
ROADMAP \
|
||||
TODO \
|
||||
CODE-OF-CONDUCT \
|
||||
.dir-locals.el \
|
||||
build-aux/build-self.scm \
|
||||
build-aux/compile-all.scm \
|
||||
build-aux/hydra/evaluate.scm \
|
||||
build-aux/hydra/gnu-system.scm \
|
||||
build-aux/hydra/demo-os.scm \
|
||||
build-aux/hydra/guix.scm \
|
||||
build-aux/hydra/guix-modular.scm \
|
||||
build-aux/check-available-binaries.scm \
|
||||
build-aux/check-final-inputs-self-contained.scm \
|
||||
build-aux/download.scm \
|
||||
build-aux/make-binary-tarball.scm \
|
||||
build-aux/generate-authors.scm \
|
||||
build-aux/test-driver.scm \
|
||||
build-aux/update-guix-package.scm \
|
||||
build-aux/update-NEWS.scm \
|
||||
build-aux/run-system-tests.scm \
|
||||
d3.v3.js \
|
||||
graph.js \
|
||||
srfi/srfi-37.scm.in \
|
||||
srfi/srfi-64.scm \
|
||||
srfi/srfi-64.upstream.scm \
|
||||
tests/test.drv \
|
||||
tests/signing-key.pub \
|
||||
tests/signing-key.sec \
|
||||
tests/cve-sample.xml \
|
||||
build-aux/config.rpath \
|
||||
bootstrap \
|
||||
release.nix \
|
||||
@@ -464,28 +323,40 @@ EXTRA_DIST += \
|
||||
|
||||
endif !BUILD_DAEMON_OFFLOAD
|
||||
|
||||
if !BUILD_SYSCALLS_MODULE
|
||||
|
||||
EXTRA_DIST += \
|
||||
guix/build/syscalls.scm
|
||||
|
||||
endif !BUILD_SYSCALLS_MODULE
|
||||
|
||||
|
||||
CLEANFILES = \
|
||||
$(GOBJECTS) \
|
||||
$(SCM_TESTS:tests/%.scm=%.log)
|
||||
|
||||
AM_V_GUILEC = $(AM_V_GUILEC_$(V))
|
||||
AM_V_GUILEC_ = $(AM_V_GUILEC_$(AM_DEFAULT_VERBOSITY))
|
||||
AM_V_GUILEC_0 = @echo " GUILEC" $@;
|
||||
|
||||
# Unset 'GUILE_LOAD_COMPILED_PATH' altogether while compiling. Otherwise, if
|
||||
# $GUILE_LOAD_COMPILED_PATH contains $(moduledir), we may find .go files in
|
||||
# there that are newer than the local .scm files (for instance because the
|
||||
# user ran 'make install' recently). When that happens, we end up loading
|
||||
# those previously-installed .go files, which may be stale, thereby breaking
|
||||
# the whole thing. Likewise, set 'XDG_CACHE_HOME' to avoid loading possibly
|
||||
# stale files from ~/.cache/guile/ccache.
|
||||
%.go: make-go ; @:
|
||||
make-go: $(MODULES) guix/config.scm $(dist_noinst_DATA)
|
||||
$(AM_V_at)echo "Compiling Scheme modules..." ; \
|
||||
# the whole thing.
|
||||
#
|
||||
# XXX: Use the C locale for when Guile lacks
|
||||
# <http://git.sv.gnu.org/cgit/guile.git/commit/?h=stable-2.0&id=e2c6bf3866d1186c60bacfbd4fe5037087ee5e3f>.
|
||||
.scm.go:
|
||||
$(AM_V_GUILEC)$(MKDIR_P) `dirname "$@"` ; \
|
||||
unset GUILE_LOAD_COMPILED_PATH ; \
|
||||
XDG_CACHE_HOME=/nowhere \
|
||||
host=$(host) srcdir="$(top_srcdir)" \
|
||||
LC_ALL=C \
|
||||
$(top_builddir)/pre-inst-env \
|
||||
$(GUILE) -L "$(top_builddir)" -L "$(top_srcdir)" \
|
||||
--no-auto-compile \
|
||||
-s "$(top_srcdir)"/build-aux/compile-all.scm $^
|
||||
$(GUILD) compile -L "$(top_builddir)" -L "$(top_srcdir)" \
|
||||
-Wformat -Wunbound-variable -Warity-mismatch \
|
||||
--target="$(host)" \
|
||||
-o "$@" "$<"
|
||||
|
||||
SUFFIXES = .go
|
||||
|
||||
@@ -494,67 +365,56 @@ SUFFIXES = .go
|
||||
# files. See
|
||||
# <http://lists.gnu.org/archive/html/guile-devel/2010-07/msg00125.html>
|
||||
# for details.
|
||||
guix_install_go_files = install-nobase_nodist_guileobjectDATA
|
||||
guix_install_go_files = install-nobase_nodist_guilemoduleDATA
|
||||
$(guix_install_go_files): install-nobase_dist_guilemoduleDATA
|
||||
|
||||
# The above trick doesn't work for 'config.go' because both 'config.scm' and
|
||||
# 'config.go' are listed in $(nobase_nodist_guileobject_DATA). Thus, give it
|
||||
# 'config.go' are listed in $(nobase_nodist_guilemodule_DATA). Thus, give it
|
||||
# special treatment.
|
||||
install-data-hook: set-bootstrap-executable-permissions
|
||||
touch "$(DESTDIR)$(guileobjectdir)/guix/config.go"
|
||||
touch "$(DESTDIR)$(guilemoduledir)/guix/config.go"
|
||||
|
||||
|
||||
SUBDIRS = po/guix po/packages
|
||||
BUILT_SOURCES =
|
||||
|
||||
include doc/local.mk
|
||||
include doc.am
|
||||
|
||||
if BUILD_DAEMON
|
||||
|
||||
include nix/local.mk
|
||||
include daemon.am
|
||||
|
||||
endif BUILD_DAEMON
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
# Pass an explicit '--localstatedir' so that configure does not error out if
|
||||
# it finds an existing installation with a different localstatedir. Inherit
|
||||
# 'ac_cv_guix_test_root' so that "make check" in $(distdir) does not have to
|
||||
# repopulate the whole store, and to make sure $(GUIX_TEST_ROOT) is short
|
||||
# enough for shebangs.
|
||||
AM_DISTCHECK_CONFIGURE_FLAGS = \
|
||||
--localstatedir="$$dc_install_base/var" \
|
||||
--with-libgcrypt-prefix="$(LIBGCRYPT_PREFIX)" \
|
||||
--with-libgcrypt-libdir="$(LIBGCRYPT_LIBDIR)" \
|
||||
--with-nix-prefix="$(NIX_PREFIX)" \
|
||||
--enable-daemon \
|
||||
ac_cv_guix_test_root="$(GUIX_TEST_ROOT)"
|
||||
--enable-daemon
|
||||
|
||||
# The self-contained tarball. Add 'glibc-utf8-locales' along with glibc just
|
||||
# so 'etc/profile' defines 'GUIX_LOCPATH' pointing to a valid set of locales.
|
||||
dist_emacsui_DATA = emacs/guix-main.scm
|
||||
nodist_emacsui_DATA = emacs/guix-helper.scm
|
||||
include emacs.am
|
||||
|
||||
# The self-contained tarball.
|
||||
guix-binary.%.tar.xz:
|
||||
$(AM_V_GEN)GUIX_PACKAGE_PATH= \
|
||||
tarball=`$(top_builddir)/pre-inst-env guix pack -K -C xz \
|
||||
-s "$*" --localstatedir guix glibc-utf8-locales \
|
||||
-e '(@@ (gnu packages commencement) glibc-final)'` ; \
|
||||
cp "$$tarball" "$@.tmp" ; mv "$@.tmp" "$@"
|
||||
-GUIX_PACKAGE_PATH= \
|
||||
$(top_builddir)/pre-inst-env "$(GUILE)" \
|
||||
"$(top_srcdir)/build-aux/make-binary-tarball.scm" "$*" "$@"
|
||||
|
||||
|
||||
dist-hook: $(distdir)/ChangeLog gen-AUTHORS gen-tarball-version
|
||||
dist-hook: sync-descriptions gen-ChangeLog gen-AUTHORS
|
||||
dist-hook: assert-no-store-file-names
|
||||
|
||||
distcheck-hook: assert-binaries-available assert-final-inputs-self-contained
|
||||
|
||||
EXTRA_DIST += $(top_srcdir)/.version
|
||||
BUILT_SOURCES += $(top_srcdir)/.version
|
||||
$(top_srcdir)/.version:
|
||||
echo $(VERSION) > "$@-t" && mv "$@-t" "$@"
|
||||
sync-descriptions:
|
||||
-GUIX_PACKAGE_PATH= \
|
||||
$(top_builddir)/pre-inst-env guix lint --checkers=gnu-description
|
||||
|
||||
gen-tarball-version:
|
||||
echo $(VERSION) > "$(distdir)/.tarball-version"
|
||||
|
||||
gen-ChangeLog $(distdir)/ChangeLog:
|
||||
$(AM_V_GEN)if test -d .git; then \
|
||||
gen-ChangeLog:
|
||||
if test -d .git; then \
|
||||
$(top_srcdir)/build-aux/gitlog-to-changelog \
|
||||
> $(distdir)/cl-t; \
|
||||
rm -f $(distdir)/ChangeLog; \
|
||||
@@ -562,190 +422,32 @@ gen-ChangeLog $(distdir)/ChangeLog:
|
||||
fi
|
||||
|
||||
gen-AUTHORS:
|
||||
$(AM_V_GEN)if test -d .git; then \
|
||||
if test -d .git; then \
|
||||
rm -f "$(distdir)/AUTHORS"; \
|
||||
$(top_builddir)/pre-inst-env "$(GUILE)" \
|
||||
"$(top_srcdir)/build-aux/generate-authors.scm" \
|
||||
"$(top_srcdir)" "$(distdir)/AUTHORS"; \
|
||||
fi
|
||||
|
||||
|
||||
#
|
||||
# Release management.
|
||||
#
|
||||
|
||||
releasedir = release-$(PACKAGE_VERSION)
|
||||
|
||||
PACKAGE_FULL_TARNAME = $(PACKAGE_TARNAME)-$(PACKAGE_VERSION)
|
||||
|
||||
# List of source tarballs produced. This must be kept in sync with the
|
||||
# 'dist-' options of 'AM_INIT_AUTOMAKE' in 'configure.ac'.
|
||||
SOURCE_TARBALLS = \
|
||||
$(foreach ext,tar.gz,$(PACKAGE_FULL_TARNAME).$(ext))
|
||||
|
||||
# Systems supported by Guix.
|
||||
SUPPORTED_SYSTEMS ?= x86_64-linux i686-linux armhf-linux aarch64-linux
|
||||
|
||||
# Guix binary tarballs.
|
||||
BINARY_TARBALLS = \
|
||||
$(foreach system,$(SUPPORTED_SYSTEMS),guix-binary.$(system).tar.xz)
|
||||
|
||||
# Systems supported by GuixSD.
|
||||
GUIXSD_SUPPORTED_SYSTEMS ?= x86_64-linux i686-linux
|
||||
|
||||
# Systems for which we build GuixSD VMs.
|
||||
GUIXSD_VM_SYSTEMS ?= x86_64-linux
|
||||
|
||||
# Prefix of the GuixSD installation image file name.
|
||||
GUIXSD_IMAGE_BASE = guixsd-install-$(PACKAGE_VERSION)
|
||||
|
||||
# Prefix of the GuixSD VM image file name.
|
||||
GUIXSD_VM_IMAGE_BASE = guixsd-vm-image-$(PACKAGE_VERSION)
|
||||
|
||||
# The release process works in several phases:
|
||||
#
|
||||
# 0. We assume the developer created a 'vX.Y' tag.
|
||||
# 1. Build the source tarball.
|
||||
# 2. Update the 'guix' package so that it corresponds to the 'vX.Y' tag.
|
||||
# 3. Build the binary tarballs for that 'guix' package.
|
||||
# 4. Update the 'guix' package again.
|
||||
# 5. Build the GuixSD installation images. The images will run 'guix'
|
||||
# corresponding to 'vX.Y' + 1 commit, and they will install 'vX.Y'.
|
||||
#
|
||||
# This 'release' target takes care of everything and copies the resulting
|
||||
# files to $(releasedir).
|
||||
#
|
||||
# XXX: Depend on 'dist' rather than 'distcheck' to work around the Gettext
|
||||
# issue described at <https://savannah.gnu.org/bugs/index.php?51027>.
|
||||
release: dist
|
||||
cd po; git checkout .
|
||||
@if ! git diff-index --quiet HEAD; then \
|
||||
echo "There are uncommitted changes; stopping." >&2 ; \
|
||||
exit 1 ; \
|
||||
fi
|
||||
$(MKDIR_P) "$(releasedir)"
|
||||
rm -f "$(releasedir)"/*
|
||||
mv $(SOURCE_TARBALLS) "$(releasedir)"
|
||||
$(top_builddir)/pre-inst-env "$(GUILE)" \
|
||||
$(top_srcdir)/build-aux/update-guix-package.scm \
|
||||
"`git rev-parse HEAD`" "$(PACKAGE_VERSION)"
|
||||
git add $(top_srcdir)/gnu/packages/package-management.scm
|
||||
git commit -m "gnu: guix: Update to $(PACKAGE_VERSION)."
|
||||
rm -f $(BINARY_TARBALLS)
|
||||
$(MAKE) $(BINARY_TARBALLS)
|
||||
for system in $(SUPPORTED_SYSTEMS) ; do \
|
||||
mv "guix-binary.$$system.tar.xz" \
|
||||
"$(releasedir)/guix-binary-$(PACKAGE_VERSION).$$system.tar.xz" ; \
|
||||
done
|
||||
$(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`."
|
||||
for system in $(GUIXSD_SUPPORTED_SYSTEMS) ; do \
|
||||
image=`$(top_builddir)/pre-inst-env \
|
||||
guix system disk-image \
|
||||
--file-system-type=iso9660 \
|
||||
--system=$$system \
|
||||
gnu/system/install.scm` ; \
|
||||
if [ ! -f "$$image" ] ; then \
|
||||
echo "failed to produced GuixSD installation image for $$system" >&2 ; \
|
||||
exit 1 ; \
|
||||
fi ; \
|
||||
xz < "$$image" > "$(releasedir)/$(GUIXSD_IMAGE_BASE).$$system.iso.xz.tmp" ; \
|
||||
mv "$(releasedir)/$(GUIXSD_IMAGE_BASE).$$system.iso.xz.tmp" \
|
||||
"$(releasedir)/$(GUIXSD_IMAGE_BASE).$$system.iso.xz" ; \
|
||||
done
|
||||
for system in $(GUIXSD_VM_SYSTEMS) ; do \
|
||||
image=`$(top_builddir)/pre-inst-env \
|
||||
guix system vm-image \
|
||||
--system=$$system \
|
||||
gnu/system/examples/vm-image.tmpl` ; \
|
||||
if [ ! -f "$$image" ] ; then \
|
||||
echo "failed to produced GuixSD VM image for $$system" >&2 ; \
|
||||
exit 1 ; \
|
||||
fi ; \
|
||||
xz < "$$image" > "$(releasedir)/$(GUIXSD_VM_IMAGE_BASE).$$system.xz.tmp" ; \
|
||||
mv "$(releasedir)/$(GUIXSD_VM_IMAGE_BASE).$$system.xz.tmp" \
|
||||
"$(releasedir)/$(GUIXSD_VM_IMAGE_BASE).$$system.xz" ; \
|
||||
done
|
||||
@echo
|
||||
@echo "Congratulations! All the release files are now in $(releasedir)."
|
||||
@echo
|
||||
|
||||
update-guix-package:
|
||||
git rev-parse HEAD
|
||||
$(top_builddir)/pre-inst-env "$(GUILE)" \
|
||||
$(top_srcdir)/build-aux/update-guix-package.scm \
|
||||
"`git rev-parse HEAD`"
|
||||
|
||||
# Location of a checkout of <git://git.savannah.gnu.org/guix/maintenance.git>.
|
||||
# Package data from this checkout is used by 'update-NEWS.scm'.
|
||||
GUIX_MAINTENANCE_DIRECTORY ?= $(top_srcdir)/../guix-maintenance
|
||||
|
||||
update-NEWS: $(GOBJECTS)
|
||||
$(top_builddir)/pre-inst-env "$(GUILE)" \
|
||||
$(top_srcdir)/build-aux/update-NEWS.scm \
|
||||
$(top_srcdir)/NEWS "$(GUIX_MAINTENANCE_DIRECTORY)/data"
|
||||
|
||||
# Make sure we're not shipping a file that embeds a local /gnu/store file name.
|
||||
assert-no-store-file-names: $(distdir)/ChangeLog
|
||||
$(AM_V_at)if grep -r --exclude=*.texi --exclude=*.info \
|
||||
--exclude=*.info-[0-9] --exclude=*.dot \
|
||||
--exclude=*.eps --exclude-dir=bootstrap \
|
||||
--exclude=guix-prettify.el \
|
||||
--exclude=ChangeLog \
|
||||
-E "$(storedir)/[a-z0-9]{32}-" $(distdir) ; \
|
||||
assert-no-store-file-names:
|
||||
if grep -r --exclude=*.texi --exclude=*.info \
|
||||
"$(storedir)/[a-z0-9]{32}-" $(distdir) ; \
|
||||
then \
|
||||
echo "error: store file names embedded in the distribution" >&2 ; \
|
||||
exit 1 ; \
|
||||
fi
|
||||
|
||||
# Make sure hydra.gnu.org has the important binaries.
|
||||
assert-binaries-available: $(GOBJECTS)
|
||||
$(AM_V_at)$(top_builddir)/pre-inst-env "$(GUILE)" \
|
||||
assert-binaries-available:
|
||||
$(top_builddir)/pre-inst-env "$(GUILE)" \
|
||||
"$(top_srcdir)/build-aux/check-available-binaries.scm"
|
||||
|
||||
# Make sure the final inputs don't refer to bootstrap tools.
|
||||
assert-final-inputs-self-contained: $(GOBJECTS)
|
||||
$(AM_V_at)$(top_builddir)/pre-inst-env "$(GUILE)" \
|
||||
assert-final-inputs-self-contained:
|
||||
$(top_builddir)/pre-inst-env "$(GUILE)" \
|
||||
"$(top_srcdir)/build-aux/check-final-inputs-self-contained.scm"
|
||||
|
||||
# Compute the Hydra jobs and write them in the target file.
|
||||
hydra-jobs.scm: $(GOBJECTS)
|
||||
$(AM_V_at)$(MKDIR_P) "`dirname "$@"`"
|
||||
$(AM_V_GEN)$(top_builddir)/pre-inst-env "$(GUILE)" \
|
||||
"$(top_srcdir)/build-aux/hydra/evaluate.scm" \
|
||||
"$(top_srcdir)/build-aux/hydra/gnu-system.scm" > "$@.tmp"
|
||||
$(AM_V_at)mv "$@.tmp" "$@"
|
||||
|
||||
# Compute the Cuirass jobs and write them in the target file.
|
||||
cuirass-jobs.scm: $(GOBJECTS)
|
||||
$(AM_V_at)$(MKDIR_P) "`dirname "$@"`"
|
||||
$(AM_V_GEN)$(top_builddir)/pre-inst-env "$(GUILE)" \
|
||||
"$(top_srcdir)/build-aux/hydra/evaluate.scm" \
|
||||
"$(top_srcdir)/build-aux/cuirass/gnu-system.scm" \
|
||||
cuirass > "$@.tmp"
|
||||
$(AM_V_at)mv "$@.tmp" "$@"
|
||||
|
||||
.PHONY: gen-ChangeLog gen-AUTHORS gen-tarball-version
|
||||
.PHONY: sync-descriptions gen-ChangeLog gen-AUTHORS clean-go
|
||||
.PHONY: assert-no-store-file-names assert-binaries-available
|
||||
.PHONY: assert-final-inputs-self-contained
|
||||
.PHONY: clean-go make-go
|
||||
.PHONY: update-guix-package update-NEWS release
|
||||
|
||||
## -------------- ##
|
||||
## Silent rules. ##
|
||||
## -------------- ##
|
||||
|
||||
AM_V_DL = $(AM_V_DL_$(V))
|
||||
AM_V_DL_ = $(AM_V_DL_$(AM_DEFAULT_VERBOSITY))
|
||||
AM_V_DL_0 = @echo " DL " $@;
|
||||
|
||||
AM_V_DOT = $(AM_V_DOT_$(V))
|
||||
AM_V_DOT_ = $(AM_V_DOT_$(AM_DEFAULT_VERBOSITY))
|
||||
AM_V_DOT_0 = @echo " DOT " $@;
|
||||
|
||||
AM_V_HELP2MAN = $(AM_V_HELP2MAN_$(V))
|
||||
AM_V_HELP2MAN_ = $(AM_V_HELP2MAN_$(AM_DEFAULT_VERBOSITY))
|
||||
AM_V_HELP2MAN_0 = @echo " HELP2MAN" $@;
|
||||
|
||||
@@ -1,50 +1,50 @@
|
||||
-*- mode: org -*-
|
||||
|
||||
[[https://www.gnu.org/software/guix/][GNU Guix]] (IPA: /ɡiːks/) is a purely functional package manager, and
|
||||
associated free software distribution, for the [[https://www.gnu.org/gnu/gnu.html][GNU system]]. In addition
|
||||
[[http://www.gnu.org/software/guix/][GNU Guix]] (IPA: /ɡiːks/) is a purely functional package manager, and
|
||||
associated free software distribution, for the [[http://www.gnu.org/gnu/gnu.html][GNU system]]. In addition
|
||||
to standard package management features, Guix supports transactional
|
||||
upgrades and roll-backs, unprivileged package management, per-user
|
||||
profiles, and garbage collection.
|
||||
|
||||
It provides [[https://www.gnu.org/software/guile/][Guile]] Scheme APIs, including a high-level embedded
|
||||
It provides [[http://www.gnu.org/software/guile/][Guile]] Scheme APIs, including a high-level embedded
|
||||
domain-specific languages (EDSLs) to describe how packages are to be
|
||||
built and composed.
|
||||
|
||||
A user-land free software distribution for GNU/Linux comes as part of
|
||||
Guix.
|
||||
|
||||
Guix is based on the [[https://nixos.org/nix/][Nix]] package manager.
|
||||
Guix is based on the [[http://nixos.org/nix/][Nix]] package manager.
|
||||
|
||||
|
||||
* Requirements
|
||||
|
||||
GNU Guix currently depends on the following packages:
|
||||
|
||||
- [[https://gnu.org/software/guile/][GNU Guile 2.2.x or 2.0.x]], version 2.0.9 or later
|
||||
- [[https://gnupg.org/][GNU libgcrypt]]
|
||||
- [[https://www.gnu.org/software/make/][GNU Make]]
|
||||
- optionally [[https://savannah.nongnu.org/projects/guile-json/][Guile-JSON]], for the 'guix import pypi' command
|
||||
- optionally [[https://www.gnutls.org][GnuTLS]] compiled with guile support enabled, for HTTPS support
|
||||
- [[http://gnu.org/software/guile/][GNU Guile 2.0.x]], version 2.0.7 or later
|
||||
- [[http://gnupg.org/][GNU libgcrypt]]
|
||||
- [[http://www.gnu.org/software/make/][GNU Make]]
|
||||
- optionally [[http://savannah.nongnu.org/projects/guile-json/][Guile-JSON]], for the 'guix import pypi' command
|
||||
- optionally [[http://www.gnutls.org][GnuTLS]] compiled with guile support enabled, for HTTPS support
|
||||
in the 'guix download' command. Note that 'guix import pypi' requires
|
||||
this functionality.
|
||||
|
||||
Unless `--disable-daemon' was passed, the following packages are needed:
|
||||
|
||||
- [[https://sqlite.org/][SQLite 3]]
|
||||
- [[http://sqlite.org/][SQLite 3]]
|
||||
- [[http://www.bzip.org][libbz2]]
|
||||
- [[https://gcc.gnu.org][GCC's g++]]
|
||||
- [[http://gcc.gnu.org][GCC's g++]]
|
||||
|
||||
When `--disable-daemon' was passed, you instead need the following:
|
||||
|
||||
- [[https://nixos.org/nix/][Nix]]
|
||||
- [[http://nixos.org/nix/][Nix]]
|
||||
|
||||
* Installation
|
||||
|
||||
See the manual for the installation instructions, either by running
|
||||
|
||||
info -f doc/guix.info "Installation"
|
||||
info -f doc/guix.info "(guix) Installation"
|
||||
|
||||
or by checking the [[https://www.gnu.org/software/guix/manual/guix.html#Installation][web copy of the manual]].
|
||||
or by checking the [[http://www.gnu.org/software/guix/manual/guix.html#Installation][web copy of the manual]].
|
||||
|
||||
For information on installation from a Git checkout, please see the section
|
||||
"Building from Git" in the manual.
|
||||
@@ -109,7 +109,7 @@ Join #guix on irc.freenode.net.
|
||||
|
||||
* Guix & Nix
|
||||
|
||||
GNU Guix is based on [[https://nixos.org/nix/][the Nix package manager]]. It implements the same
|
||||
GNU Guix is based on [[http://nixos.org/nix/][the Nix package manager]]. It implements the same
|
||||
package deployment paradigm, and in fact it reuses some of its code.
|
||||
Yet, different engineering decisions were made for Guix, as described
|
||||
below.
|
||||
@@ -132,7 +132,7 @@ the store. Guix produces such derivations, which are then interpreted
|
||||
by the daemon to perform the build. Thus, Guix derivations can use
|
||||
derivations produced by Nix (and vice versa).
|
||||
|
||||
With Nix and the [[https://nixos.org/nixpkgs][Nixpkgs]] distribution, package composition happens at
|
||||
With Nix and the [[http://nixos.org/nixpkgs][Nixpkgs]] distribution, package composition happens at
|
||||
the Nix language level, but builders are usually written in Bash.
|
||||
Conversely, Guix encourages the use of Scheme for both package
|
||||
composition and builders. Likewise, the core functionality of Nix is
|
||||
@@ -141,13 +141,13 @@ but exposes all the API as Scheme.
|
||||
|
||||
* Related software
|
||||
|
||||
- [[https://nixos.org][Nix, Nixpkgs, and NixOS]], functional package manager and associated
|
||||
- [[http://nixos.org][Nix, Nixpkgs, and NixOS]], functional package manager and associated
|
||||
software distribution, are the inspiration of Guix
|
||||
- [[https://www.gnu.org/software/stow/][GNU Stow]] builds around the idea of one directory per prefix, and a
|
||||
- [[http://www.gnu.org/software/stow/][GNU Stow]] builds around the idea of one directory per prefix, and a
|
||||
symlink tree to create user environments
|
||||
- [[https://www.pvv.ntnu.no/~arnej/store/storedoc_6.html][STORE]] shares the same idea
|
||||
- [[http://www.pvv.ntnu.no/~arnej/store/storedoc_6.html][STORE]] shares the same idea
|
||||
- [[https://live.gnome.org/OSTree/][GNOME's OSTree]] allows bootable system images to be built from a
|
||||
specified set of packages
|
||||
- The [[https://www.gnu.org/s/gsrc/][GNU Source Release Collection]] (GSRC) is a user-land software
|
||||
- The [[http://www.gnu.org/s/gsrc/][GNU Source Release Collection]] (GSRC) is a user-land software
|
||||
distribution; unlike Guix, it relies on core tools available on the
|
||||
host system
|
||||
|
||||
@@ -77,6 +77,6 @@ Freenode!
|
||||
+ build containers like guix-daemon does
|
||||
+ provide a Plash-like interface in Bash
|
||||
- daemon rewritten in Guile
|
||||
- more shepherd integration
|
||||
- more dmd integration
|
||||
+ monitor network interfaces and start/stop events based on that
|
||||
+ include a DHCP client written in Scheme
|
||||
|
||||
@@ -14,7 +14,6 @@ infrastructure help:
|
||||
Alexandru Cojocaru <xojoc@gmx.com>
|
||||
Aleix Conchillo Flaqué <aconchillo@gmail.com>
|
||||
Malcolm Cook <MEC@stowers.org>
|
||||
Thomas Danckaert <thomas.danckaert@gmail.com>
|
||||
Rafael Ferreira <rafael.f.f1@gmail.com>
|
||||
Christian Grothoff <christian@grothoff.org>
|
||||
Eric Hanchrow <eric.hanchrow@gmail.com>
|
||||
@@ -26,7 +25,6 @@ infrastructure help:
|
||||
Daniel Kochmański <dkochmanski@hellsgate.pl>
|
||||
Matthew Lien <bluet@bluet.org>
|
||||
Dave Love <fx@gnu.org>
|
||||
Chris Marusich <cmmarusich@gmail.com>
|
||||
Niels Möller <nisse@lysator.liu.se>
|
||||
Cyprien Nicolas <cyprien@nicolas.tf>
|
||||
Yutaka Niibe <gniibe@fsij.org>
|
||||
@@ -41,7 +39,6 @@ infrastructure help:
|
||||
Thomas Schwinge <thomas@codesourcery.com>
|
||||
Alexander Shendi <Alexander.Shendi@web.de>
|
||||
Alen Skondro <askondro@gmail.com>
|
||||
Jan Synáček <jan.synacek@gmail.com>
|
||||
Matthias Wachs <wachs@net.in.tum.de>
|
||||
Christopher Allan Webber <cwebber@dustycloud.org>
|
||||
Philip Woods <elzairthesorcerer@gmail.com>
|
||||
|
||||
@@ -9,6 +9,13 @@ Copyright © 2012, 2013, 2014 Ludovic Courtès <ludo@gnu.org>
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
notice and this notice are preserved.
|
||||
|
||||
* Add `guix publish' to publish the store using Guile's web server
|
||||
|
||||
Generate narinfos and nars on the fly, upon HTTP GET requests.
|
||||
Ideally, extend .nix-cache-info to include the server's public key, and also
|
||||
reply to requests for .narinfo.sig.
|
||||
Optionally, use Guile-Avahi to publish the service.
|
||||
|
||||
* MAYBE Add a substituter that uses the GNUnet DHT or [[http://libswift.org][libswift]]
|
||||
|
||||
Would be neat if binaries could be pushed to and pulled from the GNUnet DHT or
|
||||
@@ -67,6 +74,11 @@ per-package priorities, etc.
|
||||
Tests that need to download stuff or otherwise take a long time would only be
|
||||
run when that is defined.
|
||||
|
||||
* add "guix challenge"
|
||||
|
||||
Would download a substitute, and compare its contents against a (hopefully
|
||||
locally-built) copy.
|
||||
|
||||
* guix build utils
|
||||
** MAYBE Change ‘ld-wrapper’ to add RPATH for libs passed by file name
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
(public-key
|
||||
(ecc
|
||||
(curve Ed25519)
|
||||
(q #8D156F295D24B0D9A86FA5741A840FF2D24F60F7B6C4134814AD55625971B394#)
|
||||
)
|
||||
)
|
||||
+14
-184
@@ -1,5 +1,5 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2014, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2014 Ludovic Courtès <ludo@gnu.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
@@ -19,10 +19,7 @@
|
||||
(define-module (build-self)
|
||||
#:use-module (gnu)
|
||||
#:use-module (guix)
|
||||
#:use-module (guix config)
|
||||
#:use-module (srfi srfi-1)
|
||||
#:use-module (srfi srfi-19)
|
||||
#:use-module (ice-9 match)
|
||||
#:export (build))
|
||||
|
||||
;;; Commentary:
|
||||
@@ -47,63 +44,10 @@
|
||||
(define libgcrypt
|
||||
(first (find-best-packages-by-name "libgcrypt" #f)))
|
||||
|
||||
(define zlib
|
||||
(first (find-best-packages-by-name "zlib" #f)))
|
||||
|
||||
(define gzip
|
||||
(first (find-best-packages-by-name "gzip" #f)))
|
||||
|
||||
(define bzip2
|
||||
(first (find-best-packages-by-name "bzip2" #f)))
|
||||
|
||||
(define xz
|
||||
(first (find-best-packages-by-name "xz" #f)))
|
||||
|
||||
(define (false-if-wrong-guile package)
|
||||
"Return #f if PACKAGE depends on the \"wrong\" major version of Guile (e.g.,
|
||||
2.0 instead of 2.2), otherwise return PACKAGE."
|
||||
(let ((guile (any (match-lambda
|
||||
((label (? package? dep) _ ...)
|
||||
(and (string=? (package-name dep) "guile")
|
||||
dep)))
|
||||
(package-direct-inputs package))))
|
||||
(and (or (not guile)
|
||||
(string-prefix? (effective-version)
|
||||
(package-version guile)))
|
||||
package)))
|
||||
|
||||
(define (package-for-current-guile . names)
|
||||
"Return the package with one of the given NAMES that depends on the current
|
||||
Guile major version (2.0 or 2.2), or #f if none of the packages matches."
|
||||
(let loop ((names names))
|
||||
(match names
|
||||
(()
|
||||
#f)
|
||||
((name rest ...)
|
||||
(match (find-best-packages-by-name name #f)
|
||||
(()
|
||||
(loop rest))
|
||||
((first _ ...)
|
||||
(or (false-if-wrong-guile first)
|
||||
(loop rest))))))))
|
||||
|
||||
(define guile-json
|
||||
(package-for-current-guile "guile-json"
|
||||
"guile2.2-json"
|
||||
"guile2.0-json"))
|
||||
(first (find-best-packages-by-name "guile-json" #f)))
|
||||
|
||||
(define guile-ssh
|
||||
(package-for-current-guile "guile-ssh"
|
||||
"guile2.2-ssh"
|
||||
"guile2.0-ssh"))
|
||||
|
||||
(define guile-git
|
||||
(package-for-current-guile "guile-git"
|
||||
"guile2.0-git"))
|
||||
|
||||
(define guile-bytestructures
|
||||
(package-for-current-guile "guile-bytestructures"
|
||||
"guile2.0-bytestructures"))
|
||||
|
||||
;; The actual build procedure.
|
||||
|
||||
@@ -113,150 +57,36 @@ Guile major version (2.0 or 2.2), or #f if none of the packages matches."
|
||||
(lambda (file)
|
||||
(string-append (dirname file) "/.."))))
|
||||
|
||||
|
||||
(define (date-version-string)
|
||||
"Return the current date and hour in UTC timezone, for use as a poor
|
||||
person's version identifier."
|
||||
;; XXX: Replace with a Git commit id.
|
||||
(date->string (current-date 0) "~Y~m~d.~H"))
|
||||
|
||||
(define (guile-for-build)
|
||||
"Return a derivation for Guile 2.0 or 2.2, whichever matches the currently
|
||||
running Guile."
|
||||
(package->derivation (cond-expand
|
||||
(guile-2.2
|
||||
(canonical-package
|
||||
(specification->package "guile@2.2")))
|
||||
(else
|
||||
(canonical-package
|
||||
(specification->package "guile@2.0"))))))
|
||||
|
||||
;; The procedure below is our return value.
|
||||
(define* (build source
|
||||
#:key verbose? (version (date-version-string))
|
||||
(define* (build source #:key verbose?
|
||||
#:allow-other-keys
|
||||
#:rest rest)
|
||||
"Return a derivation that unpacks SOURCE into STORE and compiles Scheme
|
||||
files."
|
||||
;; The '%xxxdir' variables were added to (guix config) in July 2016 so we
|
||||
;; cannot assume that they are defined. Try to guess their value when
|
||||
;; they're undefined (XXX: we get an incorrect guess when environment
|
||||
;; variables such as 'NIX_STATE_DIR' are defined!).
|
||||
(define storedir
|
||||
(if (defined? '%storedir) %storedir %store-directory))
|
||||
(define localstatedir
|
||||
(if (defined? '%localstatedir) %localstatedir (dirname %state-directory)))
|
||||
(define sysconfdir
|
||||
(if (defined? '%sysconfdir) %sysconfdir (dirname %config-directory)))
|
||||
(define sbindir
|
||||
(if (defined? '%sbindir) %sbindir (dirname %guix-register-program)))
|
||||
|
||||
(define builder
|
||||
#~(begin
|
||||
(use-modules (guix build pull))
|
||||
|
||||
(letrec-syntax ((maybe-load-path
|
||||
(syntax-rules ()
|
||||
((_ item rest ...)
|
||||
(let ((tail (maybe-load-path rest ...)))
|
||||
(if (string? item)
|
||||
(cons (string-append item
|
||||
"/share/guile/site/"
|
||||
#$(effective-version))
|
||||
tail)
|
||||
tail)))
|
||||
((_)
|
||||
'()))))
|
||||
(set! %load-path
|
||||
(append
|
||||
(maybe-load-path #$guile-json #$guile-ssh
|
||||
#$guile-git #$guile-bytestructures)
|
||||
%load-path)))
|
||||
|
||||
(letrec-syntax ((maybe-load-compiled-path
|
||||
(syntax-rules ()
|
||||
((_ item rest ...)
|
||||
(let ((tail (maybe-load-compiled-path rest ...)))
|
||||
(if (string? item)
|
||||
(cons (string-append item
|
||||
"/lib/guile/"
|
||||
#$(effective-version)
|
||||
"/site-ccache")
|
||||
tail)
|
||||
tail)))
|
||||
((_)
|
||||
'()))))
|
||||
(set! %load-compiled-path
|
||||
(append
|
||||
(maybe-load-compiled-path #$guile-json #$guile-ssh
|
||||
#$guile-git #$guile-bytestructures)
|
||||
%load-compiled-path)))
|
||||
|
||||
;; XXX: The 'guile-ssh' package prior to Guix commit 92b7258 was
|
||||
;; broken: libguile-ssh could not be found. Work around that.
|
||||
;; FIXME: We want Guile-SSH 0.10.2 or later anyway.
|
||||
#$(if (string-prefix? "0.9." (package-version guile-ssh))
|
||||
#~(setenv "LTDL_LIBRARY_PATH" (string-append #$guile-ssh "/lib"))
|
||||
#t)
|
||||
(let ((json (string-append #$guile-json "/share/guile/site/2.0")))
|
||||
(set! %load-path (cons json %load-path))
|
||||
(set! %load-compiled-path (cons json %load-compiled-path)))
|
||||
|
||||
(build-guix #$output #$source
|
||||
|
||||
#:system #$%system
|
||||
#:storedir #$storedir
|
||||
#:localstatedir #$localstatedir
|
||||
#:sysconfdir #$sysconfdir
|
||||
#:sbindir #$sbindir
|
||||
|
||||
#:package-name #$%guix-package-name
|
||||
#:package-version #$version
|
||||
#:bug-report-address #$%guix-bug-report-address
|
||||
#:home-page-url #$%guix-home-page-url
|
||||
|
||||
#:libgcrypt #$libgcrypt
|
||||
#:zlib #$zlib
|
||||
#:gzip #$gzip
|
||||
#:bzip2 #$bzip2
|
||||
#:xz #$xz
|
||||
|
||||
;; XXX: This is not perfect, enabling VERBOSE? means
|
||||
;; building a different derivation.
|
||||
#:debug-port (if #$verbose?
|
||||
(current-error-port)
|
||||
(%make-void-port "w")))))
|
||||
(%make-void-port "w"))
|
||||
#:gcrypt #$libgcrypt)))
|
||||
|
||||
(unless guile-git
|
||||
;; XXX: Guix before February 2017 lacks a 'guile-git' package altogether.
|
||||
;; If we try to upgrade anyway, the logic in (guix scripts pull) will not
|
||||
;; build (guix git), which will leave us with an unusable 'guix pull'. To
|
||||
;; avoid that, fail early.
|
||||
(format (current-error-port)
|
||||
"\
|
||||
Your installation is too old and lacks a '~a' package.
|
||||
Please upgrade to an intermediate version first, for instance with:
|
||||
(gexp->derivation "guix-latest" builder
|
||||
#:modules '((guix build pull)
|
||||
(guix build utils))
|
||||
|
||||
guix pull --url=https://git.savannah.gnu.org/cgit/guix.git/snapshot/v0.13.0.tar.gz
|
||||
\n"
|
||||
(match (effective-version)
|
||||
("2.0" "guile2.0-git")
|
||||
(_ "guile-git")))
|
||||
(exit 1))
|
||||
|
||||
(mlet %store-monad ((guile (guile-for-build)))
|
||||
(gexp->derivation "guix-latest" builder
|
||||
#:modules '((guix build pull)
|
||||
(guix build utils)
|
||||
(guix build compile)
|
||||
|
||||
;; Closure of (guix modules).
|
||||
(guix modules)
|
||||
(guix memoization)
|
||||
(guix sets))
|
||||
|
||||
;; Arrange so that our own (guix build …) modules are
|
||||
;; used.
|
||||
#:module-path (list (top-source-directory))
|
||||
|
||||
#:guile-for-build guile)))
|
||||
;; Arrange so that our own (guix build …) modules are
|
||||
;; used.
|
||||
#:module-path (list (top-source-directory))))
|
||||
|
||||
;; This file is loaded by 'guix pull'; return it the build procedure.
|
||||
build
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
@@ -21,7 +21,6 @@
|
||||
;;;
|
||||
|
||||
(use-modules (guix store)
|
||||
(guix grafts)
|
||||
(guix packages)
|
||||
(guix derivations)
|
||||
(gnu packages emacs)
|
||||
@@ -38,20 +37,16 @@
|
||||
%hydra-supported-systems))
|
||||
(cross (map (cut package-cross-derivation store
|
||||
%bootstrap-tarballs <>)
|
||||
'("mips64el-linux-gnu"
|
||||
"arm-linux-gnueabihf")))
|
||||
'("mips64el-linux-gnuabi64")))
|
||||
(total (append native cross)))
|
||||
|
||||
(set-build-options store
|
||||
#:use-substitutes? #t
|
||||
#:substitute-urls %default-substitute-urls)
|
||||
(set-build-options store #:use-substitutes? #t)
|
||||
(let* ((total (map derivation->output-path total))
|
||||
(available (substitutable-paths store total))
|
||||
(missing (lset-difference string=? total available)))
|
||||
(if (null? missing)
|
||||
(format (current-error-port)
|
||||
"~a packages found substitutable on~{ ~a~}~%"
|
||||
(length total) %hydra-supported-systems)
|
||||
(format (current-error-port) "~a packages found substitutable~%"
|
||||
(length total))
|
||||
(format (current-error-port)
|
||||
"~a packages are not substitutable:~%~{ ~a~%~}~%"
|
||||
(length missing) missing))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2014, 2015 Ludovic Courtès <ludo@gnu.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
@@ -21,7 +21,6 @@
|
||||
;;;
|
||||
|
||||
(use-modules (guix store)
|
||||
(guix grafts)
|
||||
(guix packages)
|
||||
(guix derivations)
|
||||
(guix ui)
|
||||
@@ -37,17 +36,12 @@
|
||||
(let ((drv (package-derivation store package system)))
|
||||
;; Libc's 'debug' output refers to gcc-cross-boot0, but it's
|
||||
;; hard to avoid, so we tolerate it. This should be the
|
||||
;; only exception. Likewise, 'bash:include' depends on
|
||||
;; bootstrap-binaries via its 'Makefile.inc' (FIXME).
|
||||
;; only exception.
|
||||
(filter-map (match-lambda
|
||||
(("debug" . directory)
|
||||
(if (string=? "glibc" (package-name package))
|
||||
#f
|
||||
directory))
|
||||
(("include" . directory)
|
||||
(if (string=? "bash" (package-name package))
|
||||
#f
|
||||
directory))
|
||||
((_ . directory) directory))
|
||||
(derivation->output-paths drv)))))
|
||||
%final-inputs))
|
||||
@@ -57,7 +51,7 @@
|
||||
if it does."
|
||||
(let ((references (substitutable-references substitute)))
|
||||
(when (any (cut string-contains <> "boot") references)
|
||||
(leave (G_ "'~a' refers to bootstrap inputs: ~s~%")
|
||||
(leave (_ "'~a' refers to bootstrap inputs: ~s~%")
|
||||
(substitutable-path substitute) references))))
|
||||
|
||||
(define (test-final-inputs store system)
|
||||
@@ -71,7 +65,7 @@ refer to the bootstrap tools."
|
||||
(string=? (substitutable-path substitute)
|
||||
dir))
|
||||
available)
|
||||
(leave (G_ "~a (system: ~a) has no substitute~%")
|
||||
(leave (_ "~a (system: ~a) has no substitute~%")
|
||||
dir system)))
|
||||
inputs)
|
||||
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2016 Taylan Ulrich Bayırlı/Kammer <taylanbayirli@gmail.com>
|
||||
;;; Copyright © 2016, 2017 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/>.
|
||||
|
||||
(use-modules (ice-9 match)
|
||||
(ice-9 threads)
|
||||
(srfi srfi-1)
|
||||
(guix build compile)
|
||||
(guix build utils))
|
||||
|
||||
(define host (getenv "host"))
|
||||
(define srcdir (getenv "srcdir"))
|
||||
|
||||
(define (relative-file file)
|
||||
(if (string-prefix? (string-append srcdir "/") file)
|
||||
(string-drop file (+ 1 (string-length srcdir)))
|
||||
file))
|
||||
|
||||
(define (file-mtime<? f1 f2)
|
||||
(< (stat:mtime (stat f1))
|
||||
(stat:mtime (stat f2))))
|
||||
|
||||
(define (scm->go file)
|
||||
(let* ((relative (relative-file file))
|
||||
(without-extension (string-drop-right relative 4)))
|
||||
(string-append without-extension ".go")))
|
||||
|
||||
(define (file-needs-compilation? file)
|
||||
(let ((go (scm->go file)))
|
||||
(or (not (file-exists? go))
|
||||
(file-mtime<? go file))))
|
||||
|
||||
(define* (parallel-job-count #:optional (flags (getenv "MAKEFLAGS")))
|
||||
"Return the number of parallel jobs as determined by FLAGS, the flags passed
|
||||
to 'make'."
|
||||
(match flags
|
||||
(#f (current-processor-count))
|
||||
(flags
|
||||
(let ((initial-flags (string-tokenize flags)))
|
||||
(let loop ((flags initial-flags))
|
||||
(match flags
|
||||
(()
|
||||
;; Note: GNU make prior to version 4.2 would hide "-j" flags from
|
||||
;; $MAKEFLAGS. Thus, check for a "--jobserver" flag here and
|
||||
;; assume we're using all cores if specified.
|
||||
(if (any (lambda (flag)
|
||||
(string-prefix? "--jobserver" flag))
|
||||
initial-flags)
|
||||
(current-processor-count) ;GNU make < 4.2
|
||||
1)) ;sequential make
|
||||
(("-j" (= string->number count) _ ...)
|
||||
(if (integer? count)
|
||||
count
|
||||
(current-processor-count)))
|
||||
((head tail ...)
|
||||
(if (string-prefix? "-j" head)
|
||||
(match (string-drop head 2)
|
||||
(""
|
||||
(current-processor-count))
|
||||
((= string->number count)
|
||||
(if (integer? count)
|
||||
count
|
||||
(current-processor-count))))
|
||||
(loop tail)))))))))
|
||||
|
||||
;; Install a SIGINT handler to give unwind handlers in 'compile-file' an
|
||||
;; opportunity to run upon SIGINT and to remove temporary output files.
|
||||
(sigaction SIGINT
|
||||
(lambda args
|
||||
(exit 1)))
|
||||
|
||||
(match (command-line)
|
||||
((_ . files)
|
||||
(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 " LOAD ~a~%" file)
|
||||
(force-output)))
|
||||
#:report-compilation (lambda (file total completed)
|
||||
(when file
|
||||
(format #t " GUILEC ~a~%"
|
||||
(scm->go file))
|
||||
(force-output))))))
|
||||
@@ -1,47 +0,0 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2017 Jan Nieuwenhuizen <janneke@gnu.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
;;; GNU Guix is free software; you can redistribute it and/or modify it
|
||||
;;; under the terms of the GNU General Public License as published by
|
||||
;;; the Free Software Foundation; either version 3 of the License, or (at
|
||||
;;; your option) any later version.
|
||||
;;;
|
||||
;;; GNU Guix is distributed in the hope that it will be useful, but
|
||||
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;;; GNU General Public License for more details.
|
||||
;;;
|
||||
;;; You should have received a copy of the GNU General Public License
|
||||
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;;
|
||||
;;; This file defines build jobs for the Cuirass continuation integration
|
||||
;;; tool.
|
||||
;;;
|
||||
|
||||
(include-from-path "build-aux/hydra/gnu-system.scm")
|
||||
|
||||
(use-modules ((guix licenses)
|
||||
#:select (license? license-name license-uri license-comment)))
|
||||
|
||||
(define (cuirass-jobs store arguments)
|
||||
"Return Cuirass jobs."
|
||||
(map hydra-job->cuirass-job (hydra-jobs store arguments)))
|
||||
|
||||
(define (hydra-job->cuirass-job hydra-job)
|
||||
(let ((name (car hydra-job))
|
||||
(job ((cdr hydra-job))))
|
||||
(lambda _ (acons #:job-name (symbol->string name)
|
||||
(map symbol-alist-entry->keyword-alist-entry job)))))
|
||||
|
||||
(define (symbol-alist-entry->keyword-alist-entry entry)
|
||||
(cons (symbol->keyword (car entry)) (entry->sexp-entry (cdr entry))))
|
||||
|
||||
(define (entry->sexp-entry o)
|
||||
(match o
|
||||
((? license?) `((name . (license-name o))
|
||||
(uri . ,(license-uri o))
|
||||
(comment . ,(license-comment o))))
|
||||
(_ o)))
|
||||
+15
-14
@@ -1,7 +1,6 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2012, 2013, 2017 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2012, 2013 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2014, 2015 Mark H Weaver <mhw@netris.org>
|
||||
;;; Copyright © 2017 Efraim Flashner <efraim@flashner.co.il>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
@@ -27,7 +26,7 @@
|
||||
(web client)
|
||||
(rnrs io ports)
|
||||
(srfi srfi-11)
|
||||
(guix base16)
|
||||
(guix utils)
|
||||
(guix hash))
|
||||
|
||||
(define %url-base
|
||||
@@ -37,25 +36,27 @@
|
||||
;;"http://www.fdn.fr/~lcourtes/software/guix/packages"
|
||||
)
|
||||
|
||||
;; XXX: Work around <http://bugs.gnu.org/13095>, present in Guile
|
||||
;; up to 2.0.7.
|
||||
(module-define! (resolve-module '(web client))
|
||||
'shutdown (const #f))
|
||||
|
||||
(define (file-name->uri file)
|
||||
"Return the URI for FILE."
|
||||
(match (string-tokenize file (char-set-complement (char-set #\/)))
|
||||
((_ ... system basename)
|
||||
(string->uri
|
||||
(string-append %url-base "/" system
|
||||
(match system
|
||||
("aarch64-linux"
|
||||
"/20170217/")
|
||||
("armhf-linux"
|
||||
"/20150101/")
|
||||
(_
|
||||
"/20131110/"))
|
||||
basename)))))
|
||||
(string->uri (string-append %url-base "/" system
|
||||
(match system
|
||||
("armhf-linux"
|
||||
"/20150101/")
|
||||
(_
|
||||
"/20131110/"))
|
||||
basename)))))
|
||||
|
||||
(match (command-line)
|
||||
((_ file expected-hash)
|
||||
(let ((uri (file-name->uri file)))
|
||||
(format #t "downloading file `~a'~%from `~a'...~%"
|
||||
(format #t "downloading file `~a' from `~a'...~%"
|
||||
file (uri->string uri))
|
||||
(let*-values (((resp data) (http-get uri #:decode-body? #f))
|
||||
((hash) (bytevector->base16-string (sha256 data)))
|
||||
|
||||
@@ -1,226 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Print a version string.
|
||||
scriptversion=2017-01-09.19; # UTC
|
||||
|
||||
# Copyright (C) 2007-2017 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program 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.
|
||||
#
|
||||
# This program 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/>.
|
||||
|
||||
# This script is derived from GIT-VERSION-GEN from GIT: http://git.or.cz/.
|
||||
# It may be run two ways:
|
||||
# - from a git repository in which the "git describe" command below
|
||||
# produces useful output (thus requiring at least one signed tag)
|
||||
# - from a non-git-repo directory containing a .tarball-version file, which
|
||||
# presumes this script is invoked like "./git-version-gen .tarball-version".
|
||||
|
||||
# In order to use intra-version strings in your project, you will need two
|
||||
# separate generated version string files:
|
||||
#
|
||||
# .tarball-version - present only in a distribution tarball, and not in
|
||||
# a checked-out repository. Created with contents that were learned at
|
||||
# the last time autoconf was run, and used by git-version-gen. Must not
|
||||
# be present in either $(srcdir) or $(builddir) for git-version-gen to
|
||||
# give accurate answers during normal development with a checked out tree,
|
||||
# but must be present in a tarball when there is no version control system.
|
||||
# Therefore, it cannot be used in any dependencies. GNUmakefile has
|
||||
# hooks to force a reconfigure at distribution time to get the value
|
||||
# correct, without penalizing normal development with extra reconfigures.
|
||||
#
|
||||
# .version - present in a checked-out repository and in a distribution
|
||||
# tarball. Usable in dependencies, particularly for files that don't
|
||||
# want to depend on config.h but do want to track version changes.
|
||||
# Delete this file prior to any autoconf run where you want to rebuild
|
||||
# files to pick up a version string change; and leave it stale to
|
||||
# minimize rebuild time after unrelated changes to configure sources.
|
||||
#
|
||||
# As with any generated file in a VC'd directory, you should add
|
||||
# /.version to .gitignore, so that you don't accidentally commit it.
|
||||
# .tarball-version is never generated in a VC'd directory, so needn't
|
||||
# be listed there.
|
||||
#
|
||||
# Use the following line in your configure.ac, so that $(VERSION) will
|
||||
# automatically be up-to-date each time configure is run (and note that
|
||||
# since configure.ac no longer includes a version string, Makefile rules
|
||||
# should not depend on configure.ac for version updates).
|
||||
#
|
||||
# AC_INIT([GNU project],
|
||||
# m4_esyscmd([build-aux/git-version-gen .tarball-version]),
|
||||
# [bug-project@example])
|
||||
#
|
||||
# Then use the following lines in your Makefile.am, so that .version
|
||||
# will be present for dependencies, and so that .version and
|
||||
# .tarball-version will exist in distribution tarballs.
|
||||
#
|
||||
# EXTRA_DIST = $(top_srcdir)/.version
|
||||
# BUILT_SOURCES = $(top_srcdir)/.version
|
||||
# $(top_srcdir)/.version:
|
||||
# echo $(VERSION) > $@-t && mv $@-t $@
|
||||
# dist-hook:
|
||||
# echo $(VERSION) > $(distdir)/.tarball-version
|
||||
|
||||
|
||||
me=$0
|
||||
|
||||
version="git-version-gen $scriptversion
|
||||
|
||||
Copyright 2011 Free Software Foundation, Inc.
|
||||
There is NO warranty. You may redistribute this software
|
||||
under the terms of the GNU General Public License.
|
||||
For more information about these matters, see the files named COPYING."
|
||||
|
||||
usage="\
|
||||
Usage: $me [OPTION]... \$srcdir/.tarball-version [TAG-NORMALIZATION-SED-SCRIPT]
|
||||
Print a version string.
|
||||
|
||||
Options:
|
||||
|
||||
--prefix PREFIX prefix of git tags (default 'v')
|
||||
--fallback VERSION
|
||||
fallback version to use if \"git --version\" fails
|
||||
|
||||
--help display this help and exit
|
||||
--version output version information and exit
|
||||
|
||||
Running without arguments will suffice in most cases."
|
||||
|
||||
prefix=v
|
||||
fallback=
|
||||
|
||||
while test $# -gt 0; do
|
||||
case $1 in
|
||||
--help) echo "$usage"; exit 0;;
|
||||
--version) echo "$version"; exit 0;;
|
||||
--prefix) shift; prefix=${1?};;
|
||||
--fallback) shift; fallback=${1?};;
|
||||
-*)
|
||||
echo "$0: Unknown option '$1'." >&2
|
||||
echo "$0: Try '--help' for more information." >&2
|
||||
exit 1;;
|
||||
*)
|
||||
if test "x$tarball_version_file" = x; then
|
||||
tarball_version_file="$1"
|
||||
elif test "x$tag_sed_script" = x; then
|
||||
tag_sed_script="$1"
|
||||
else
|
||||
echo "$0: extra non-option argument '$1'." >&2
|
||||
exit 1
|
||||
fi;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if test "x$tarball_version_file" = x; then
|
||||
echo "$usage"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
tag_sed_script="${tag_sed_script:-s/x/x/}"
|
||||
|
||||
nl='
|
||||
'
|
||||
|
||||
# Avoid meddling by environment variable of the same name.
|
||||
v=
|
||||
v_from_git=
|
||||
|
||||
# First see if there is a tarball-only version file.
|
||||
# then try "git describe", then default.
|
||||
if test -f $tarball_version_file
|
||||
then
|
||||
v=`cat $tarball_version_file` || v=
|
||||
case $v in
|
||||
*$nl*) v= ;; # reject multi-line output
|
||||
[0-9]*) ;;
|
||||
*) v= ;;
|
||||
esac
|
||||
test "x$v" = x \
|
||||
&& echo "$0: WARNING: $tarball_version_file is missing or damaged" 1>&2
|
||||
fi
|
||||
|
||||
if test "x$v" != x
|
||||
then
|
||||
: # use $v
|
||||
# Otherwise, if there is at least one git commit involving the working
|
||||
# directory, and "git describe" output looks sensible, use that to
|
||||
# derive a version string.
|
||||
elif test "`git log -1 --pretty=format:x . 2>&1`" = x \
|
||||
&& v=`git describe --abbrev=4 --match="$prefix*" HEAD 2>/dev/null \
|
||||
|| git describe --abbrev=4 HEAD 2>/dev/null` \
|
||||
&& v=`printf '%s\n' "$v" | sed "$tag_sed_script"` \
|
||||
&& case $v in
|
||||
$prefix[0-9]*) ;;
|
||||
*) (exit 1) ;;
|
||||
esac
|
||||
then
|
||||
# Is this a new git that lists number of commits since the last
|
||||
# tag or the previous older version that did not?
|
||||
# Newer: v6.10-77-g0f8faeb
|
||||
# Older: v6.10-g0f8faeb
|
||||
case $v in
|
||||
*-*-*) : git describe is okay three part flavor ;;
|
||||
*-*)
|
||||
: git describe is older two part flavor
|
||||
# Recreate the number of commits and rewrite such that the
|
||||
# result is the same as if we were using the newer version
|
||||
# of git describe.
|
||||
vtag=`echo "$v" | sed 's/-.*//'`
|
||||
commit_list=`git rev-list "$vtag"..HEAD 2>/dev/null` \
|
||||
|| { commit_list=failed;
|
||||
echo "$0: WARNING: git rev-list failed" 1>&2; }
|
||||
numcommits=`echo "$commit_list" | wc -l`
|
||||
v=`echo "$v" | sed "s/\(.*\)-\(.*\)/\1-$numcommits-\2/"`;
|
||||
test "$commit_list" = failed && v=UNKNOWN
|
||||
;;
|
||||
esac
|
||||
|
||||
# Change the first '-' to a '.', so version-comparing tools work properly.
|
||||
# Remove the "g" in git describe's output string, to save a byte.
|
||||
v=`echo "$v" | sed 's/-/./;s/\(.*\)-g/\1-/'`;
|
||||
v_from_git=1
|
||||
elif test "x$fallback" = x || git --version >/dev/null 2>&1; then
|
||||
v=UNKNOWN
|
||||
else
|
||||
v=$fallback
|
||||
fi
|
||||
|
||||
v=`echo "$v" |sed "s/^$prefix//"`
|
||||
|
||||
# Test whether to append the "-dirty" suffix only if the version
|
||||
# string we're using came from git. I.e., skip the test if it's "UNKNOWN"
|
||||
# or if it came from .tarball-version.
|
||||
if test "x$v_from_git" != x; then
|
||||
# Don't declare a version "dirty" merely because a timestamp has changed.
|
||||
git update-index --refresh > /dev/null 2>&1
|
||||
|
||||
dirty=`exec 2>/dev/null;git diff-index --name-only HEAD` || dirty=
|
||||
case "$dirty" in
|
||||
'') ;;
|
||||
*) # Append the suffix only if there isn't one already.
|
||||
case $v in
|
||||
*-dirty) ;;
|
||||
*) v="$v-dirty" ;;
|
||||
esac ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Omit the trailing newline, so that m4_esyscmd can use the result directly.
|
||||
printf %s "$v"
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC0"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
@@ -0,0 +1,84 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2014, 2015 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 defines an operating system configuration for the demo virtual
|
||||
;;; machine images that we build.
|
||||
;;;
|
||||
|
||||
(use-modules (gnu))
|
||||
(use-service-modules desktop xorg networking avahi dbus)
|
||||
(use-package-modules linux xorg tor avahi)
|
||||
|
||||
(operating-system
|
||||
(host-name "gnu")
|
||||
(timezone "Europe/Paris")
|
||||
(locale "en_US.utf8")
|
||||
|
||||
(bootloader (grub-configuration
|
||||
(device "/dev/sda")))
|
||||
(file-systems
|
||||
;; We provide a dummy file system for /, but that's OK because the VM build
|
||||
;; code will automatically declare the / file system for us.
|
||||
(cons* (file-system
|
||||
(mount-point "/")
|
||||
(device "dummy")
|
||||
(type "dummy"))
|
||||
;; %fuse-control-file-system ; needs fuse.ko
|
||||
;; %binary-format-file-system ; needs binfmt.ko
|
||||
%base-file-systems))
|
||||
|
||||
(users (list (user-account
|
||||
(name "guest")
|
||||
(group "users")
|
||||
(supplementary-groups '("wheel")) ; allow use of sudo
|
||||
(password "")
|
||||
(comment "Guest of GNU")
|
||||
(home-directory "/home/guest"))))
|
||||
|
||||
(issue "
|
||||
This is an alpha preview of the GNU system. Welcome.
|
||||
|
||||
This image features the GNU Guix package manager, which was used to
|
||||
build it (http://www.gnu.org/software/guix/). The init system is
|
||||
GNU dmd (http://www.gnu.org/software/dmd/).
|
||||
|
||||
You can log in as 'guest' or 'root' with no password.
|
||||
")
|
||||
|
||||
(services (cons* (slim-service #:auto-login? #t
|
||||
#:default-user "guest")
|
||||
|
||||
;; QEMU networking settings.
|
||||
(static-networking-service "eth0" "10.0.2.10"
|
||||
#:name-servers '("10.0.2.3")
|
||||
#:gateway "10.0.2.2")
|
||||
|
||||
(avahi-service)
|
||||
(dbus-service)
|
||||
(tor-service)
|
||||
|
||||
%base-services))
|
||||
(pam-services
|
||||
;; Explicitly allow for empty passwords.
|
||||
(base-pam-services #:allow-empty-passwords? #t))
|
||||
|
||||
(packages (cons* strace
|
||||
tor torsocks
|
||||
xterm avahi %base-packages)))
|
||||
@@ -1,130 +0,0 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2016, 2017 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2017 Jan Nieuwenhuizen <janneke@gnu.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
;;; GNU Guix is free software; you can redistribute it and/or modify it
|
||||
;;; under the terms of the GNU General Public License as published by
|
||||
;;; the Free Software Foundation; either version 3 of the License, or (at
|
||||
;;; your option) any later version.
|
||||
;;;
|
||||
;;; GNU Guix is distributed in the hope that it will be useful, but
|
||||
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;;; GNU General Public License for more details.
|
||||
;;;
|
||||
;;; You should have received a copy of the GNU General Public License
|
||||
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; This program replicates the behavior of Hydra's 'hydra-eval-guile-job'.
|
||||
;;; It evaluates the Hydra job defined by the program passed as its first
|
||||
;;; arguments and outputs an sexp of the jobs on standard output.
|
||||
|
||||
(use-modules (guix store)
|
||||
(srfi srfi-19)
|
||||
(ice-9 match)
|
||||
(ice-9 pretty-print)
|
||||
(ice-9 format))
|
||||
|
||||
(define %top-srcdir
|
||||
(and=> (assq-ref (current-source-location) 'filename)
|
||||
(lambda (file)
|
||||
(canonicalize-path
|
||||
(string-append (dirname file) "/../..")))))
|
||||
|
||||
(define %user-module
|
||||
;; Hydra user module.
|
||||
(let ((m (make-module)))
|
||||
(beautify-user-module! m)
|
||||
m))
|
||||
|
||||
(cond-expand
|
||||
(guile-2.2
|
||||
;; Guile 2.2.2 has a bug whereby 'time-monotonic' objects have seconds and
|
||||
;; nanoseconds swapped (fixed in Guile commit 886ac3e). Work around it.
|
||||
(define time-monotonic time-tai))
|
||||
(else #t))
|
||||
|
||||
(define (call-with-time thunk kont)
|
||||
"Call THUNK and pass KONT the elapsed time followed by THUNK's return
|
||||
values."
|
||||
(let* ((start (current-time time-monotonic))
|
||||
(result (call-with-values thunk list))
|
||||
(end (current-time time-monotonic)))
|
||||
(apply kont (time-difference end start) result)))
|
||||
|
||||
(define (call-with-time-display thunk)
|
||||
"Call THUNK and write to the current output port its duration."
|
||||
(call-with-time thunk
|
||||
(lambda (time . results)
|
||||
(format #t "~,3f seconds~%"
|
||||
(+ (time-second time)
|
||||
(/ (time-nanosecond time) 1e9)))
|
||||
(apply values results))))
|
||||
|
||||
(define (assert-valid-job job thing)
|
||||
"Raise an error if THING is not an alist with a valid 'derivation' entry.
|
||||
Otherwise return THING."
|
||||
(unless (and (list? thing)
|
||||
(and=> (assoc-ref thing 'derivation)
|
||||
(lambda (value)
|
||||
(and (string? value)
|
||||
(string-suffix? ".drv" value)))))
|
||||
(error "job did not produce a valid alist" job thing))
|
||||
thing)
|
||||
|
||||
|
||||
;; Without further ado...
|
||||
(match (command-line)
|
||||
((command file cuirass? ...)
|
||||
;; Load FILE, a Scheme file that defines Hydra jobs.
|
||||
(let ((port (current-output-port)))
|
||||
(save-module-excursion
|
||||
(lambda ()
|
||||
(set-current-module %user-module)
|
||||
(primitive-load file)))
|
||||
|
||||
(with-store store
|
||||
;; Make sure we don't resort to substitutes.
|
||||
(set-build-options store
|
||||
#:use-substitutes? #f
|
||||
#:substitute-urls '())
|
||||
|
||||
;; Grafts can trigger early builds. We do not want that to happen
|
||||
;; during evaluation, so use a sledgehammer to catch such problems.
|
||||
(set! build-things
|
||||
(lambda (store . args)
|
||||
(format (current-error-port)
|
||||
"error: trying to build things during evaluation!~%")
|
||||
(format (current-error-port)
|
||||
"'build-things' arguments: ~s~%" args)
|
||||
(exit 1)))
|
||||
|
||||
;; Call the entry point of FILE and print the resulting job sexp.
|
||||
(pretty-print
|
||||
(match ((module-ref %user-module
|
||||
(if (equal? cuirass? "cuirass")
|
||||
'cuirass-jobs
|
||||
'hydra-jobs))
|
||||
store `((guix
|
||||
. ((file-name . ,%top-srcdir)))))
|
||||
(((names . thunks) ...)
|
||||
(map (lambda (job thunk)
|
||||
(format (current-error-port) "evaluating '~a'... " job)
|
||||
(force-output (current-error-port))
|
||||
(cons job
|
||||
(assert-valid-job job
|
||||
(call-with-time-display thunk))))
|
||||
names thunks)))
|
||||
port))))
|
||||
((command _ ...)
|
||||
(format (current-error-port) "Usage: ~a FILE [cuirass]
|
||||
Evaluate the Hydra or Cuirass jobs defined in FILE.~%"
|
||||
command)
|
||||
(exit 1)))
|
||||
|
||||
;;; Local Variables:
|
||||
;;; eval: (put 'call-with-time 'scheme-indent-function 1)
|
||||
;;; End:
|
||||
|
||||
+65
-168
@@ -1,6 +1,5 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2017 Jan Nieuwenhuizen <janneke@gnu.org>
|
||||
;;; Copyright © 2012, 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
@@ -39,16 +38,12 @@
|
||||
|
||||
(use-modules (guix config)
|
||||
(guix store)
|
||||
(guix grafts)
|
||||
(guix profiles)
|
||||
(guix packages)
|
||||
(guix derivations)
|
||||
(guix monads)
|
||||
((guix licenses) #:select (gpl3+))
|
||||
((guix utils) #:select (%current-system))
|
||||
((guix scripts system) #:select (read-operating-system))
|
||||
((guix scripts pack)
|
||||
#:select (lookup-compressor self-contained-tarball))
|
||||
(gnu packages)
|
||||
(gnu packages gcc)
|
||||
(gnu packages base)
|
||||
@@ -58,11 +53,11 @@
|
||||
(gnu packages compression)
|
||||
(gnu packages multiprecision)
|
||||
(gnu packages make-bootstrap)
|
||||
(gnu packages commencement)
|
||||
(gnu packages package-management)
|
||||
(gnu system)
|
||||
(gnu system vm)
|
||||
(gnu system install)
|
||||
(gnu tests)
|
||||
(srfi srfi-1)
|
||||
(srfi srfi-26)
|
||||
(ice-9 match))
|
||||
@@ -75,20 +70,16 @@
|
||||
(define* (package->alist store package system
|
||||
#:optional (package-derivation package-derivation))
|
||||
"Convert PACKAGE to an alist suitable for Hydra."
|
||||
(parameterize ((%graft? #f))
|
||||
`((derivation . ,(derivation-file-name
|
||||
(package-derivation store package system
|
||||
#:graft? #f)))
|
||||
(description . ,(package-synopsis package))
|
||||
(long-description . ,(package-description package))
|
||||
(license . ,(package-license package))
|
||||
(home-page . ,(package-home-page package))
|
||||
(maintainers . ("bug-guix@gnu.org"))
|
||||
(max-silent-time . ,(or (assoc-ref (package-properties package)
|
||||
'max-silent-time)
|
||||
3600)) ;1 hour by default
|
||||
(timeout . ,(or (assoc-ref (package-properties package) 'timeout)
|
||||
72000))))) ;20 hours by default
|
||||
`((derivation . ,(derivation-file-name
|
||||
(package-derivation store package system
|
||||
#:graft? #f)))
|
||||
(description . ,(package-synopsis package))
|
||||
(long-description . ,(package-description package))
|
||||
(license . ,(package-license package))
|
||||
(home-page . ,(package-home-page package))
|
||||
(maintainers . ("bug-guix@gnu.org"))
|
||||
(timeout . ,(or (assoc-ref (package-properties package) 'timeout)
|
||||
72000)))) ; 20 hours by default
|
||||
|
||||
(define (package-job store job-name package system)
|
||||
"Return a job called JOB-NAME that builds PACKAGE on SYSTEM."
|
||||
@@ -112,10 +103,10 @@ SYSTEM."
|
||||
;; chain.)
|
||||
(list gcc-4.8 gcc-4.9 gcc-5 glibc binutils
|
||||
gmp mpfr mpc coreutils findutils diffutils patch sed grep
|
||||
gawk gnu-gettext hello guile-2.0 guile-2.2 zlib gzip xz
|
||||
gawk gnu-gettext hello guile-2.0 zlib gzip xz
|
||||
%bootstrap-binaries-tarball
|
||||
%binutils-bootstrap-tarball
|
||||
(%glibc-bootstrap-tarball)
|
||||
%glibc-bootstrap-tarball
|
||||
%gcc-bootstrap-tarball
|
||||
%guile-bootstrap-tarball
|
||||
%bootstrap-tarballs))
|
||||
@@ -125,15 +116,13 @@ SYSTEM."
|
||||
|
||||
(define %cross-targets
|
||||
'("mips64el-linux-gnu"
|
||||
"mips64el-linux-gnuabi64"
|
||||
"arm-linux-gnueabihf"
|
||||
"aarch64-linux-gnu"
|
||||
"powerpc-linux-gnu"
|
||||
"i586-pc-gnu" ;aka. GNU/Hurd
|
||||
"i686-w64-mingw32"))
|
||||
"mips64el-linux-gnuabi64"))
|
||||
|
||||
(define %guixsd-supported-systems
|
||||
'("x86_64-linux" "i686-linux"))
|
||||
(define (demo-os)
|
||||
"Return the \"demo\" 'operating-system' structure."
|
||||
(let* ((dir (dirname (assoc-ref (current-source-location) 'filename)))
|
||||
(file (string-append dir "/demo-os.scm")))
|
||||
(read-operating-system file)))
|
||||
|
||||
(define (qemu-jobs store system)
|
||||
"Return a list of jobs that build QEMU images for SYSTEM."
|
||||
@@ -149,58 +138,26 @@ system.")
|
||||
(define (->job name drv)
|
||||
(let ((name (symbol-append name (string->symbol ".")
|
||||
(string->symbol system))))
|
||||
`(,name . ,(lambda ()
|
||||
(parameterize ((%graft? #f))
|
||||
(->alist drv))))))
|
||||
`(,name . ,(cut ->alist drv))))
|
||||
|
||||
(define MiB
|
||||
(expt 2 20))
|
||||
|
||||
(if (member system %guixsd-supported-systems)
|
||||
(list (->job 'usb-image
|
||||
(if (member system '("x86_64-linux" "i686-linux"))
|
||||
(list (->job 'qemu-image
|
||||
(run-with-store store
|
||||
(mbegin %store-monad
|
||||
(set-guile-for-build (default-guile))
|
||||
(system-qemu-image (demo-os)
|
||||
#:disk-image-size
|
||||
(* 1400 MiB))))) ; 1.4 GiB
|
||||
(->job 'usb-image
|
||||
(run-with-store store
|
||||
(mbegin %store-monad
|
||||
(set-guile-for-build (default-guile))
|
||||
(system-disk-image installation-os
|
||||
#:disk-image-size
|
||||
(* 1024 MiB)))))
|
||||
(->job 'iso9660-image
|
||||
(run-with-store store
|
||||
(mbegin %store-monad
|
||||
(set-guile-for-build (default-guile))
|
||||
(system-disk-image installation-os
|
||||
#:file-system-type
|
||||
"iso9660")))))
|
||||
'()))
|
||||
|
||||
(define (system-test-jobs store system)
|
||||
"Return a list of jobs for the system tests."
|
||||
(define (test->thunk test)
|
||||
(lambda ()
|
||||
(define drv
|
||||
(run-with-store store
|
||||
(mbegin %store-monad
|
||||
(set-current-system system)
|
||||
(set-grafting #f)
|
||||
(set-guile-for-build (default-guile))
|
||||
(system-test-value test))))
|
||||
|
||||
`((derivation . ,(derivation-file-name drv))
|
||||
(description . ,(format #f "GuixSD '~a' system test"
|
||||
(system-test-name test)))
|
||||
(long-description . ,(system-test-description test))
|
||||
(license . ,gpl3+)
|
||||
(home-page . ,%guix-home-page-url)
|
||||
(maintainers . ("bug-guix@gnu.org")))))
|
||||
|
||||
(define (->job test)
|
||||
(let ((name (string->symbol
|
||||
(string-append "test." (system-test-name test)
|
||||
"." system))))
|
||||
(cons name (test->thunk test))))
|
||||
|
||||
(if (member system %guixsd-supported-systems)
|
||||
(map ->job (all-system-tests))
|
||||
(* 860 MiB))))))
|
||||
'()))
|
||||
|
||||
(define (tarball-jobs store system)
|
||||
@@ -217,21 +174,14 @@ all its dependencies, and ready to be installed on non-GuixSD distributions.")
|
||||
(define (->job name drv)
|
||||
(let ((name (symbol-append name (string->symbol ".")
|
||||
(string->symbol system))))
|
||||
`(,name . ,(lambda ()
|
||||
(parameterize ((%graft? #f))
|
||||
(->alist drv))))))
|
||||
`(,name . ,(cut ->alist drv))))
|
||||
|
||||
;; XXX: Add a job for the stable Guix?
|
||||
(list (->job 'binary-tarball
|
||||
(run-with-store store
|
||||
(mbegin %store-monad
|
||||
(set-guile-for-build (default-guile))
|
||||
(>>= (profile-derivation (packages->manifest (list guix)))
|
||||
(lambda (profile)
|
||||
(self-contained-tarball "guix-binary" profile
|
||||
#:localstatedir? #t
|
||||
#:compressor
|
||||
(lookup-compressor "xz")))))
|
||||
(self-contained-tarball))
|
||||
#:system system))))
|
||||
|
||||
(define job-name
|
||||
@@ -246,41 +196,17 @@ all its dependencies, and ready to be installed on non-GuixSD distributions.")
|
||||
(match (package-transitive-inputs package)
|
||||
(((_ inputs _ ...) ...)
|
||||
inputs))))
|
||||
(%final-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 (symbol-append 'base. (job-name package))
|
||||
package system))
|
||||
#f)
|
||||
((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))))
|
||||
(package-job store (job-name package) package system))
|
||||
(else
|
||||
#f)))))
|
||||
|
||||
(define (all-packages)
|
||||
"Return the list of packages to build."
|
||||
(define (adjust package result)
|
||||
(cond ((package-replacement package)
|
||||
(cons* package ;build both
|
||||
(package-replacement package)
|
||||
result))
|
||||
((package-superseded package)
|
||||
result) ;don't build it
|
||||
(else
|
||||
(cons package result))))
|
||||
|
||||
(fold-packages adjust
|
||||
(fold adjust '() ;include base packages
|
||||
(match (%final-inputs)
|
||||
(((labels packages _ ...) ...)
|
||||
packages)))
|
||||
#:select? (const #t))) ;include hidden packages
|
||||
|
||||
|
||||
;;;
|
||||
;;; Hydra entry point.
|
||||
@@ -291,8 +217,6 @@ valid."
|
||||
(define subset
|
||||
(match (assoc-ref arguments 'subset)
|
||||
("core" 'core) ; only build core packages
|
||||
("hello" 'hello) ; only build hello
|
||||
(((? string?) (? string?) ...) 'list) ; only build selected list of packages
|
||||
(_ 'all))) ; build everything
|
||||
|
||||
(define (cross-jobs system)
|
||||
@@ -301,74 +225,47 @@ valid."
|
||||
;; prevents known-to-fail cross-builds from i686-linux or armhf-linux to
|
||||
;; mips64el-linux-gnuabi64.
|
||||
(and (or (string-prefix? "i686-" system)
|
||||
(string-prefix? "i586-" system)
|
||||
(string-prefix? "armhf-" system))
|
||||
(string-contains target "64"))) ;x86_64, mips64el, aarch64, etc.
|
||||
(string-suffix? "64" target)))
|
||||
|
||||
(define (same? target)
|
||||
;; Return true if SYSTEM and TARGET are the same thing. This is so we
|
||||
;; don't try to cross-compile to 'mips64el-linux-gnu' from
|
||||
;; 'mips64el-linux'.
|
||||
(or (string-contains target system)
|
||||
(and (string-prefix? "armhf" system) ;armhf-linux
|
||||
(string-prefix? "arm" target)))) ;arm-linux-gnueabihf
|
||||
(string-contains target system))
|
||||
|
||||
(define (pointless? target)
|
||||
;; Return #t if it makes no sense to cross-build to TARGET from SYSTEM.
|
||||
(and (string-contains target "mingw")
|
||||
(not (string=? "x86_64-linux" system))))
|
||||
|
||||
(define (either proc1 proc2 proc3)
|
||||
(define (either proc1 proc2)
|
||||
(lambda (x)
|
||||
(or (proc1 x) (proc2 x) (proc3 x))))
|
||||
(or (proc1 x) (proc2 x))))
|
||||
|
||||
(append-map (lambda (target)
|
||||
(map (lambda (package)
|
||||
(package-cross-job store (job-name package)
|
||||
package target system))
|
||||
%packages-to-cross-build))
|
||||
(remove (either from-32-to-64? same? pointless?)
|
||||
%cross-targets)))
|
||||
(remove (either from-32-to-64? same?) %cross-targets)))
|
||||
|
||||
;; Turn off grafts. Grafting is meant to happen on the user's machines.
|
||||
(parameterize ((%graft? #f))
|
||||
;; Return one job for each package, except bootstrap packages.
|
||||
(append-map (lambda (system)
|
||||
(case subset
|
||||
((all)
|
||||
;; Build everything, including replacements.
|
||||
(let ((all (all-packages))
|
||||
(job (lambda (package)
|
||||
(package->job store package
|
||||
system))))
|
||||
(append (filter-map job all)
|
||||
(qemu-jobs store system)
|
||||
(system-test-jobs store system)
|
||||
(tarball-jobs store system)
|
||||
(cross-jobs system))))
|
||||
((core)
|
||||
;; Build core packages only.
|
||||
(append (map (lambda (package)
|
||||
(package-job store (job-name package)
|
||||
package system))
|
||||
%core-packages)
|
||||
(cross-jobs system)))
|
||||
((hello)
|
||||
;; Build hello package only.
|
||||
(if (string=? system (%current-system))
|
||||
(let ((hello (specification->package "hello")))
|
||||
(list (package-job store (job-name hello) hello system)))
|
||||
'()))
|
||||
((list)
|
||||
;; Build selected list of packages only.
|
||||
(if (string=? system (%current-system))
|
||||
(let* ((names (assoc-ref arguments 'subset))
|
||||
(packages (map specification->package names)))
|
||||
(map (lambda (package)
|
||||
(package-job store (job-name package)
|
||||
package system))
|
||||
packages))
|
||||
'()))
|
||||
(else
|
||||
(error "unknown subset" subset))))
|
||||
%hydra-supported-systems)))
|
||||
;; Return one job for each package, except bootstrap packages.
|
||||
(append-map (lambda (system)
|
||||
(case subset
|
||||
((all)
|
||||
;; Build everything.
|
||||
(fold-packages (lambda (package result)
|
||||
(let ((job (package->job store package
|
||||
system)))
|
||||
(if job
|
||||
(cons job result)
|
||||
result)))
|
||||
(append (qemu-jobs store system)
|
||||
(tarball-jobs store system)
|
||||
(cross-jobs system))))
|
||||
((core)
|
||||
;; Build core packages only.
|
||||
(append (map (lambda (package)
|
||||
(package-job store (job-name package)
|
||||
package system))
|
||||
%core-packages)
|
||||
(cross-jobs system)))
|
||||
(else
|
||||
(error "unknown subset" subset))))
|
||||
%hydra-supported-systems))
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2017 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 defines a continuous integration job to build the same modular
|
||||
;;; Guix as 'guix pull', which is defined in (guix self).
|
||||
;;;
|
||||
|
||||
;; Attempt to use our very own Guix modules.
|
||||
(eval-when (compile load eval)
|
||||
|
||||
;; Ignore any available .go, and force recompilation. This is because our
|
||||
;; checkout in the store has mtime set to the epoch, and thus .go files look
|
||||
;; newer, even though they may not correspond.
|
||||
(set! %fresh-auto-compile #t)
|
||||
|
||||
(and=> (assoc-ref (current-source-location) 'filename)
|
||||
(lambda (file)
|
||||
(let ((dir (canonicalize-path
|
||||
(string-append (dirname file) "/../.."))))
|
||||
(format (current-error-port) "prepending ~s to the load path~%"
|
||||
dir)
|
||||
(set! %load-path (cons dir %load-path))))))
|
||||
|
||||
|
||||
(use-modules (guix store)
|
||||
(guix config)
|
||||
(guix utils)
|
||||
(guix grafts)
|
||||
((guix packages) #:select (%hydra-supported-systems))
|
||||
(guix derivations)
|
||||
(guix monads)
|
||||
(guix gexp)
|
||||
(guix self)
|
||||
((guix licenses) #:prefix license:)
|
||||
(srfi srfi-1)
|
||||
(srfi srfi-26)
|
||||
(ice-9 match))
|
||||
|
||||
;; XXX: Debugging hack: since `hydra-eval-guile-jobs' redirects the output
|
||||
;; port to the bit bucket, let us write to the error port instead.
|
||||
(setvbuf (current-error-port) _IOLBF)
|
||||
(set-current-output-port (current-error-port))
|
||||
|
||||
(define* (build-job store source version system)
|
||||
"Return a Hydra job a list building the modular Guix derivation from SOURCE
|
||||
for SYSTEM. Use VERSION as the version identifier."
|
||||
(lambda ()
|
||||
`((derivation . ,(derivation-file-name
|
||||
(parameterize ((%graft? #f))
|
||||
(run-with-store store
|
||||
(lower-object (compiled-guix source
|
||||
#:version version))))))
|
||||
(description . "Modular Guix")
|
||||
(long-description
|
||||
. "This is the modular Guix package as produced by 'guix pull'.")
|
||||
(license . ,license:gpl3+)
|
||||
(home-page . ,%guix-home-page-url)
|
||||
(maintainers . (,%guix-bug-report-address)))))
|
||||
|
||||
(define (hydra-jobs store arguments)
|
||||
"Return Hydra jobs."
|
||||
(define systems
|
||||
(match (filter-map (match-lambda
|
||||
(('system . value) value)
|
||||
(_ #f))
|
||||
arguments)
|
||||
((lst ..1)
|
||||
lst)
|
||||
(_
|
||||
(list (%current-system)))))
|
||||
|
||||
(define guix-checkout
|
||||
(assq-ref arguments 'guix))
|
||||
|
||||
(define version
|
||||
(or (assq-ref guix-checkout 'revision)
|
||||
"0.unknown"))
|
||||
|
||||
(let ((file (assq-ref guix-checkout 'file-name)))
|
||||
(format (current-error-port) "using checkout ~s (~s)~%"
|
||||
guix-checkout file)
|
||||
|
||||
(map (lambda (system)
|
||||
(let ((name (string->symbol
|
||||
(string-append "guix." system))))
|
||||
`(,name
|
||||
. ,(build-job store file version system))))
|
||||
%hydra-supported-systems)))
|
||||
+19
-22
@@ -1,5 +1,5 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
@@ -43,10 +43,12 @@
|
||||
(use-modules (guix store)
|
||||
(guix packages)
|
||||
(guix utils)
|
||||
(guix grafts)
|
||||
(guix derivations)
|
||||
(guix build-system gnu)
|
||||
(gnu packages version-control)
|
||||
(gnu packages package-management)
|
||||
(gnu packages graphviz)
|
||||
(gnu packages man)
|
||||
(srfi srfi-1)
|
||||
(srfi srfi-26)
|
||||
(ice-9 match))
|
||||
@@ -60,15 +62,23 @@
|
||||
#:optional (package-derivation package-derivation))
|
||||
"Convert PACKAGE to an alist suitable for Hydra."
|
||||
`((derivation . ,(derivation-file-name
|
||||
(parameterize ((%graft? #f))
|
||||
(package-derivation store package system
|
||||
#:graft? #f))))
|
||||
(package-derivation store package system)))
|
||||
(description . ,(package-synopsis package))
|
||||
(long-description . ,(package-description package))
|
||||
(license . ,(package-license package))
|
||||
(home-page . ,(package-home-page package))
|
||||
(maintainers . ("bug-guix@gnu.org"))))
|
||||
|
||||
(define (tarball-package checkout)
|
||||
"Return a package that does `make distcheck' from CHECKOUT, a directory
|
||||
containing a Git checkout of Guix."
|
||||
(dist-package (package
|
||||
(inherit guix)
|
||||
(native-inputs `(("graphviz" ,graphviz)
|
||||
("help2man" ,help2man)
|
||||
,@(package-native-inputs guix))))
|
||||
checkout))
|
||||
|
||||
(define (hydra-jobs store arguments)
|
||||
"Return Hydra jobs."
|
||||
(define systems
|
||||
@@ -85,22 +95,9 @@
|
||||
(define guix-checkout
|
||||
(assq-ref arguments 'guix))
|
||||
|
||||
(let ((file (assq-ref guix-checkout 'file-name)))
|
||||
(let ((guix (assq-ref guix-checkout 'file-name)))
|
||||
(format (current-error-port) "using checkout ~s (~s)~%"
|
||||
guix-checkout file)
|
||||
|
||||
guix-checkout guix)
|
||||
`((tarball . ,(cute package->alist store
|
||||
(dist-package guix file)
|
||||
(%current-system)))
|
||||
|
||||
,@(map (lambda (system)
|
||||
(let ((name (string->symbol
|
||||
(string-append "guix." system))))
|
||||
`(,name
|
||||
. ,(cute package->alist store
|
||||
(package
|
||||
(inherit guix)
|
||||
(version "latest")
|
||||
(source file))
|
||||
system))))
|
||||
%hydra-supported-systems))))
|
||||
(tarball-package guix)
|
||||
(%current-system))))))
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2015 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/>.
|
||||
|
||||
|
||||
;;;
|
||||
;;; Build a self-contained tarball containing binaries for Guix and its
|
||||
;;; dependencies.
|
||||
;;;
|
||||
|
||||
(use-modules (guix)
|
||||
(guix ui)
|
||||
(gnu system install)
|
||||
(ice-9 match))
|
||||
|
||||
(define copy-file*
|
||||
(lift2 copy-file %store-monad))
|
||||
|
||||
(define rename-file*
|
||||
(lift2 rename-file %store-monad))
|
||||
|
||||
(match (command-line)
|
||||
((_ system file)
|
||||
(with-store store
|
||||
(run-with-store store
|
||||
(mlet %store-monad ((tarball (self-contained-tarball)))
|
||||
(mbegin %store-monad
|
||||
(show-what-to-build* (list tarball))
|
||||
(built-derivations (list tarball))
|
||||
(copy-file* (derivation->output-path tarball)
|
||||
(string-append file ".part"))
|
||||
(rename-file* (string-append file ".part") file)))
|
||||
#:system system))))
|
||||
@@ -1,87 +0,0 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2016 Ludovic Courtès <ludo@gnu.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
;;; GNU Guix is free software; you can redistribute it and/or modify it
|
||||
;;; under the terms of the GNU General Public License as published by
|
||||
;;; the Free Software Foundation; either version 3 of the License, or (at
|
||||
;;; your option) any later version.
|
||||
;;;
|
||||
;;; GNU Guix is distributed in the hope that it will be useful, but
|
||||
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;;; GNU General Public License for more details.
|
||||
;;;
|
||||
;;; You should have received a copy of the GNU General Public License
|
||||
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
(define-module (run-system-tests)
|
||||
#:use-module (gnu tests)
|
||||
#:use-module (guix store)
|
||||
#:use-module (guix monads)
|
||||
#:use-module (guix derivations)
|
||||
#:use-module (guix ui)
|
||||
#:use-module (srfi srfi-1)
|
||||
#:use-module (srfi srfi-34)
|
||||
#:use-module (ice-9 match)
|
||||
#:export (run-system-tests))
|
||||
|
||||
(define (built-derivations* drv)
|
||||
(lambda (store)
|
||||
(guard (c ((nix-protocol-error? c)
|
||||
(values #f store)))
|
||||
(values (build-derivations store drv) store))))
|
||||
|
||||
(define (filterm mproc lst) ;XXX: move to (guix monads)
|
||||
(with-monad %store-monad
|
||||
(>>= (foldm %store-monad
|
||||
(lambda (item result)
|
||||
(mlet %store-monad ((keep? (mproc item)))
|
||||
(return (if keep?
|
||||
(cons item result)
|
||||
result))))
|
||||
'()
|
||||
lst)
|
||||
(lift1 reverse %store-monad))))
|
||||
|
||||
(define (run-system-tests . args)
|
||||
(define tests
|
||||
;; Honor the 'TESTS' environment variable so that one can select a subset
|
||||
;; of tests to run in the usual way:
|
||||
;;
|
||||
;; make check-system TESTS=installed-os
|
||||
(match (getenv "TESTS")
|
||||
(#f
|
||||
(all-system-tests))
|
||||
((= string-tokenize (tests ...))
|
||||
(filter (lambda (test)
|
||||
(member (system-test-name test) tests))
|
||||
(all-system-tests)))))
|
||||
|
||||
(format (current-error-port) "Running ~a system tests...~%"
|
||||
(length tests))
|
||||
|
||||
(with-store store
|
||||
(run-with-store store
|
||||
(mlet* %store-monad ((drv (mapm %store-monad system-test-value tests))
|
||||
(out -> (map derivation->output-path drv)))
|
||||
(mbegin %store-monad
|
||||
(show-what-to-build* drv)
|
||||
(set-build-options* #:keep-going? #t #:keep-failed? #t
|
||||
#:print-build-trace #t
|
||||
#:fallback? #t)
|
||||
(built-derivations* drv)
|
||||
(mlet %store-monad ((valid (filterm (store-lift valid-path?)
|
||||
out))
|
||||
(failed (filterm (store-lift
|
||||
(negate valid-path?))
|
||||
out)))
|
||||
(format #t "TOTAL: ~a\n" (length drv))
|
||||
(for-each (lambda (item)
|
||||
(format #t "PASS: ~a~%" item))
|
||||
valid)
|
||||
(for-each (lambda (item)
|
||||
(format #t "FAIL: ~a~%" item))
|
||||
failed)
|
||||
(exit (null? failed))))))))
|
||||
@@ -1,184 +0,0 @@
|
||||
;;;; test-driver.scm - Guile test driver for Automake testsuite harness
|
||||
|
||||
(define script-version "2017-03-22.13") ;UTC
|
||||
|
||||
;;; Copyright © 2015, 2016 Mathieu Lirzin <mthl@gnu.org>
|
||||
;;;
|
||||
;;; This program 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.
|
||||
;;;
|
||||
;;; This program 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 script provides a Guile test driver using the SRFI-64 Scheme API for
|
||||
;;; test suites. SRFI-64 is distributed with Guile since version 2.0.9.
|
||||
;;;
|
||||
;;;; Code:
|
||||
|
||||
(use-modules (ice-9 getopt-long)
|
||||
(ice-9 pretty-print)
|
||||
(srfi srfi-26)
|
||||
(srfi srfi-64))
|
||||
|
||||
(define (show-help)
|
||||
(display "Usage:
|
||||
test-driver --test-name=NAME --log-file=PATH --trs-file=PATH
|
||||
[--expect-failure={yes|no}] [--color-tests={yes|no}]
|
||||
[--enable-hard-errors={yes|no}] [--brief={yes|no}}] [--]
|
||||
TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS]
|
||||
The '--test-name', '--log-file' and '--trs-file' options are mandatory.\n"))
|
||||
|
||||
(define %options
|
||||
'((test-name (value #t))
|
||||
(log-file (value #t))
|
||||
(trs-file (value #t))
|
||||
(color-tests (value #t))
|
||||
(expect-failure (value #t)) ;XXX: not implemented yet
|
||||
(enable-hard-errors (value #t)) ;not implemented in SRFI-64
|
||||
(brief (value #t))
|
||||
(help (single-char #\h) (value #f))
|
||||
(version (single-char #\V) (value #f))))
|
||||
|
||||
(define (option->boolean options key)
|
||||
"Return #t if the value associated with KEY in OPTIONS is \"yes\"."
|
||||
(and=> (option-ref options key #f) (cut string=? <> "yes")))
|
||||
|
||||
(define* (test-display field value #:optional (port (current-output-port))
|
||||
#:key pretty?)
|
||||
"Display \"FIELD: VALUE\\n\" on PORT."
|
||||
(if pretty?
|
||||
(begin
|
||||
(format port "~A:~%" field)
|
||||
(pretty-print value port #:per-line-prefix "+ "))
|
||||
(format port "~A: ~S~%" field value)))
|
||||
|
||||
(define* (result->string symbol #:key colorize?)
|
||||
"Return SYMBOL as an upper case string. Use colors when COLORIZE is #t."
|
||||
(let ((result (string-upcase (symbol->string symbol))))
|
||||
(if colorize?
|
||||
(string-append (case symbol
|
||||
((pass) "[0;32m") ;green
|
||||
((xfail) "[1;32m") ;light green
|
||||
((skip) "[1;34m") ;blue
|
||||
((fail xpass) "[0;31m") ;red
|
||||
((error) "[0;35m")) ;magenta
|
||||
result
|
||||
"[m") ;no color
|
||||
result)))
|
||||
|
||||
(define* (test-runner-gnu test-name #:key color? brief? out-port trs-port)
|
||||
"Return an custom SRFI-64 test runner. TEST-NAME is a string specifying the
|
||||
file name of the current the test. COLOR? specifies whether to use colors,
|
||||
and BRIEF?, well, you know. OUT-PORT and TRS-PORT must be output ports. The
|
||||
current output port is supposed to be redirected to a '.log' file."
|
||||
|
||||
(define (test-on-test-begin-gnu runner)
|
||||
;; Procedure called at the start of an individual test case, before the
|
||||
;; test expression (and expected value) are evaluated.
|
||||
(let ((result (cute assq-ref (test-result-alist runner) <>)))
|
||||
(format #t "test-name: ~A~%" (result 'test-name))
|
||||
(format #t "location: ~A~%"
|
||||
(string-append (result 'source-file) ":"
|
||||
(number->string (result 'source-line))))
|
||||
(test-display "source" (result 'source-form) #:pretty? #t)))
|
||||
|
||||
(define (test-on-test-end-gnu runner)
|
||||
;; Procedure called at the end of an individual test case, when the result
|
||||
;; of the test is available.
|
||||
(let* ((results (test-result-alist runner))
|
||||
(result? (cut assq <> results))
|
||||
(result (cut assq-ref results <>)))
|
||||
(unless brief?
|
||||
;; Display the result of each test case on the console.
|
||||
(format out-port "~A: ~A - ~A~%"
|
||||
(result->string (test-result-kind runner) #:colorize? color?)
|
||||
test-name (test-runner-test-name runner)))
|
||||
(when (result? 'expected-value)
|
||||
(test-display "expected-value" (result 'expected-value)))
|
||||
(when (result? 'expected-error)
|
||||
(test-display "expected-error" (result 'expected-error) #:pretty? #t))
|
||||
(when (result? 'actual-value)
|
||||
(test-display "actual-value" (result 'actual-value)))
|
||||
(when (result? 'actual-error)
|
||||
(test-display "actual-error" (result 'actual-error) #:pretty? #t))
|
||||
(format #t "result: ~a~%" (result->string (result 'result-kind)))
|
||||
(newline)
|
||||
(format trs-port ":test-result: ~A ~A~%"
|
||||
(result->string (test-result-kind runner))
|
||||
(test-runner-test-name runner))))
|
||||
|
||||
(define (test-on-group-end-gnu runner)
|
||||
;; Procedure called by a 'test-end', including at the end of a test-group.
|
||||
(let ((fail (or (positive? (test-runner-fail-count runner))
|
||||
(positive? (test-runner-xpass-count runner))))
|
||||
(skip (or (positive? (test-runner-skip-count runner))
|
||||
(positive? (test-runner-xfail-count runner)))))
|
||||
;; XXX: The global results need some refinements for XPASS.
|
||||
(format trs-port ":global-test-result: ~A~%"
|
||||
(if fail "FAIL" (if skip "SKIP" "PASS")))
|
||||
(format trs-port ":recheck: ~A~%"
|
||||
(if fail "yes" "no"))
|
||||
(format trs-port ":copy-in-global-log: ~A~%"
|
||||
(if (or fail skip) "yes" "no"))
|
||||
(when brief?
|
||||
;; Display the global test group result on the console.
|
||||
(format out-port "~A: ~A~%"
|
||||
(result->string (if fail 'fail (if skip 'skip 'pass))
|
||||
#:colorize? color?)
|
||||
test-name))
|
||||
#f))
|
||||
|
||||
(let ((runner (test-runner-null)))
|
||||
(test-runner-on-test-begin! runner test-on-test-begin-gnu)
|
||||
(test-runner-on-test-end! runner test-on-test-end-gnu)
|
||||
(test-runner-on-group-end! runner test-on-group-end-gnu)
|
||||
(test-runner-on-bad-end-name! runner test-on-bad-end-name-simple)
|
||||
runner))
|
||||
|
||||
|
||||
;;;
|
||||
;;; Entry point.
|
||||
;;;
|
||||
|
||||
(define (main . args)
|
||||
(let* ((opts (getopt-long (command-line) %options))
|
||||
(option (cut option-ref opts <> <>)))
|
||||
(cond
|
||||
((option 'help #f) (show-help))
|
||||
((option 'version #f) (format #t "test-driver.scm ~A" script-version))
|
||||
(else
|
||||
(let ((log (open-file (option 'log-file "") "w0"))
|
||||
(trs (open-file (option 'trs-file "") "wl"))
|
||||
(out (duplicate-port (current-output-port) "wl")))
|
||||
(redirect-port log (current-output-port))
|
||||
(redirect-port log (current-warning-port))
|
||||
(redirect-port log (current-error-port))
|
||||
(test-with-runner
|
||||
(test-runner-gnu (option 'test-name #f)
|
||||
#:color? (option->boolean opts 'color-tests)
|
||||
#:brief? (option->boolean opts 'brief)
|
||||
#:out-port out #:trs-port trs)
|
||||
(load-from-path (option 'test-name #f)))
|
||||
(close-port log)
|
||||
(close-port trs)
|
||||
(close-port out))))
|
||||
(exit 0)))
|
||||
|
||||
;;; Local Variables:
|
||||
;;; eval: (add-hook 'write-file-functions 'time-stamp)
|
||||
;;; time-stamp-start: "(define script-version \""
|
||||
;;; time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
;;; time-stamp-time-zone: "UTC"
|
||||
;;; time-stamp-end: "\") ;UTC"
|
||||
;;; End:
|
||||
|
||||
;;;; test-driver.scm ends here.
|
||||
@@ -1,161 +0,0 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2017 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/>.
|
||||
|
||||
;;; Commentary:
|
||||
;;;
|
||||
;;; This script updates the list of new and updated packages in 'NEWS'.
|
||||
;;;
|
||||
;;; Code:
|
||||
|
||||
(use-modules (gnu) (guix)
|
||||
(guix build utils)
|
||||
((guix ui) #:select (fill-paragraph))
|
||||
(srfi srfi-1)
|
||||
(srfi srfi-11)
|
||||
(ice-9 match)
|
||||
(ice-9 rdelim)
|
||||
(ice-9 regex)
|
||||
(ice-9 pretty-print))
|
||||
|
||||
(define %header-rx
|
||||
(make-regexp "^\\* Changes in (version )?([0-9.]+) \\(since ([0-9.]+)\\)"))
|
||||
|
||||
(define (NEWS->versions port)
|
||||
"Return two values: the previous version and the current version as read
|
||||
from PORT, which is an input port on the 'NEWS' file."
|
||||
(let loop ()
|
||||
(let ((line (read-line port)))
|
||||
(cond ((eof-object? line)
|
||||
(error "failed to determine previous and current version"
|
||||
port))
|
||||
((regexp-exec %header-rx line)
|
||||
=>
|
||||
(lambda (match)
|
||||
(values (match:substring match 3)
|
||||
(match:substring match 2))))
|
||||
(else
|
||||
(loop))))))
|
||||
|
||||
(define (skip-to-org-heading port)
|
||||
"Read from PORT until an Org heading is found."
|
||||
(let loop ()
|
||||
(let ((next (peek-char port)))
|
||||
(cond ((eqv? next #\*)
|
||||
#t)
|
||||
((eof-object? next)
|
||||
(error "next heading could not be found"))
|
||||
(else
|
||||
(read-line port)
|
||||
(loop))))))
|
||||
|
||||
(define (rewrite-org-section input output heading-rx proc)
|
||||
"Write to OUTPUT the text read from INPUT, but with the first Org section
|
||||
matching HEADING-RX replaced by NEW-HEADING and CONTENTS."
|
||||
(let loop ()
|
||||
(let ((line (read-line input)))
|
||||
(cond ((eof-object? line)
|
||||
(error "failed to match heading regexp" heading-rx))
|
||||
((regexp-exec heading-rx line)
|
||||
=>
|
||||
(lambda (match)
|
||||
(proc match output)
|
||||
(skip-to-org-heading input)
|
||||
(dump-port input output)
|
||||
#t))
|
||||
(else
|
||||
(display line output)
|
||||
(newline output)
|
||||
(loop))))))
|
||||
|
||||
(define (enumeration->paragraph lst)
|
||||
"Turn LST, a list of strings, into a single string that is a ready-to-print
|
||||
paragraph."
|
||||
(fill-paragraph (string-join (sort lst string<?) ", ")
|
||||
75))
|
||||
|
||||
(define (write-packages-added news-file old new)
|
||||
"Write to NEWS-FILE the list of packages added between OLD and NEW."
|
||||
(let ((added (lset-difference string=? (map car new) (map car old))))
|
||||
(with-atomic-file-replacement news-file
|
||||
(lambda (input output)
|
||||
(rewrite-org-section input output
|
||||
(make-regexp "^(\\*+) (.*) new packages")
|
||||
(lambda (match port)
|
||||
(let ((stars (match:substring match 1)))
|
||||
(format port
|
||||
"~a ~a new packages~%~%~a~%~%"
|
||||
stars (length added)
|
||||
(enumeration->paragraph added)))))))))
|
||||
|
||||
(define (write-packages-updates news-file old new)
|
||||
"Write to NEWS-FILE the list of packages upgraded between OLD and NEW."
|
||||
(let ((upgraded (filter-map (match-lambda
|
||||
((package . new-version)
|
||||
(match (assoc package old)
|
||||
((_ . old-version)
|
||||
(and (version>? new-version old-version)
|
||||
(string-append package "@"
|
||||
new-version)))
|
||||
(_ #f))))
|
||||
new)))
|
||||
(with-atomic-file-replacement news-file
|
||||
(lambda (input output)
|
||||
(rewrite-org-section input output
|
||||
(make-regexp "^(\\*+) (.*) package updates")
|
||||
(lambda (match port)
|
||||
(let ((stars (match:substring match 1)))
|
||||
(format port
|
||||
"~a ~a package updates~%~%~a~%~%"
|
||||
stars (length upgraded)
|
||||
(enumeration->paragraph upgraded)))))))))
|
||||
|
||||
|
||||
(define (main . args)
|
||||
(match args
|
||||
((news-file data-directory)
|
||||
;; Don't browse things listed in the user's $GUIX_PACKAGE_PATH. Here we
|
||||
;; assume that the last item in (%package-module-path) is the distro
|
||||
;; directory.
|
||||
(parameterize ((%package-module-path
|
||||
(list (last (%package-module-path)))))
|
||||
(define (package-file version)
|
||||
(string-append data-directory "/packages-"
|
||||
version ".txt"))
|
||||
|
||||
(let-values (((previous-version new-version)
|
||||
(call-with-input-file news-file NEWS->versions)))
|
||||
(let* ((old (call-with-input-file (package-file previous-version)
|
||||
read))
|
||||
(new (fold-packages (lambda (p r)
|
||||
(alist-cons (package-name p) (package-version p)
|
||||
r))
|
||||
'())))
|
||||
(call-with-output-file (package-file new-version)
|
||||
(lambda (port)
|
||||
(pretty-print new port)))
|
||||
|
||||
(write-packages-added news-file old new)
|
||||
(write-packages-updates news-file old new)))))
|
||||
(x
|
||||
(format (current-error-port) "Usage: update-NEWS NEWS-FILE DATA-DIRECTORY
|
||||
|
||||
Update the list of new and updated packages in NEWS-FILE using the
|
||||
previous-version package list from DATA-DIRECTORY.\n")
|
||||
(exit 1))))
|
||||
|
||||
(apply main (cdr (command-line)))
|
||||
@@ -1,144 +0,0 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2017 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/>.
|
||||
|
||||
;;; Commentary:
|
||||
;;;
|
||||
;;; This scripts updates the definition of the 'guix' package in Guix for the
|
||||
;;; current commit. It requires Git to be installed.
|
||||
;;;
|
||||
;;; Code:
|
||||
|
||||
(use-modules (guix)
|
||||
(guix git-download)
|
||||
(guix upstream)
|
||||
(guix utils)
|
||||
(guix base32)
|
||||
(guix build utils)
|
||||
(gnu packages package-management)
|
||||
(ice-9 match))
|
||||
|
||||
(define %top-srcdir
|
||||
(string-append (current-source-directory) "/.."))
|
||||
|
||||
(define version-controlled?
|
||||
(git-predicate %top-srcdir))
|
||||
|
||||
(define (package-definition-location)
|
||||
"Return the source properties of the definition of the 'guix' package."
|
||||
(call-with-input-file (location-file (package-location guix))
|
||||
(lambda (port)
|
||||
(let loop ()
|
||||
(match (read port)
|
||||
((? eof-object?)
|
||||
(error "definition of 'guix' package could not be found"
|
||||
(port-filename port)))
|
||||
(('define-public 'guix value)
|
||||
(source-properties value))
|
||||
(_
|
||||
(loop)))))))
|
||||
|
||||
(define* (update-definition commit hash
|
||||
#:key version old-hash)
|
||||
"Return a one-argument procedure that takes a string, the definition of the
|
||||
'guix' package, and returns a string, the update definition for VERSION,
|
||||
COMMIT."
|
||||
(define (linear-offset str line column)
|
||||
;; Return the offset in characters to reach LINE and COLUMN (both
|
||||
;; zero-indexed) in STR.
|
||||
(call-with-input-string str
|
||||
(lambda (port)
|
||||
(let loop ((offset 0))
|
||||
(cond ((and (= (port-column port) column)
|
||||
(= (port-line port) line))
|
||||
offset)
|
||||
((eof-object? (read-char port))
|
||||
(error "line and column not reached!"
|
||||
str))
|
||||
(else
|
||||
(loop (+ 1 offset))))))))
|
||||
|
||||
(define (update-hash str)
|
||||
;; Replace OLD-HASH with HASH in STR.
|
||||
(string-replace-substring str
|
||||
(bytevector->nix-base32-string old-hash)
|
||||
(bytevector->nix-base32-string hash)))
|
||||
|
||||
(lambda (str)
|
||||
(match (call-with-input-string str read)
|
||||
(('let (('version old-version)
|
||||
('commit old-commit)
|
||||
('revision old-revision))
|
||||
defn)
|
||||
(let* ((location (source-properties defn))
|
||||
(line (assq-ref location 'line))
|
||||
(column 0)
|
||||
(offset (linear-offset str line column)))
|
||||
(string-append (format #f "(let ((version \"~a\")
|
||||
(commit \"~a\")
|
||||
(revision ~a))\n"
|
||||
(or version old-version)
|
||||
commit
|
||||
(if (and version
|
||||
(not (string=? version old-version)))
|
||||
0
|
||||
(+ 1 old-revision)))
|
||||
(string-drop (update-hash str) offset))))
|
||||
(exp
|
||||
(error "'guix' package definition is not as expected" exp)))))
|
||||
|
||||
|
||||
(define (main . args)
|
||||
(match args
|
||||
((commit version)
|
||||
(with-store store
|
||||
(let* ((source (add-to-store store
|
||||
"guix-checkout" ;dummy name
|
||||
#t "sha256" %top-srcdir
|
||||
#:select? version-controlled?))
|
||||
(hash (query-path-hash store source))
|
||||
(location (package-definition-location))
|
||||
(old-hash (origin-sha256 (package-source guix))))
|
||||
(edit-expression location
|
||||
(update-definition commit hash
|
||||
#:old-hash old-hash
|
||||
#:version version))
|
||||
|
||||
;; Re-add SOURCE to the store, but this time under the real name used
|
||||
;; in the 'origin'. This allows us to build the package without
|
||||
;; having to make a real checkout; thus, it also works when working
|
||||
;; on a private branch.
|
||||
(reload-module
|
||||
(resolve-module '(gnu packages package-management)))
|
||||
|
||||
(let* ((source (add-to-store store
|
||||
(origin-file-name (package-source guix))
|
||||
#t "sha256" source))
|
||||
(root (store-path-package-name source)))
|
||||
|
||||
;; Add an indirect GC root for SOURCE in the current directory.
|
||||
(false-if-exception (delete-file root))
|
||||
(symlink source root)
|
||||
(add-indirect-root store root)
|
||||
|
||||
(format #t "source code for commit ~a: ~a (GC root: ~a)~%"
|
||||
commit source root)))))
|
||||
((commit)
|
||||
;; Automatically deduce the version and revision numbers.
|
||||
(main commit #f))))
|
||||
|
||||
(apply main (cdr (command-line)))
|
||||
+13
-32
@@ -5,7 +5,6 @@ AC_MSG_RESULT([$guix_build_daemon])
|
||||
|
||||
dnl C++ environment. This macro must be used unconditionnaly.
|
||||
AC_PROG_CXX
|
||||
AM_PROG_AR
|
||||
AC_LANG([C++])
|
||||
|
||||
if test "x$guix_build_daemon" = "xyes"; then
|
||||
@@ -15,6 +14,14 @@ if test "x$guix_build_daemon" = "xyes"; then
|
||||
AC_PROG_RANLIB
|
||||
AC_CONFIG_HEADER([nix/config.h])
|
||||
|
||||
dnl Decompressors, for use by the substituter.
|
||||
AC_PATH_PROG([GZIP], [gzip])
|
||||
AC_PATH_PROG([BZIP2], [bzip2])
|
||||
AC_PATH_PROG([XZ], [xz])
|
||||
AC_SUBST([GZIP])
|
||||
AC_SUBST([BZIP2])
|
||||
AC_SUBST([XZ])
|
||||
|
||||
dnl Use 64-bit file system calls so that we can support files > 2 GiB.
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
@@ -111,50 +118,24 @@ if test "x$guix_build_daemon" = "xyes"; then
|
||||
dnl Check for <linux/fs.h> (for immutable file support).
|
||||
AC_CHECK_HEADERS([linux/fs.h])
|
||||
|
||||
dnl Determine the appropriate default list of substitute URLs.
|
||||
GUILE_MODULE_AVAILABLE([have_gnutls], [(gnutls)])
|
||||
if test "x$have_gnutls" = "xyes"; then
|
||||
guix_substitute_urls="https://mirror.hydra.gnu.org"
|
||||
else
|
||||
AC_MSG_WARN([GnuTLS is missing, substitutes will be downloaded in the clear])
|
||||
guix_substitute_urls="http://mirror.hydra.gnu.org"
|
||||
fi
|
||||
AC_MSG_CHECKING([for default substitute URLs])
|
||||
AC_MSG_RESULT([$guix_substitute_urls])
|
||||
|
||||
AC_DEFINE_UNQUOTED([GUIX_SUBSTITUTE_URLS], ["$guix_substitute_urls"],
|
||||
[Default list of substitute URLs used by 'guix-daemon'.])
|
||||
|
||||
dnl Check whether the 'offload' build hook can be built (uses
|
||||
dnl 'restore-file-set', which requires unbuffered custom binary input
|
||||
dnl ports from Guile >= 2.0.10.)
|
||||
GUIX_CHECK_UNBUFFERED_CBIP
|
||||
guix_build_daemon_offload="$ac_cv_guix_cbips_support_setvbuf"
|
||||
|
||||
dnl Check for Guile-SSH, which is required by 'guix offload'.
|
||||
GUIX_CHECK_GUILE_SSH
|
||||
|
||||
case "x$ac_cv_guix_cbips_support_setvbuf$guix_cv_have_recent_guile_ssh" in
|
||||
xyesyes)
|
||||
guix_build_daemon_offload="yes"
|
||||
AC_DEFINE([HAVE_DAEMON_OFFLOAD_HOOK], [1],
|
||||
[Define if the daemon's 'offload' build hook is being built (requires Guile-SSH).])
|
||||
;;
|
||||
*)
|
||||
guix_build_daemon_offload="no"
|
||||
;;
|
||||
esac
|
||||
if test "x$guix_build_daemon_offload" = "xyes"; then
|
||||
AC_DEFINE([HAVE_DAEMON_OFFLOAD_HOOK], [1],
|
||||
[Define if the daemon's 'offload' build hook is being built.])
|
||||
fi
|
||||
|
||||
dnl Temporary directory used to store the daemon's data.
|
||||
GUIX_TEST_ROOT_DIRECTORY
|
||||
GUIX_TEST_ROOT="$ac_cv_guix_test_root"
|
||||
AC_SUBST([GUIX_TEST_ROOT])
|
||||
|
||||
GUIX_CHECK_LOCALSTATEDIR
|
||||
|
||||
AC_CONFIG_FILES([nix/scripts/list-runtime-roots],
|
||||
[chmod +x nix/scripts/list-runtime-roots])
|
||||
AC_CONFIG_FILES([nix/scripts/download],
|
||||
[chmod +x nix/scripts/download])
|
||||
AC_CONFIG_FILES([nix/scripts/substitute],
|
||||
[chmod +x nix/scripts/substitute])
|
||||
AC_CONFIG_FILES([nix/scripts/guix-authenticate],
|
||||
|
||||
+32
-84
@@ -2,13 +2,11 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ(2.68)
|
||||
AC_INIT([GNU Guix],
|
||||
[m4_esyscmd([build-aux/git-version-gen .tarball-version])],
|
||||
[bug-guix@gnu.org], [guix],
|
||||
[https://www.gnu.org/software/guix/])
|
||||
AC_INIT([GNU Guix], [0.9.0], [bug-guix@gnu.org], [guix],
|
||||
[http://www.gnu.org/software/guix/])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
|
||||
AM_INIT_AUTOMAKE([1.14 gnu silent-rules subdir-objects \
|
||||
AM_INIT_AUTOMAKE([1.12 gnu silent-rules subdir-objects \
|
||||
color-tests parallel-tests -Woverride -Wno-portability])
|
||||
|
||||
# Enable silent rules by default.
|
||||
@@ -23,6 +21,9 @@ AC_USE_SYSTEM_EXTENSIONS
|
||||
AM_GNU_GETTEXT([external])
|
||||
AM_GNU_GETTEXT_VERSION([0.18.1])
|
||||
|
||||
guilemoduledir="${datarootdir}/guile/site/2.0"
|
||||
AC_SUBST([guilemoduledir])
|
||||
|
||||
GUIX_SYSTEM_TYPE
|
||||
GUIX_ASSERT_SUPPORTED_SYSTEM
|
||||
|
||||
@@ -40,19 +41,12 @@ AC_ARG_WITH([bash-completion-dir],
|
||||
[bashcompletiondir='${sysconfdir}/bash_completion.d'])
|
||||
AC_SUBST([bashcompletiondir])
|
||||
|
||||
AC_ARG_WITH([zsh-completion-dir],
|
||||
AC_HELP_STRING([--with-zsh-completion-dir=DIR],
|
||||
[name of the Zsh completion directory]),
|
||||
[zshcompletiondir="$withval"],
|
||||
[zshcompletiondir='${datadir}/zsh/site-functions'])
|
||||
AC_SUBST([zshcompletiondir])
|
||||
|
||||
dnl Better be verbose.
|
||||
AC_MSG_CHECKING([for the store directory])
|
||||
AC_MSG_RESULT([$storedir])
|
||||
|
||||
AC_ARG_ENABLE([daemon],
|
||||
[AS_HELP_STRING([--disable-daemon], [do not build the Nix daemon (C++)])],
|
||||
[AS_HELP_STRING([--disable-daemon], [build the Nix daemon (C++)])],
|
||||
[guix_build_daemon="$enableval"],
|
||||
[guix_build_daemon="yes"])
|
||||
|
||||
@@ -66,60 +60,35 @@ AC_SUBST([guix_localstatedir])
|
||||
AC_SUBST([guix_sysconfdir])
|
||||
AC_SUBST([guix_sbindir])
|
||||
|
||||
GUIX_CHECK_FILE_NAME_LIMITS([can_run_tests])
|
||||
AM_CONDITIONAL([CAN_RUN_TESTS], [test "x$can_run_tests" = "xyes"])
|
||||
GUIX_CHECK_FILE_NAME_LIMITS
|
||||
|
||||
dnl We require pkg.m4 (from pkg-config) and guile.m4 (from Guile.)
|
||||
dnl Make sure they are available.
|
||||
m4_pattern_forbid([PKG_CHECK_MODULES])
|
||||
m4_pattern_forbid([GUILE_MODULE_AVAILABLE])
|
||||
m4_pattern_forbid([^GUILE_P$])
|
||||
|
||||
dnl Search for 'guile' and 'guild'. This macro defines
|
||||
dnl 'GUILE_EFFECTIVE_VERSION'.
|
||||
GUILE_PKG([2.2 2.0])
|
||||
GUILE_PROGS
|
||||
PKG_CHECK_MODULES([GUILE], [guile-2.0 >= 2.0.7])
|
||||
AC_PATH_PROG([GUILE], [guile])
|
||||
AC_PATH_PROG([GUILD], [guild])
|
||||
if test "x$GUILD" = "x"; then
|
||||
AC_MSG_ERROR(['guild' binary not found; please check your guile-2.x installation.])
|
||||
fi
|
||||
|
||||
if test "x$GUILE_EFFECTIVE_VERSION" = "x2.0"; then
|
||||
PKG_CHECK_MODULES([GUILE], [guile-2.0 >= 2.0.9])
|
||||
fi
|
||||
|
||||
dnl Installation directories for .scm and .go files.
|
||||
guilemoduledir="${datarootdir}/guile/site/$GUILE_EFFECTIVE_VERSION"
|
||||
guileobjectdir="${libdir}/guile/$GUILE_EFFECTIVE_VERSION/site-ccache"
|
||||
AC_SUBST([guilemoduledir])
|
||||
AC_SUBST([guileobjectdir])
|
||||
|
||||
dnl The GnuTLS bindings are necessary for substitutes over HTTPS and for 'guix
|
||||
dnl pull', among other things.
|
||||
GUILE_MODULE_AVAILABLE([have_gnutls], [(gnutls)])
|
||||
if test "x$have_gnutls" != "xyes"; then
|
||||
AC_MSG_ERROR([The Guile bindings of GnuTLS are missing; please install them.])
|
||||
fi
|
||||
|
||||
dnl Check for Guile-Git.
|
||||
GUILE_MODULE_AVAILABLE([have_guile_git], [(git)])
|
||||
if test "x$have_guile_git" != "xyes"; then
|
||||
AC_MSG_ERROR([Guile-Git is missing; please install it.])
|
||||
fi
|
||||
|
||||
dnl Guile-JSON is used in various places.
|
||||
dnl guile-json is used for the PyPI package importer
|
||||
GUILE_MODULE_AVAILABLE([have_guile_json], [(json)])
|
||||
AM_CONDITIONAL([HAVE_GUILE_JSON], [test "x$have_guile_json" = "xyes"])
|
||||
|
||||
dnl Make sure we have a full-fledged Guile.
|
||||
GUIX_ASSERT_GUILE_FEATURES([regex posix socket net-db threads])
|
||||
|
||||
dnl Decompressors, for use by the substituter and other modules.
|
||||
AC_PATH_PROG([GZIP], [gzip])
|
||||
AC_PATH_PROG([BZIP2], [bzip2])
|
||||
AC_PATH_PROG([XZ], [xz])
|
||||
AC_SUBST([GZIP])
|
||||
AC_SUBST([BZIP2])
|
||||
AC_SUBST([XZ])
|
||||
dnl Check whether (srfi srfi-37) works, and provide our own if it doesn't.
|
||||
GUIX_CHECK_SRFI_37
|
||||
AM_CONDITIONAL([INSTALL_SRFI_37], [test "x$ac_cv_guix_srfi_37_broken" = xyes])
|
||||
|
||||
dnl Check whether (guix build syscalls) can be built.
|
||||
GUIX_CHECK_LIBC_MOUNT
|
||||
AM_CONDITIONAL([BUILD_SYSCALLS_MODULE],
|
||||
[test "x$guix_cv_libc_has_mount" = "xyes"])
|
||||
|
||||
AC_ARG_WITH([nix-prefix],
|
||||
[AS_HELP_STRING([--with-nix-prefix=DIR],
|
||||
@@ -216,22 +185,6 @@ AC_SUBST([LIBGCRYPT_LIBDIR])
|
||||
|
||||
GUIX_ASSERT_LIBGCRYPT_USABLE
|
||||
|
||||
dnl Library name of zlib suitable for 'dynamic-link'.
|
||||
GUIX_LIBZ_LIBDIR([libz_libdir])
|
||||
if test "x$libz_libdir" = "x"; then
|
||||
LIBZ="libz"
|
||||
else
|
||||
LIBZ="$libz_libdir/libz"
|
||||
fi
|
||||
AC_MSG_CHECKING([for zlib's shared library name])
|
||||
AC_MSG_RESULT([$LIBZ])
|
||||
AC_SUBST([LIBZ])
|
||||
|
||||
dnl Check for Guile-SSH, for the (guix ssh) module.
|
||||
GUIX_CHECK_GUILE_SSH
|
||||
AM_CONDITIONAL([HAVE_GUILE_SSH],
|
||||
[test "x$guix_cv_have_recent_guile_ssh" = "xyes"])
|
||||
|
||||
AC_CACHE_SAVE
|
||||
|
||||
m4_include([config-daemon.ac])
|
||||
@@ -243,28 +196,23 @@ AM_MISSING_PROG([DOT], [dot])
|
||||
dnl Manual pages.
|
||||
AM_MISSING_PROG([HELP2MAN], [help2man])
|
||||
|
||||
dnl Emacs (optional), for 'etc/indent-package.el'.
|
||||
AC_PATH_PROG([EMACS], [emacs], [/usr/bin/emacs])
|
||||
AC_SUBST([EMACS])
|
||||
|
||||
case "$storedir" in
|
||||
/gnu/store)
|
||||
;;
|
||||
*)
|
||||
AC_MSG_WARN([Using a store directory other than '/gnu/store' will prevent you])
|
||||
AC_MSG_WARN([from downloading substitutes from gnu.org.])
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_CONFIG_FILES([Makefile
|
||||
po/guix/Makefile.in
|
||||
po/packages/Makefile.in
|
||||
guix/config.scm])
|
||||
|
||||
AC_CONFIG_FILES([scripts/guix], [chmod +x scripts/guix])
|
||||
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])
|
||||
AC_CONFIG_FILES([etc/indent-code.el], [chmod +x etc/indent-code.el])
|
||||
AC_CONFIG_FILES([pre-inst-env], [chmod +x pre-inst-env])
|
||||
AC_CONFIG_FILES([test-env], [chmod +x test-env])
|
||||
|
||||
dnl Emacs interface.
|
||||
AC_PATH_PROG([DOT_USER_PROGRAM], [dot], [dot])
|
||||
AM_PATH_LISPDIR
|
||||
AM_CONDITIONAL([HAVE_EMACS], [test "x$EMACS" != "xno"])
|
||||
|
||||
emacsuidir="${guilemoduledir}/guix/emacs"
|
||||
AC_SUBST([emacsuidir])
|
||||
AC_CONFIG_FILES([emacs/guix-config.el
|
||||
emacs/guix-helper.scm])
|
||||
|
||||
AC_OUTPUT
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
# GNU Guix --- Functional package management for GNU
|
||||
# Copyright © 2012, 2013, 2014, 2015 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/>.
|
||||
|
||||
#
|
||||
# Integration of the `guix-daemon' code taken from upstream Nix.
|
||||
#
|
||||
|
||||
BUILT_SOURCES += nix/libstore/schema.sql.hh
|
||||
CLEANFILES += $(BUILT_SOURCES) etc/guix-daemon.service
|
||||
|
||||
noinst_LIBRARIES = libformat.a libutil.a libstore.a
|
||||
|
||||
# Use '-std=c++11' for 'std::shared_ptr', 'auto', lambdas, and more.
|
||||
AM_CXXFLAGS = -Wall -std=c++11
|
||||
|
||||
libformat_a_SOURCES = \
|
||||
nix/boost/format/free_funcs.cc \
|
||||
nix/boost/format/parsing.cc \
|
||||
nix/boost/format/format_implementation.cc
|
||||
|
||||
libformat_headers = \
|
||||
nix/boost/throw_exception.hpp \
|
||||
nix/boost/format.hpp \
|
||||
nix/boost/assert.hpp \
|
||||
nix/boost/format/macros_default.hpp \
|
||||
nix/boost/format/format_fwd.hpp \
|
||||
nix/boost/format/format_class.hpp \
|
||||
nix/boost/format/exceptions.hpp \
|
||||
nix/boost/format/group.hpp \
|
||||
nix/boost/format/feed_args.hpp \
|
||||
nix/boost/format/internals_fwd.hpp \
|
||||
nix/boost/format/internals.hpp
|
||||
|
||||
libformat_a_CPPFLAGS = \
|
||||
-I$(top_srcdir)/nix
|
||||
|
||||
libutil_a_SOURCES = \
|
||||
nix/libutil/archive.cc \
|
||||
nix/libutil/affinity.cc \
|
||||
nix/libutil/serialise.cc \
|
||||
nix/libutil/util.cc \
|
||||
nix/libutil/xml-writer.cc \
|
||||
nix/libutil/hash.cc \
|
||||
nix/libutil/gcrypt-hash.cc
|
||||
|
||||
libutil_headers = \
|
||||
nix/libutil/affinity.hh \
|
||||
nix/libutil/hash.hh \
|
||||
nix/libutil/serialise.hh \
|
||||
nix/libutil/xml-writer.hh \
|
||||
nix/libutil/util.hh \
|
||||
nix/libutil/archive.hh \
|
||||
nix/libutil/types.hh \
|
||||
nix/libutil/gcrypt-hash.hh \
|
||||
nix/libutil/md5.h \
|
||||
nix/libutil/sha1.h \
|
||||
nix/libutil/sha256.h
|
||||
|
||||
libutil_a_CPPFLAGS = \
|
||||
-I$(top_builddir)/nix \
|
||||
-I$(top_srcdir)/nix/libutil \
|
||||
$(libformat_a_CPPFLAGS)
|
||||
|
||||
libstore_a_SOURCES = \
|
||||
nix/libstore/gc.cc \
|
||||
nix/libstore/globals.cc \
|
||||
nix/libstore/misc.cc \
|
||||
nix/libstore/references.cc \
|
||||
nix/libstore/store-api.cc \
|
||||
nix/libstore/optimise-store.cc \
|
||||
nix/libstore/local-store.cc \
|
||||
nix/libstore/remote-store.cc \
|
||||
nix/libstore/build.cc \
|
||||
nix/libstore/pathlocks.cc \
|
||||
nix/libstore/derivations.cc
|
||||
|
||||
libstore_headers = \
|
||||
nix/libstore/references.hh \
|
||||
nix/libstore/pathlocks.hh \
|
||||
nix/libstore/globals.hh \
|
||||
nix/libstore/worker-protocol.hh \
|
||||
nix/libstore/remote-store.hh \
|
||||
nix/libstore/derivations.hh \
|
||||
nix/libstore/misc.hh \
|
||||
nix/libstore/local-store.hh \
|
||||
nix/libstore/store-api.hh
|
||||
|
||||
libstore_a_CPPFLAGS = \
|
||||
$(libutil_a_CPPFLAGS) \
|
||||
-I$(top_srcdir)/nix/libstore \
|
||||
-I$(top_builddir)/nix/libstore \
|
||||
-DNIX_STORE_DIR=\"$(storedir)\" \
|
||||
-DNIX_DATA_DIR=\"$(datadir)\" \
|
||||
-DNIX_STATE_DIR=\"$(localstatedir)/guix\" \
|
||||
-DNIX_LOG_DIR=\"$(localstatedir)/log/guix\" \
|
||||
-DNIX_CONF_DIR=\"$(sysconfdir)/guix\" \
|
||||
-DNIX_LIBEXEC_DIR=\"$(libexecdir)\" \
|
||||
-DNIX_BIN_DIR=\"$(bindir)\" \
|
||||
-DOPENSSL_PATH="\"guix-authenticate\"" \
|
||||
-DDEFAULT_CHROOT_DIRS="\"\""
|
||||
|
||||
libstore_a_CXXFLAGS = $(AM_CXXFLAGS) \
|
||||
$(SQLITE3_CFLAGS) $(LIBGCRYPT_CFLAGS)
|
||||
|
||||
bin_PROGRAMS = guix-daemon
|
||||
sbin_PROGRAMS = guix-register
|
||||
|
||||
guix_daemon_SOURCES = \
|
||||
nix/nix-daemon/nix-daemon.cc \
|
||||
nix/nix-daemon/guix-daemon.cc
|
||||
|
||||
guix_daemon_CPPFLAGS = \
|
||||
-DLOCALEDIR=\"$(localedir)\" \
|
||||
$(libutil_a_CPPFLAGS) \
|
||||
-I$(top_srcdir)/nix/libstore
|
||||
|
||||
guix_daemon_LDADD = \
|
||||
libstore.a libutil.a libformat.a -lbz2 \
|
||||
$(SQLITE3_LIBS) $(LIBGCRYPT_LIBS)
|
||||
|
||||
guix_daemon_headers = \
|
||||
nix/nix-daemon/shared.hh
|
||||
|
||||
|
||||
guix_register_SOURCES = \
|
||||
nix/guix-register/guix-register.cc
|
||||
|
||||
guix_register_CPPFLAGS = \
|
||||
$(libutil_a_CPPFLAGS) \
|
||||
$(libstore_a_CPPFLAGS) \
|
||||
-I$(top_srcdir)/nix/libstore
|
||||
|
||||
# XXX: Should we start using shared libs?
|
||||
guix_register_LDADD = \
|
||||
libstore.a libutil.a libformat.a -lbz2 \
|
||||
$(SQLITE3_LIBS) $(LIBGCRYPT_LIBS)
|
||||
|
||||
|
||||
noinst_HEADERS = \
|
||||
$(libformat_headers) $(libutil_headers) $(libstore_headers) \
|
||||
$(guix_daemon_headers)
|
||||
|
||||
nix/libstore/schema.sql.hh: nix/libstore/schema.sql
|
||||
$(GUILE) --no-auto-compile -c \
|
||||
"(use-modules (rnrs io ports)) \
|
||||
(call-with-output-file \"$@\" \
|
||||
(lambda (out) \
|
||||
(call-with-input-file \"$^\" \
|
||||
(lambda (in) \
|
||||
(write (get-string-all in) out)))))"
|
||||
|
||||
nodist_pkglibexec_SCRIPTS = \
|
||||
nix/scripts/list-runtime-roots \
|
||||
nix/scripts/substitute
|
||||
|
||||
if BUILD_DAEMON_OFFLOAD
|
||||
|
||||
nodist_pkglibexec_SCRIPTS += \
|
||||
nix/scripts/offload
|
||||
|
||||
endif BUILD_DAEMON_OFFLOAD
|
||||
|
||||
|
||||
# XXX: It'd be better to hide it in $(pkglibexecdir).
|
||||
nodist_libexec_SCRIPTS = \
|
||||
nix/scripts/guix-authenticate
|
||||
|
||||
# The '.service' file for systemd.
|
||||
systemdservicedir = $(libdir)/systemd/system
|
||||
nodist_systemdservice_DATA = etc/guix-daemon.service
|
||||
|
||||
etc/guix-daemon.service: etc/guix-daemon.service.in \
|
||||
$(top_builddir)/config.status
|
||||
$(MKDIR_P) "`dirname "$@"`"
|
||||
$(SED) -e 's|@''bindir''@|$(bindir)|' < \
|
||||
"$(srcdir)/etc/guix-daemon.service.in" > "$@.tmp"
|
||||
mv "$@.tmp" "$@"
|
||||
|
||||
EXTRA_DIST += \
|
||||
nix/libstore/schema.sql \
|
||||
nix/AUTHORS \
|
||||
nix/COPYING \
|
||||
etc/guix-daemon.service.in
|
||||
|
||||
AM_TESTS_ENVIRONMENT += \
|
||||
top_builddir="$(abs_top_builddir)"
|
||||
|
||||
TESTS += \
|
||||
tests/guix-daemon.sh
|
||||
|
||||
clean-local:
|
||||
-if test -d "$(GUIX_TEST_ROOT)"; then \
|
||||
find "$(GUIX_TEST_ROOT)" | xargs chmod +w; \
|
||||
fi
|
||||
-rm -rf "$(GUIX_TEST_ROOT)"
|
||||
@@ -0,0 +1,143 @@
|
||||
# GNU Guix --- Functional package management for GNU
|
||||
# Copyright © 2012, 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
|
||||
# Copyright © 2013 Andreas Enge <andreas@enge.fr>
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
info_TEXINFOS = doc/guix.texi
|
||||
|
||||
DOT_FILES = \
|
||||
doc/images/bootstrap-graph.dot \
|
||||
doc/images/coreutils-graph.dot \
|
||||
doc/images/coreutils-bag-graph.dot \
|
||||
doc/images/service-graph.dot \
|
||||
doc/images/dmd-graph.dot
|
||||
|
||||
DOT_VECTOR_GRAPHICS = \
|
||||
$(DOT_FILES:%.dot=%.eps) \
|
||||
$(DOT_FILES:%.dot=%.pdf)
|
||||
|
||||
EXTRA_DIST += \
|
||||
doc/contributing.texi \
|
||||
doc/emacs.texi \
|
||||
doc/fdl-1.3.texi \
|
||||
$(DOT_FILES) \
|
||||
$(DOT_VECTOR_GRAPHICS) \
|
||||
doc/images/coreutils-size-map.eps \
|
||||
doc/environment-gdb.scm \
|
||||
doc/package-hello.scm
|
||||
|
||||
OS_CONFIG_EXAMPLES_TEXI = \
|
||||
doc/os-config-bare-bones.texi \
|
||||
doc/os-config-desktop.texi
|
||||
|
||||
# Bundle this file so that makeinfo finds it in out-of-source-tree builds.
|
||||
BUILT_SOURCES += $(OS_CONFIG_EXAMPLES_TEXI)
|
||||
EXTRA_DIST += $(OS_CONFIG_EXAMPLES_TEXI)
|
||||
MAINTAINERCLEANFILES = $(OS_CONFIG_EXAMPLES_TEXI)
|
||||
|
||||
doc/os-config-%.texi: gnu/system/examples/%.tmpl
|
||||
$(MKDIR_P) "`dirname "$@"`"
|
||||
cp "$<" "$@"
|
||||
|
||||
infoimagedir = $(infodir)/images
|
||||
dist_infoimage_DATA = \
|
||||
$(DOT_FILES:%.dot=%.png) \
|
||||
doc/images/coreutils-size-map.png
|
||||
|
||||
# Try hard to obtain an image size and aspect that's reasonable for inclusion
|
||||
# in an Info or PDF document.
|
||||
DOT_OPTIONS = \
|
||||
-Gratio=.9 -Gnodesep=.005 -Granksep=.00005 \
|
||||
-Nfontsize=9 -Nheight=.1 -Nwidth=.1
|
||||
|
||||
.dot.png:
|
||||
$(DOT) -Tpng $(DOT_OPTIONS) < "$<" > "$@.tmp"
|
||||
mv "$@.tmp" "$@"
|
||||
|
||||
.dot.pdf:
|
||||
$(DOT) -Tpdf $(DOT_OPTIONS) < "$<" > "$@.tmp"
|
||||
mv "$@.tmp" "$@"
|
||||
|
||||
.dot.eps:
|
||||
$(DOT) -Teps $(DOT_OPTIONS) < "$<" > "$@.tmp"
|
||||
mv "$@.tmp" "$@"
|
||||
|
||||
.png.eps:
|
||||
convert "$<" "$@-tmp.eps"
|
||||
mv "$@-tmp.eps" "$@"
|
||||
|
||||
# We cannot add new dependencies to `doc/guix.pdf' & co. (info "(automake)
|
||||
# Extending"). Using the `-local' rules is imperfect, because they may be
|
||||
# triggered after the main rule. Oh, well.
|
||||
pdf-local: $(DOT_FILES=%.dot=$(top_srcdir)/%.pdf)
|
||||
info-local: $(DOT_FILES=%.dot=$(top_srcdir)/%.png)
|
||||
ps-local: $(DOT_FILES=%.dot=$(top_srcdir)/%.eps) \
|
||||
$(top_srcdir)/doc/images/coreutils-size-map.eps
|
||||
dvi-local: ps-local
|
||||
|
||||
|
||||
# Manual pages.
|
||||
|
||||
doc/guix.1: $(SUBCOMMANDS:%=guix/scripts/%.scm)
|
||||
-LANGUAGE= $(top_builddir)/pre-inst-env \
|
||||
$(HELP2MAN) --output="$@" guix
|
||||
|
||||
# Note: Do not depend on 'guix-daemon' since that would trigger a rebuild even
|
||||
# for people building from a tarball.
|
||||
doc/guix-daemon.1: nix/nix-daemon/guix-daemon.cc
|
||||
-LANGUAGE= $(top_builddir)/pre-inst-env \
|
||||
$(HELP2MAN) --output="$@" guix-daemon
|
||||
|
||||
define subcommand-manual-target
|
||||
|
||||
doc/guix-$(1).1: guix/scripts/$(1).scm
|
||||
-LANGUAGE= $(top_builddir)/pre-inst-env \
|
||||
$(HELP2MAN) --output="$$@" "guix $(1)"
|
||||
|
||||
endef
|
||||
|
||||
SUBCOMMANDS := \
|
||||
archive \
|
||||
build \
|
||||
challenge \
|
||||
download \
|
||||
edit \
|
||||
environment \
|
||||
gc \
|
||||
hash \
|
||||
import \
|
||||
lint \
|
||||
package \
|
||||
publish \
|
||||
pull \
|
||||
refresh \
|
||||
size \
|
||||
system
|
||||
|
||||
$(eval $(foreach subcommand,$(SUBCOMMANDS), \
|
||||
$(call subcommand-manual-target,$(subcommand))))
|
||||
|
||||
dist_man1_MANS = \
|
||||
doc/guix.1 \
|
||||
$(SUBCOMMANDS:%=doc/guix-%.1)
|
||||
|
||||
if BUILD_DAEMON
|
||||
|
||||
dist_man1_MANS += \
|
||||
doc/guix-daemon.1
|
||||
|
||||
endif
|
||||
+29
-231
@@ -7,18 +7,6 @@ grow! Please get in touch with us on @email{guix-devel@@gnu.org} and
|
||||
reports, patches, and anything that may be helpful to the project. We
|
||||
particularly welcome help on packaging (@pxref{Packaging Guidelines}).
|
||||
|
||||
@cindex code of conduct, of contributors
|
||||
@cindex contributor covenant
|
||||
We want to provide a warm, friendly, and harassment-free environment, so
|
||||
that anyone can contribute to the best of their abilities. To this end
|
||||
our project uses a ``Contributor Covenant'', which was adapted from
|
||||
@url{http://contributor-covenant.org/}. You can find a local version in
|
||||
the @file{CODE-OF-CONDUCT} file in the source tree.
|
||||
|
||||
Contributors are not required to use their legal name in patches and
|
||||
on-line communication; they can use any name or pseudonym of their
|
||||
choice.
|
||||
|
||||
@menu
|
||||
* Building from Git:: The latest and greatest.
|
||||
* Running Guix Before It Is Installed:: Hacker tricks.
|
||||
@@ -31,13 +19,7 @@ choice.
|
||||
@section Building from Git
|
||||
|
||||
If you want to hack Guix itself, it is recommended to use the latest
|
||||
version from the Git repository:
|
||||
|
||||
@example
|
||||
git clone https://git.savannah.gnu.org/git/guix.git
|
||||
@end example
|
||||
|
||||
When building Guix from a checkout,
|
||||
version from the Git repository. When building Guix from a checkout,
|
||||
the following packages are required in addition to those mentioned in
|
||||
the installation instructions (@pxref{Requirements}).
|
||||
|
||||
@@ -45,56 +27,38 @@ the installation instructions (@pxref{Requirements}).
|
||||
@item @url{http://gnu.org/software/autoconf/, GNU Autoconf};
|
||||
@item @url{http://gnu.org/software/automake/, GNU Automake};
|
||||
@item @url{http://gnu.org/software/gettext/, GNU Gettext};
|
||||
@item @url{http://gnu.org/software/texinfo/, GNU Texinfo};
|
||||
@item @url{http://www.graphviz.org/, Graphviz};
|
||||
@item @url{http://www.gnu.org/software/help2man/, GNU Help2man (optional)}.
|
||||
@end itemize
|
||||
|
||||
The easiest way to set up a development environment for Guix is, of
|
||||
course, by using Guix! The following command starts a new shell where
|
||||
all the dependencies and appropriate environment variables are set up to
|
||||
hack on Guix:
|
||||
Run @command{./bootstrap} to download the Nix daemon source code and to
|
||||
generate the build system infrastructure using autoconf. It reports an
|
||||
error if an inappropriate version of the above packages is being used.
|
||||
|
||||
@example
|
||||
guix environment guix
|
||||
@end example
|
||||
|
||||
@xref{Invoking guix environment}, for more information on that command.
|
||||
Extra dependencies can be added with @option{--ad-hoc}:
|
||||
|
||||
@example
|
||||
guix environment guix --ad-hoc help2man git strace
|
||||
@end example
|
||||
|
||||
Run @command{./bootstrap} to generate the build system infrastructure
|
||||
using Autoconf and Automake. If you get an error like this one:
|
||||
@noindent
|
||||
If you get an error like this one:
|
||||
|
||||
@example
|
||||
configure.ac:46: error: possibly undefined macro: PKG_CHECK_MODULES
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
it probably means that Autoconf couldn’t find @file{pkg.m4}, which is
|
||||
provided by pkg-config. Make sure that @file{pkg.m4} is available. The
|
||||
same holds for the @file{guile.m4} set of macros provided by Guile. For
|
||||
instance, if you installed Automake in @file{/usr/local}, it wouldn’t
|
||||
look for @file{.m4} files in @file{/usr/share}. In that case, you have
|
||||
to invoke the following command:
|
||||
provided by @command{pkg-config}. Make sure that @file{pkg.m4} is
|
||||
available. For instance, if you installed Automake in
|
||||
@file{/usr/local}, it wouldn’t look for @file{.m4} files in
|
||||
@file{/usr/share}. So you have to invoke the following command in that
|
||||
case
|
||||
|
||||
@example
|
||||
export ACLOCAL_PATH=/usr/share/aclocal
|
||||
@end example
|
||||
|
||||
@xref{Macro Search Path,,, automake, The GNU Automake Manual}, for
|
||||
See @pxref{Macro Search Path,,, automake, The GNU Automake Manual} for
|
||||
more information.
|
||||
|
||||
Then, run @command{./configure} as usual. Make sure to pass
|
||||
@code{--localstatedir=@var{directory}} where @var{directory} is the
|
||||
@code{localstatedir} value used by your current installation (@pxref{The
|
||||
Store}, for information about this).
|
||||
Then, run @command{./configure} as usual.
|
||||
|
||||
Finally, you have to invoke @code{make check} to run tests
|
||||
(@pxref{Running the Test Suite}). If anything
|
||||
Finally, you have to invoke @code{make check} to run tests. If anything
|
||||
fails, take a look at installation instructions (@pxref{Installation})
|
||||
or send a message to the @email{guix-devel@@gnu.org, mailing list}.
|
||||
|
||||
@@ -122,46 +86,11 @@ Similarly, for a Guile session using the Guix modules:
|
||||
|
||||
@example
|
||||
$ ./pre-inst-env guile -c '(use-modules (guix utils)) (pk (%current-system))'
|
||||
|
||||
;;; ("x86_64-linux")
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
@cindex REPL
|
||||
@cindex read-eval-print loop
|
||||
@dots{} and for a REPL (@pxref{Using Guile Interactively,,, guile, Guile
|
||||
Reference Manual}):
|
||||
|
||||
@example
|
||||
$ ./pre-inst-env guile
|
||||
scheme@@(guile-user)> ,use(guix)
|
||||
scheme@@(guile-user)> ,use(gnu)
|
||||
scheme@@(guile-user)> (define snakes
|
||||
(fold-packages
|
||||
(lambda (package lst)
|
||||
(if (string-prefix? "python"
|
||||
(package-name package))
|
||||
(cons package lst)
|
||||
lst))
|
||||
'()))
|
||||
scheme@@(guile-user)> (length snakes)
|
||||
$1 = 361
|
||||
@end example
|
||||
|
||||
The @command{pre-inst-env} script sets up all the environment variables
|
||||
necessary to support this, including @env{PATH} and @env{GUILE_LOAD_PATH}.
|
||||
|
||||
Note that @command{./pre-inst-env guix pull} does @emph{not} upgrade the
|
||||
local source tree; it simply updates the @file{~/.config/guix/latest}
|
||||
symlink (@pxref{Invoking guix pull}). Run @command{git pull} instead if
|
||||
you want to upgrade your local source tree.@footnote{If you would like
|
||||
to set up @command{guix} to use your Git checkout, you can point the
|
||||
@file{~/.config/guix/latest} symlink to your Git checkout directory.
|
||||
If you are the sole user of your system, you may also consider pointing
|
||||
the @file{/root/.config/guix/latest} symlink to point to
|
||||
@file{~/.config/guix/latest}; this way it will always use the same
|
||||
@command{guix} as your user does.}
|
||||
|
||||
|
||||
@node The Perfect Setup
|
||||
@section The Perfect Setup
|
||||
@@ -182,8 +111,7 @@ that it finds source files from your checkout:
|
||||
|
||||
@lisp
|
||||
;; @r{Assuming the Guix checkout is in ~/src/guix.}
|
||||
(with-eval-after-load 'geiser-guile
|
||||
(add-to-list 'geiser-guile-load-path "~/src/guix"))
|
||||
(add-to-list 'geiser-guile-load-path "~/src/guix")
|
||||
@end lisp
|
||||
|
||||
To actually edit the code, Emacs already has a neat Scheme mode. But in
|
||||
@@ -193,6 +121,9 @@ facilities to directly operate on the syntax tree, such as raising an
|
||||
s-expression or wrapping it, swallowing or rejecting the following
|
||||
s-expression, etc.
|
||||
|
||||
GNU Guix also comes with a minor mode that provides some additional
|
||||
functionality for Scheme buffers (@pxref{Emacs Development}).
|
||||
|
||||
|
||||
@node Coding Style
|
||||
@section Coding Style
|
||||
@@ -243,8 +174,6 @@ especially when matching lists.
|
||||
@node Formatting Code
|
||||
@subsection Formatting Code
|
||||
|
||||
@cindex formatting code
|
||||
@cindex coding style
|
||||
When writing Scheme code, we follow common wisdom among Scheme
|
||||
programmers. In general, we follow the
|
||||
@url{http://mumble.net/~campbell/scheme/style.txt, Riastradh's Lisp
|
||||
@@ -254,28 +183,8 @@ please do read it.
|
||||
|
||||
Some special forms introduced in Guix, such as the @code{substitute*}
|
||||
macro, have special indentation rules. These are defined in the
|
||||
@file{.dir-locals.el} file, which Emacs automatically uses. Also note
|
||||
that Emacs-Guix provides @code{guix-devel-mode} mode that indents and
|
||||
highlights Guix code properly (@pxref{Development,,, emacs-guix, The
|
||||
Emacs-Guix Reference Manual}).
|
||||
|
||||
@cindex indentation, of code
|
||||
@cindex formatting, of code
|
||||
If you do not use Emacs, please make sure to let your editor knows these
|
||||
rules. To automatically indent a package definition, you can also run:
|
||||
|
||||
@example
|
||||
./etc/indent-code.el gnu/packages/@var{file}.scm @var{package}
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
This automatically indents the definition of @var{package} in
|
||||
@file{gnu/packages/@var{file}.scm} by running Emacs in batch mode. To
|
||||
indent a whole file, omit the second argument:
|
||||
|
||||
@example
|
||||
./etc/indent-code.el gnu/services/@var{file}.scm
|
||||
@end example
|
||||
@file{.dir-locals.el} file, which Emacs automatically uses. If you do
|
||||
not use Emacs, please make sure to let your editor know the rules.
|
||||
|
||||
We require all top-level procedures to carry a docstring. This
|
||||
requirement can be relaxed for simple private procedures in the
|
||||
@@ -291,15 +200,7 @@ keyword parameters for procedures that take more than four parameters.
|
||||
Development is done using the Git distributed version control system.
|
||||
Thus, access to the repository is not strictly necessary. We welcome
|
||||
contributions in the form of patches as produced by @code{git
|
||||
format-patch} sent to the @email{guix-patches@@gnu.org} mailing list.
|
||||
|
||||
This mailing list is backed by a Debbugs instance accessible at
|
||||
@uref{https://bugs.gnu.org/guix-patches}, which allows us to keep track
|
||||
of submissions. Each message sent to that mailing list gets a new
|
||||
tracking number assigned; people can then follow up on the submission by
|
||||
sending email to @code{@var{NNN}@@debbugs.gnu.org}, where @var{NNN} is
|
||||
the tracking number (@pxref{Sending a Patch Series}).
|
||||
|
||||
format-patch} sent to the @email{guix-devel@@gnu.org, mailing list}.
|
||||
Please write commit logs in the ChangeLog format (@pxref{Change Logs,,,
|
||||
standards, GNU Coding Standards}); you can check the commit history for
|
||||
examples.
|
||||
@@ -308,12 +209,6 @@ Before submitting a patch that adds or modifies a package definition,
|
||||
please run through this check list:
|
||||
|
||||
@enumerate
|
||||
@item
|
||||
If the authors of the packaged software provide a cryptographic
|
||||
signature for the release tarball, make an effort to verify the
|
||||
authenticity of the archive. For a detached GPG signature file this
|
||||
would be done with the @code{gpg --verify} command.
|
||||
|
||||
@item
|
||||
Take some time to provide an adequate synopsis and description for the
|
||||
package. @xref{Synopses and Descriptions}, for some guidelines.
|
||||
@@ -327,20 +222,6 @@ name of the new or modified package, and fix any errors it reports
|
||||
Make sure the package builds on your platform, using @code{guix build
|
||||
@var{package}}.
|
||||
|
||||
@item
|
||||
@cindex bundling
|
||||
Make sure the package does not use bundled copies of software already
|
||||
available as separate packages.
|
||||
|
||||
Sometimes, packages include copies of the source code of their
|
||||
dependencies as a convenience for users. However, as a distribution, we
|
||||
want to make sure that such packages end up using the copy we already
|
||||
have in the distribution, if there is one. This improves resource usage
|
||||
(the dependency is built and stored only once), and allows the
|
||||
distribution to make transverse changes such as applying security
|
||||
updates for a given software package in a single place and have them
|
||||
affect the whole system---something that bundled copies prevent.
|
||||
|
||||
@item
|
||||
Take a look at the profile reported by @command{guix size}
|
||||
(@pxref{Invoking guix size}). This will allow you to notice references
|
||||
@@ -353,102 +234,19 @@ For important changes, check that dependent package (if applicable) are
|
||||
not affected by the change; @code{guix refresh --list-dependent
|
||||
@var{package}} will help you do that (@pxref{Invoking guix refresh}).
|
||||
|
||||
@c See <https://lists.gnu.org/archive/html/guix-devel/2016-10/msg00933.html>.
|
||||
@cindex branching strategy
|
||||
@cindex rebuild scheduling strategy
|
||||
Depending on the number of dependent packages and thus the amount of
|
||||
rebuilding induced, commits go to different branches, along these lines:
|
||||
|
||||
@table @asis
|
||||
@item 300 dependent packages or less
|
||||
@code{master} branch (non-disruptive changes).
|
||||
|
||||
@item between 300 and 1,200 dependent packages
|
||||
@code{staging} branch (non-disruptive changes). This branch is intended
|
||||
to be merged in @code{master} every 3 weeks or so. Topical changes
|
||||
(e.g., an update of the GNOME stack) can instead go to a specific branch
|
||||
(say, @code{gnome-updates}).
|
||||
|
||||
@item more than 1,200 dependent packages
|
||||
@code{core-updates} branch (may include major and potentially disruptive
|
||||
changes). This branch is intended to be merged in @code{master} every
|
||||
2.5 months or so.
|
||||
@end table
|
||||
|
||||
All these branches are tracked by our build farm
|
||||
and merged into @code{master} once
|
||||
everything has been successfully built. This allows us to fix issues
|
||||
before they hit users, and to reduce the window during which pre-built
|
||||
binaries are not available.
|
||||
|
||||
@item
|
||||
@cindex determinism, of build processes
|
||||
@cindex reproducible builds, checking
|
||||
Check whether the package's build process is deterministic. This
|
||||
typically means checking whether an independent build of the package
|
||||
yields the exact same result that you obtained, bit for bit.
|
||||
|
||||
A simple way to do that is by building the same package several times in
|
||||
a row on your machine (@pxref{Invoking guix build}):
|
||||
|
||||
@example
|
||||
guix build --rounds=2 my-package
|
||||
@end example
|
||||
|
||||
This is enough to catch a class of common non-determinism issues, such
|
||||
as timestamps or randomly-generated output in the build result.
|
||||
|
||||
Another option is to use @command{guix challenge} (@pxref{Invoking guix
|
||||
challenge}). You may run it once the package has been committed and
|
||||
built by @code{hydra.gnu.org} to check whether it obtains the same
|
||||
result as you did. Better yet: Find another machine that can build it
|
||||
and run @command{guix publish}. Since the remote build machine is
|
||||
likely different from yours, this can catch non-determinism issues
|
||||
related to the hardware---e.g., use of different instruction set
|
||||
extensions---or to the operating system kernel---e.g., reliance on
|
||||
@code{uname} or @file{/proc} files.
|
||||
|
||||
@item
|
||||
When writing documentation, please use gender-neutral wording when
|
||||
referring to people, such as
|
||||
@uref{https://en.wikipedia.org/wiki/Singular_they, singular
|
||||
``they''@comma{} ``their''@comma{} ``them''}, and so forth.
|
||||
|
||||
@item
|
||||
Verify that your patch contains only one set of related changes.
|
||||
Bundling unrelated changes together makes reviewing harder and slower.
|
||||
|
||||
Examples of unrelated changes include the addition of several packages,
|
||||
or a package update along with fixes to that package.
|
||||
|
||||
@item
|
||||
Please follow our code formatting rules, possibly running the
|
||||
@command{etc/indent-code.el} script to do that automatically for you
|
||||
(@pxref{Formatting Code}).
|
||||
A simple way to do that is with @command{guix challenge}
|
||||
(@pxref{Invoking guix challenge}). You may run it once the package has
|
||||
been committed and built by @code{hydra.gnu.org} to check whether it
|
||||
obtains the same result as you did. Better yet: Find another machine
|
||||
that can build it and run @command{guix publish}.
|
||||
|
||||
@end enumerate
|
||||
|
||||
When posting a patch to the mailing list, use @samp{[PATCH] @dots{}} as
|
||||
a subject. You may use your email client or the @command{git
|
||||
send-email} command (@pxref{Sending a Patch Series}). We prefer to get
|
||||
patches in plain text messages, either inline or as MIME attachments.
|
||||
You are advised to pay attention if your email client changes anything
|
||||
like line breaks or indentation which could potentially break the
|
||||
patches.
|
||||
|
||||
When a bug is resolved, please close the thread by sending an email to
|
||||
@email{@var{NNN}-done@@debbugs.gnu.org}.
|
||||
|
||||
@unnumberedsubsec Sending a Patch Series
|
||||
@anchor{Sending a Patch Series}
|
||||
@cindex patch series
|
||||
@cindex @code{git send-email}
|
||||
@cindex @code{git-send-email}
|
||||
|
||||
When sending a patch series (e.g., using @code{git send-email}), please
|
||||
first send one message to @email{guix-patches@@gnu.org}, and then send
|
||||
subsequent patches to @email{@var{NNN}@@debbugs.gnu.org} to make sure
|
||||
they are kept together. See
|
||||
@uref{https://debbugs.gnu.org/Advanced.html, the Debbugs documentation}
|
||||
for more information.
|
||||
@c Debbugs bug: https://debbugs.gnu.org/db/15/15361.html
|
||||
When posting a patch to the mailing list, use @samp{[PATCH] @dots{}} as a
|
||||
subject. You may use your email client or the @command{git send-mail}
|
||||
command.
|
||||
|
||||
+739
@@ -0,0 +1,739 @@
|
||||
@node Emacs Interface
|
||||
@chapter Emacs Interface
|
||||
|
||||
@cindex Emacs
|
||||
GNU Guix comes with several useful modules (known as ``guix.el'') for
|
||||
GNU@tie{}Emacs which are intended to make an Emacs user interaction with
|
||||
Guix convenient and fun.
|
||||
|
||||
@menu
|
||||
* Initial Setup: Emacs Initial Setup. Preparing @file{~/.emacs}.
|
||||
* Package Management: Emacs Package Management. Managing packages and generations.
|
||||
* Popup Interface: Emacs Popup Interface. Magit-like interface for guix commands.
|
||||
* Prettify Mode: Emacs Prettify. Abbreviating @file{/gnu/store/@dots{}} file names.
|
||||
* Build Log Mode: Emacs Build Log. Highlighting Guix build logs.
|
||||
* Completions: Emacs Completions. Completing @command{guix} shell command.
|
||||
* Development: Emacs Development. Tools for Guix developers.
|
||||
@end menu
|
||||
|
||||
|
||||
@node Emacs Initial Setup
|
||||
@section Initial Setup
|
||||
|
||||
On the Guix System Distribution (@pxref{GNU Distribution}), ``guix.el''
|
||||
is ready to use, provided Guix is installed system-wide, which is the
|
||||
case by default. So if that is what you're using, you can happily skip
|
||||
this section and read about the fun stuff.
|
||||
|
||||
If you're not yet a happy user of GuixSD, a little bit of setup is needed.
|
||||
To be able to use ``guix.el'', you need to install the following
|
||||
packages:
|
||||
|
||||
@itemize
|
||||
@item
|
||||
@uref{http://www.gnu.org/software/emacs/, GNU Emacs}, version 24.3 or
|
||||
later;
|
||||
|
||||
@item
|
||||
@uref{http://nongnu.org/geiser/, Geiser}, version 0.3 or later: it is
|
||||
used for interacting with the Guile process.
|
||||
|
||||
@item
|
||||
@uref{https://github.com/magit/magit/, magit-popup library}. You
|
||||
already have this library if you use Magit 2.1.0 or later. This library
|
||||
is an optional dependency---it is required only for @kbd{M-x@tie{}guix}
|
||||
command (@pxref{Emacs Popup Interface}).
|
||||
|
||||
@end itemize
|
||||
|
||||
When it is done ``guix.el'' may be configured by requiring a special
|
||||
@code{guix-init} file---i.e., by adding the following code into your
|
||||
init file (@pxref{Init File,,, emacs, The GNU Emacs Manual}):
|
||||
|
||||
@example
|
||||
(add-to-list 'load-path "/path/to/directory-with-guix.el")
|
||||
(require 'guix-init nil t)
|
||||
@end example
|
||||
|
||||
So the only thing you need to figure out is where the directory with
|
||||
elisp files for Guix is placed. It depends on how you installed Guix:
|
||||
|
||||
@itemize
|
||||
@item
|
||||
If it was installed by a package manager of your distribution or by a
|
||||
usual @code{./configure && make && make install} command sequence, then
|
||||
elisp files are placed in a standard directory with Emacs packages
|
||||
(usually it is @file{/usr/share/emacs/site-lisp/}), which is already in
|
||||
@code{load-path}, so there is no need to add that directory there.
|
||||
|
||||
@item
|
||||
If you used a binary installation method (@pxref{Binary Installation}),
|
||||
then Guix is installed somewhere in the store, so the elisp files are
|
||||
placed in @file{/gnu/store/@dots{}-guix-0.8.2/share/emacs/site-lisp/} or
|
||||
alike. However it is not recommended to refer directly to a store
|
||||
directory. Instead you can install Guix using Guix itself with
|
||||
@command{guix package -i guix} command (@pxref{Invoking guix package})
|
||||
and add @file{~/.guix-profile/share/emacs/site-lisp/} directory to
|
||||
@code{load-path} variable.
|
||||
|
||||
@item
|
||||
If you did not install Guix at all and prefer a hacking way
|
||||
(@pxref{Running Guix Before It Is Installed}), along with augmenting
|
||||
@code{load-path} you need to set @code{guix-load-path} variable to the
|
||||
same directory, so your final configuration will look like this:
|
||||
|
||||
@example
|
||||
(let ((dir "/path/to/your-guix-git-tree/emacs"))
|
||||
(add-to-list 'load-path dir)
|
||||
(setq guix-load-path dir))
|
||||
(require 'guix-init nil t)
|
||||
@end example
|
||||
@end itemize
|
||||
|
||||
By default, along with autoloading (@pxref{Autoload,,, elisp, The GNU
|
||||
Emacs Lisp Reference Manual}) the main interactive commands for
|
||||
``guix.el'' (@pxref{Emacs Commands}), requiring @code{guix-init} will
|
||||
also autoload commands for the Emacs packages installed in your user
|
||||
profile.
|
||||
|
||||
To disable automatic loading of installed Emacs packages, set
|
||||
@code{guix-package-enable-at-startup} variable to @code{nil} before
|
||||
requiring @code{guix-init}. This variable has the same meaning for
|
||||
Emacs packages installed with Guix, as @code{package-enable-at-startup}
|
||||
for the built-in Emacs package system (@pxref{Package Installation,,,
|
||||
emacs, The GNU Emacs Manual}).
|
||||
|
||||
You can activate Emacs packages installed in your profile whenever you
|
||||
want using @kbd{M-x@tie{}guix-emacs-load-autoloads}.
|
||||
|
||||
|
||||
@node Emacs Package Management
|
||||
@section Package Management
|
||||
|
||||
Once ``guix.el'' has been successfully configured, you should be able to
|
||||
use a visual interface for routine package management tasks, pretty much
|
||||
like the @command{guix package} command (@pxref{Invoking guix package}).
|
||||
Specifically, it makes it easy to:
|
||||
|
||||
@itemize
|
||||
@item browse and display packages and generations;
|
||||
@item search, install, upgrade and remove packages;
|
||||
@item display packages from previous generations;
|
||||
@item do some other useful things.
|
||||
@end itemize
|
||||
|
||||
@menu
|
||||
* Commands: Emacs Commands. @kbd{M-x guix-@dots{}}
|
||||
* General information: Emacs General info. Common for both interfaces.
|
||||
* ``List'' buffer: Emacs List buffer. List-like interface.
|
||||
* ``Info'' buffer: Emacs Info buffer. Help-like interface.
|
||||
* Configuration: Emacs Configuration. Configuring the interface.
|
||||
@end menu
|
||||
|
||||
@node Emacs Commands
|
||||
@subsection Commands
|
||||
|
||||
All commands for displaying packages and generations use the current
|
||||
profile, which can be changed with
|
||||
@kbd{M-x@tie{}guix-set-current-profile}. Alternatively, if you call any
|
||||
of these commands with prefix argument (@kbd{C-u}), you will be prompted
|
||||
for a profile just for that command.
|
||||
|
||||
Commands for displaying packages:
|
||||
|
||||
@table @kbd
|
||||
|
||||
@item M-x guix-all-available-packages
|
||||
@itemx M-x guix-newest-available-packages
|
||||
Display all/newest available packages.
|
||||
|
||||
@item M-x guix-installed-packages
|
||||
Display all installed packages.
|
||||
|
||||
@item M-x guix-obsolete-packages
|
||||
Display obsolete packages (the packages that are installed in a profile
|
||||
but cannot be found among available packages).
|
||||
|
||||
@item M-x guix-search-by-name
|
||||
Display package(s) with the specified name.
|
||||
|
||||
@item M-x guix-search-by-regexp
|
||||
Search for packages by a specified regexp. By default ``name'',
|
||||
``synopsis'' and ``description'' of the packages will be searched. This
|
||||
can be changed by modifying @code{guix-search-params} variable.
|
||||
|
||||
@end table
|
||||
|
||||
By default, these commands display each output on a separate line. If
|
||||
you prefer to see a list of packages---i.e., a list with a package per
|
||||
line, use the following setting:
|
||||
|
||||
@example
|
||||
(setq guix-package-list-type 'package)
|
||||
@end example
|
||||
|
||||
Commands for displaying generations:
|
||||
|
||||
@table @kbd
|
||||
|
||||
@item M-x guix-generations
|
||||
List all the generations.
|
||||
|
||||
@item M-x guix-last-generations
|
||||
List the @var{N} last generations. You will be prompted for the number
|
||||
of generations.
|
||||
|
||||
@item M-x guix-generations-by-time
|
||||
List generations matching time period. You will be prompted for the
|
||||
period using Org mode time prompt based on Emacs calendar (@pxref{The
|
||||
date/time prompt,,, org, The Org Manual}).
|
||||
|
||||
@end table
|
||||
|
||||
You can also invoke the @command{guix pull} command (@pxref{Invoking
|
||||
guix pull}) from Emacs using:
|
||||
|
||||
@table @kbd
|
||||
@item M-x guix-pull
|
||||
With @kbd{C-u}, make it verbose.
|
||||
@end table
|
||||
|
||||
Once @command{guix pull} has succeeded, the Guix REPL is restared. This
|
||||
allows you to keep using the Emacs interface with the updated Guix.
|
||||
|
||||
@node Emacs General info
|
||||
@subsection General information
|
||||
|
||||
The following keys are available for both ``list'' and ``info'' types of
|
||||
buffers:
|
||||
|
||||
@table @kbd
|
||||
@item l
|
||||
@itemx r
|
||||
Go backward/forward by the history of the displayed results (this
|
||||
history is similar to the history of the Emacs @code{help-mode} or
|
||||
@code{Info-mode}).
|
||||
|
||||
@item g
|
||||
Revert current buffer: update information about the displayed
|
||||
packages/generations and redisplay it.
|
||||
|
||||
@item R
|
||||
Redisplay current buffer (without updating information).
|
||||
|
||||
@item M
|
||||
Apply manifest to the current profile or to a specified profile, if
|
||||
prefix argument is used. This has the same meaning as @code{--manifest}
|
||||
option (@pxref{Invoking guix package}).
|
||||
|
||||
@item C-c C-z
|
||||
Go to the Guix REPL (@pxref{The REPL,,, geiser, Geiser User Manual}).
|
||||
|
||||
@item h
|
||||
@itemx ?
|
||||
Describe current mode to see all available bindings.
|
||||
|
||||
@end table
|
||||
|
||||
@emph{Hint:} If you need several ``list'' or ``info'' buffers, you can
|
||||
simlpy @kbd{M-x clone-buffer} them, and each buffer will have its own
|
||||
history.
|
||||
|
||||
@emph{Warning:} Name/version pairs cannot be used to identify packages
|
||||
(because a name is not necessarily unique), so ``guix.el'' uses special
|
||||
identifiers that live only during a guile session, so if the Guix REPL
|
||||
was restarted, you may want to revert ``list'' buffer (by pressing
|
||||
@kbd{g}).
|
||||
|
||||
@node Emacs List buffer
|
||||
@subsection ``List'' buffer
|
||||
|
||||
An interface of a ``list'' buffer is similar to the interface provided
|
||||
by ``package.el'' (@pxref{Package Menu,,, emacs, The GNU Emacs Manual}).
|
||||
|
||||
Default key bindings available for both ``package-list'' and
|
||||
``generation-list'' buffers:
|
||||
|
||||
@table @kbd
|
||||
@item m
|
||||
Mark the current entry (with prefix, mark all entries).
|
||||
@item u
|
||||
Unmark the current entry (with prefix, unmark all entries).
|
||||
@item @key{DEL}
|
||||
Unmark backward.
|
||||
@item S
|
||||
Sort entries by a specified column.
|
||||
@end table
|
||||
|
||||
A ``package-list'' buffer additionally provides the following bindings:
|
||||
|
||||
@table @kbd
|
||||
@item @key{RET}
|
||||
Describe marked packages (display available information in a
|
||||
``package-info'' buffer).
|
||||
@item i
|
||||
Mark the current package for installation.
|
||||
@item d
|
||||
Mark the current package for deletion.
|
||||
@item U
|
||||
Mark the current package for upgrading.
|
||||
@item ^
|
||||
Mark all obsolete packages for upgrading.
|
||||
@item e
|
||||
Edit the definition of the curent package (go to its location). This is
|
||||
similar to @command{guix edit} command (@pxref{Invoking guix edit}), but
|
||||
for opening a package recipe in the current Emacs instance.
|
||||
@item x
|
||||
Execute actions on the marked packages.
|
||||
@end table
|
||||
|
||||
A ``generation-list'' buffer additionally provides the following
|
||||
bindings:
|
||||
|
||||
@table @kbd
|
||||
@item @key{RET}
|
||||
List packages installed in the current generation.
|
||||
@item i
|
||||
Describe marked generations (display available information in a
|
||||
``generation-info'' buffer).
|
||||
@item s
|
||||
Switch profile to the current generation.
|
||||
@item d
|
||||
Mark the current generation for deletion (with prefix, mark all
|
||||
generations).
|
||||
@item x
|
||||
Execute actions on the marked generations---i.e., delete generations.
|
||||
@item e
|
||||
Run Ediff (@pxref{Top,,, ediff, The Ediff Manual}) on package outputs
|
||||
installed in the 2 marked generations. With prefix argument, run Ediff
|
||||
on manifests of the marked generations.
|
||||
@item D
|
||||
@itemx =
|
||||
Run Diff (@pxref{Diff Mode,,, emacs, The GNU Emacs Manual}) on package
|
||||
outputs installed in the 2 marked generations. With prefix argument,
|
||||
run Diff on manifests of the marked generations.
|
||||
@item +
|
||||
List package outputs added to the latest marked generation comparing
|
||||
with another marked generation.
|
||||
@item -
|
||||
List package outputs removed from the latest marked generation comparing
|
||||
with another marked generation.
|
||||
@end table
|
||||
|
||||
@node Emacs Info buffer
|
||||
@subsection ``Info'' buffer
|
||||
|
||||
The interface of an ``info'' buffer is similar to the interface of
|
||||
@code{help-mode} (@pxref{Help Mode,,, emacs, The GNU Emacs Manual}).
|
||||
|
||||
``Info'' buffer contains some buttons (as usual you may use @key{TAB} /
|
||||
@kbd{S-@key{TAB}} to move between buttons---@pxref{Mouse References,,,
|
||||
emacs, The GNU Emacs Manual}) which can be used to:
|
||||
|
||||
@itemize @bullet
|
||||
@item (in a ``package-info'' buffer)
|
||||
|
||||
@itemize @minus
|
||||
@item install/remove a package;
|
||||
@item jump to a package location;
|
||||
@item browse home page of a package;
|
||||
@item describe packages from ``Inputs'' fields.
|
||||
@end itemize
|
||||
|
||||
@item (in a ``generation-info'' buffer)
|
||||
|
||||
@itemize @minus
|
||||
@item remove a generation;
|
||||
@item switch to a generation;
|
||||
@item list packages installed in a generation;
|
||||
@item jump to a generation directory.
|
||||
@end itemize
|
||||
|
||||
@end itemize
|
||||
|
||||
It is also possible to copy a button label (a link to an URL or a file)
|
||||
by pressing @kbd{c} on a button.
|
||||
|
||||
|
||||
@node Emacs Configuration
|
||||
@subsection Configuration
|
||||
|
||||
There are many variables you can modify to change the appearance or
|
||||
behavior of Emacs user interface. Some of these variables are described
|
||||
in this section. Also you can use Custom Interface (@pxref{Easy
|
||||
Customization,,, emacs, The GNU Emacs Manual}) to explore/set variables
|
||||
(not all) and faces.
|
||||
|
||||
@menu
|
||||
* Guile and Build Options: Emacs Build Options. Specifying how packages are built.
|
||||
* Buffer Names: Emacs Buffer Names. Names of Guix buffers.
|
||||
* Keymaps: Emacs Keymaps. Configuring key bindings.
|
||||
* Appearance: Emacs Appearance. Settings for visual appearance.
|
||||
@end menu
|
||||
|
||||
@node Emacs Build Options
|
||||
@subsubsection Guile and Build Options
|
||||
|
||||
@table @code
|
||||
@item guix-guile-program
|
||||
If you have some special needs for starting a Guile process, you may set
|
||||
this variable, for example:
|
||||
|
||||
@example
|
||||
(setq guix-guile-program '("/bin/guile" "--no-auto-compile"))
|
||||
@end example
|
||||
|
||||
@item guix-use-substitutes
|
||||
Has the same meaning as @code{--no-substitutes} option (@pxref{Invoking
|
||||
guix build}).
|
||||
|
||||
@item guix-dry-run
|
||||
Has the same meaning as @code{--dry-run} option (@pxref{Invoking guix
|
||||
build}).
|
||||
|
||||
@end table
|
||||
|
||||
@node Emacs Buffer Names
|
||||
@subsubsection Buffer Names
|
||||
|
||||
Default names of ``guix.el'' buffers (``*Guix@tie{}@dots{}*'') may be
|
||||
changed with the following variables:
|
||||
|
||||
@table @code
|
||||
@item guix-package-list-buffer-name
|
||||
@item guix-output-list-buffer-name
|
||||
@item guix-generation-list-buffer-name
|
||||
@item guix-package-info-buffer-name
|
||||
@item guix-output-info-buffer-name
|
||||
@item guix-generation-info-buffer-name
|
||||
@item guix-repl-buffer-name
|
||||
@item guix-internal-repl-buffer-name
|
||||
@end table
|
||||
|
||||
By default, the name of a profile is also displayed in a ``list'' or
|
||||
``info'' buffer name. To change this behavior, use
|
||||
@code{guix-buffer-name-function} variable.
|
||||
|
||||
For example, if you want to display all types of results in a single
|
||||
buffer (in such case you will probably use a history (@kbd{l}/@kbd{r})
|
||||
extensively), you may do it like this:
|
||||
|
||||
@example
|
||||
(let ((name "Guix Universal"))
|
||||
(setq
|
||||
guix-package-list-buffer-name name
|
||||
guix-output-list-buffer-name name
|
||||
guix-generation-list-buffer-name name
|
||||
guix-package-info-buffer-name name
|
||||
guix-output-info-buffer-name name
|
||||
guix-generation-info-buffer-name name
|
||||
guix-buffer-name-function #'guix-buffer-name-simple))
|
||||
@end example
|
||||
|
||||
@node Emacs Keymaps
|
||||
@subsubsection Keymaps
|
||||
|
||||
If you want to change default key bindings, use the following keymaps
|
||||
(@pxref{Init Rebinding,,, emacs, The GNU Emacs Manual}):
|
||||
|
||||
@table @code
|
||||
@item guix-root-map
|
||||
Parent keymap with general keys for all guix modes.
|
||||
|
||||
@item guix-list-mode-map
|
||||
Parent keymap with general keys for ``list'' buffers.
|
||||
|
||||
@item guix-package-list-mode-map
|
||||
Keymap with specific keys for ``package-list'' buffers.
|
||||
|
||||
@item guix-output-list-mode-map
|
||||
Keymap with specific keys for ``output-list'' buffers.
|
||||
|
||||
@item guix-generation-list-mode-map
|
||||
Keymap with specific keys for ``generation-list'' buffers.
|
||||
|
||||
@item guix-info-mode-map
|
||||
Parent keymap with general keys for ``info'' buffers.
|
||||
|
||||
@item guix-package-info-mode-map
|
||||
Keymap with specific keys for ``package-info'' buffers.
|
||||
|
||||
@item guix-output-info-mode-map
|
||||
Keymap with specific keys for ``output-info'' buffers.
|
||||
|
||||
@item guix-generation-info-mode-map
|
||||
Keymap with specific keys for ``generation-info'' buffers.
|
||||
|
||||
@item guix-info-button-map
|
||||
Keymap with keys available when a point is placed on a button.
|
||||
|
||||
@end table
|
||||
|
||||
@node Emacs Appearance
|
||||
@subsubsection Appearance
|
||||
|
||||
You can change almost any aspect of ``list'' / ``info'' buffers using
|
||||
the following variables:
|
||||
|
||||
@table @code
|
||||
@item guix-list-column-format
|
||||
@itemx guix-list-column-titles
|
||||
@itemx guix-list-column-value-methods
|
||||
Specify the columns, their names, what and how is displayed in ``list''
|
||||
buffers.
|
||||
|
||||
@item guix-info-displayed-params
|
||||
@itemx guix-info-insert-methods
|
||||
@itemx guix-info-ignore-empty-vals
|
||||
@itemx guix-info-param-title-format
|
||||
@itemx guix-info-multiline-prefix
|
||||
@itemx guix-info-indent
|
||||
@itemx guix-info-fill-column
|
||||
@itemx guix-info-delimiter
|
||||
Various settings for ``info'' buffers.
|
||||
|
||||
@end table
|
||||
|
||||
|
||||
@node Emacs Popup Interface
|
||||
@section Popup Interface
|
||||
|
||||
If you ever used Magit, you know what ``popup interface'' is
|
||||
(@pxref{Top,,, magit-popup, Magit-Popup User Manual}). Even if you are
|
||||
not acquainted with Magit, there should be no worries as it is very
|
||||
intuitive.
|
||||
|
||||
So @kbd{M-x@tie{}guix} command provides a top-level popup interface for
|
||||
all available guix commands. When you select an option, you'll be
|
||||
prompted for a value in the minibuffer. Many values have completions,
|
||||
so don't hesitate to press @key{TAB} key. Multiple values (for example,
|
||||
packages or lint checkers) should be separated by commas.
|
||||
|
||||
After specifying all options and switches for a command, you may choose
|
||||
one of the available actions. The following default actions are
|
||||
available for all commands:
|
||||
|
||||
@itemize
|
||||
|
||||
@item
|
||||
Run the command in the Guix REPL. It is faster than running
|
||||
@code{guix@tie{}@dots{}} command directly in shell, as there is no
|
||||
need to run another guile process and to load required modules there.
|
||||
|
||||
@item
|
||||
Run the command in a shell buffer. You can set
|
||||
@code{guix-run-in-shell-function} variable to fine tune the shell buffer
|
||||
you want to use.
|
||||
|
||||
@item
|
||||
Add the command line to the kill ring (@pxref{Kill Ring,,, emacs, The
|
||||
GNU Emacs Manual}).
|
||||
|
||||
@end itemize
|
||||
|
||||
Several commands (@command{guix graph}, @command{guix system dmd-graph}
|
||||
and @command{guix system extension-graph}) also have a ``View graph''
|
||||
action, which allows you to view a generated graph using @command{dot}
|
||||
command (specified by @code{guix-dot-program} variable). By default a
|
||||
PNG file will be saved in @file{/tmp} directory and will be opened
|
||||
directly in Emacs. This behavior may be changed with the following
|
||||
variables:
|
||||
|
||||
@table @code
|
||||
|
||||
@item guix-find-file-function
|
||||
Function used to open a generated graph. If you want to open a graph in
|
||||
an external program, you can do it by modifying this variable---for
|
||||
example, you can use a functionality provided by the Org Mode
|
||||
(@pxref{Top,,, org, The Org Manual}):
|
||||
|
||||
@example
|
||||
(setq guix-find-file-function 'org-open-file)
|
||||
(add-to-list 'org-file-apps '("\\.png\\'" . "sxiv %s"))
|
||||
@end example
|
||||
|
||||
@item guix-dot-default-arguments
|
||||
Command line arguments to run @command{dot} command. If you change an
|
||||
output format (for example, into @code{-Tpdf}), you also need to change
|
||||
the next variable.
|
||||
|
||||
@item guix-dot-file-name-function
|
||||
Function used to define a name of the generated graph file. Default
|
||||
name is @file{/tmp/guix-emacs-graph-XXXXXX.png}.
|
||||
|
||||
@end table
|
||||
|
||||
So, for example, if you want to generate and open a PDF file in your
|
||||
Emacs, you may change the settings like this:
|
||||
|
||||
@example
|
||||
(defun my-guix-pdf-graph ()
|
||||
"/tmp/my-current-guix-graph.pdf")
|
||||
|
||||
(setq guix-dot-default-arguments '("-Tpdf")
|
||||
guix-dot-file-name-function 'my-guix-pdf-graph)
|
||||
@end example
|
||||
|
||||
|
||||
@node Emacs Prettify
|
||||
@section Guix Prettify Mode
|
||||
|
||||
GNU@tie{}Guix also comes with ``guix-prettify.el''. It provides a minor
|
||||
mode for abbreviating store file names by replacing hash sequences of
|
||||
symbols with ``@dots{}'':
|
||||
|
||||
@example
|
||||
/gnu/store/72f54nfp6g1hz873w8z3gfcah0h4nl9p-foo-0.1
|
||||
@result{} /gnu/store/…-foo-0.1
|
||||
@end example
|
||||
|
||||
Once you set up ``guix.el'' (@pxref{Emacs Initial Setup}), the following
|
||||
commands become available:
|
||||
|
||||
@table @kbd
|
||||
|
||||
@item M-x guix-prettify-mode
|
||||
Enable/disable prettifying for the current buffer.
|
||||
|
||||
@item M-x global-guix-prettify-mode
|
||||
Enable/disable prettifying globally.
|
||||
|
||||
@end table
|
||||
|
||||
To automatically enable @code{guix-prettify-mode} globally on Emacs
|
||||
start, add the following line to your init file:
|
||||
|
||||
@example
|
||||
(global-guix-prettify-mode)
|
||||
@end example
|
||||
|
||||
If you want to enable it only for specific major modes, add it to the
|
||||
mode hooks (@pxref{Hooks,,, emacs, The GNU Emacs Manual}), for example:
|
||||
|
||||
@example
|
||||
(add-hook 'shell-mode-hook 'guix-prettify-mode)
|
||||
(add-hook 'dired-mode-hook 'guix-prettify-mode)
|
||||
@end example
|
||||
|
||||
|
||||
@node Emacs Build Log
|
||||
@section Build Log Mode
|
||||
|
||||
GNU@tie{}Guix provides major and minor modes for highlighting build
|
||||
logs. So when you have a file with a package build output---for
|
||||
example, a file returned by @command{guix build --log-file @dots{}}
|
||||
command (@pxref{Invoking guix build}), you may call @kbd{M-x
|
||||
guix-build-log-mode} command in the buffer with this file. This major
|
||||
mode highlights some lines specific to build output and provides the
|
||||
following key bindings:
|
||||
|
||||
@table @kbd
|
||||
|
||||
@item M-n
|
||||
Move to the next build phase.
|
||||
|
||||
@item M-p
|
||||
Move to the previous build phase.
|
||||
|
||||
@item @key{TAB}
|
||||
Toggle (show/hide) the body of the current build phase.
|
||||
|
||||
@item S-@key{TAB}
|
||||
Toggle (show/hide) the bodies of all build phases.
|
||||
|
||||
@end table
|
||||
|
||||
There is also @kbd{M-x guix-build-log-minor-mode} which also provides
|
||||
the same highlighting (but not key bindings). And as it is a minor
|
||||
mode, it can be enabled in any buffer. For example, if you are building
|
||||
some package in a shell buffer (@pxref{Interactive Shell,,, emacs, The
|
||||
GNU Emacs Manual}), you may enable @command{guix-build-log-minor-mode}
|
||||
to make it more colorful. Guix build output is rather specific, so this
|
||||
new highlighting shouldn't conflict with the existing one.
|
||||
|
||||
|
||||
@node Emacs Completions
|
||||
@section Shell Completions
|
||||
|
||||
Another feature that becomes available after configuring Emacs interface
|
||||
(@pxref{Emacs Initial Setup}) is completing of @command{guix}
|
||||
subcommands, options, packages and other things in @code{shell}
|
||||
(@pxref{Interactive Shell,,, emacs, The GNU Emacs Manual}) and
|
||||
@code{eshell} (@pxref{Top,,, eshell, Eshell: The Emacs Shell}).
|
||||
|
||||
It works the same way as other completions do. Just press @key{TAB}
|
||||
when your intuition tells you.
|
||||
|
||||
And here are some examples, where pressing @key{TAB} may complete
|
||||
something:
|
||||
|
||||
@itemize @w{}
|
||||
|
||||
@item @code{guix pa}@key{TAB}
|
||||
@item @code{guix package -}@key{TAB}
|
||||
@item @code{guix package --}@key{TAB}
|
||||
@item @code{guix package -i gei}@key{TAB}
|
||||
@item @code{guix build -L/tm}@key{TAB}
|
||||
@item @code{guix build --sy}@key{TAB}
|
||||
@item @code{guix build --system=i}@key{TAB}
|
||||
@item @code{guix system rec}@key{TAB}
|
||||
@item @code{guix lint --checkers=sy}@key{TAB}
|
||||
@item @code{guix lint --checkers=synopsis,des}@key{TAB}
|
||||
|
||||
@end itemize
|
||||
|
||||
|
||||
@node Emacs Development
|
||||
@section Development
|
||||
|
||||
By default, when you open a Scheme file, @code{guix-devel-mode} will be
|
||||
activated (if you don't want it, set @code{guix-devel-activate-mode} to
|
||||
nil). This minor mode provides the following key bindings:
|
||||
|
||||
@table @kbd
|
||||
|
||||
@item C-c . k
|
||||
Copy the name of the current Guile module into kill ring
|
||||
(@code{guix-devel-copy-module-as-kill}).
|
||||
|
||||
@item C-c . u
|
||||
Use the current Guile module. Often after opening a Scheme file, you
|
||||
want to use a module it defines, so you switch to the Geiser REPL and
|
||||
write @code{,use (some module)} there. You may just use this command
|
||||
instead (@code{guix-devel-use-module}).
|
||||
|
||||
@item C-c . b
|
||||
Build a package defined by the current variable definition. The
|
||||
building process is run in the current Geiser REPL. If you modified the
|
||||
current package definition, don't forget to reevaluate it before calling
|
||||
this command---for example, with @kbd{C-M-x} (@pxref{To eval or not to
|
||||
eval,,, geiser, Geiser User Manual})
|
||||
(@code{guix-devel-build-package-definition}).
|
||||
|
||||
@item C-c . s
|
||||
Build a source derivation of the package defined by the current variable
|
||||
definition. This command has the same meaning as @code{guix build -S}
|
||||
shell command (@pxref{Invoking guix build})
|
||||
(@code{guix-devel-build-package-source}).
|
||||
|
||||
@item C-c . l
|
||||
Lint (check) a package defined by the current variable definition
|
||||
(@pxref{Invoking guix lint}) (@code{guix-devel-lint-package}).
|
||||
|
||||
@end table
|
||||
|
||||
Unluckily, there is a limitation related to long-running REPL commands.
|
||||
When there is a running process in a Geiser REPL, you are not supposed
|
||||
to evaluate anything in a scheme buffer, because this will ``freeze''
|
||||
the REPL: it will stop producing any output (however, the evaluating
|
||||
process will continue---you will just not see any progress anymore). Be
|
||||
aware: even moving the point in a scheme buffer may ``break'' the REPL
|
||||
if Autodoc (@pxref{Autodoc and friends,,, geiser, Geiser User Manual})
|
||||
is enabled (which is the default).
|
||||
|
||||
So you have to postpone editing your scheme buffers until the running
|
||||
evaluation will be finished in the REPL.
|
||||
|
||||
Alternatively, to avoid this limitation, you may just run another Geiser
|
||||
REPL, and while something is being evaluated in the previous REPL, you
|
||||
can continue editing a scheme file with the help of the current one.
|
||||
+1209
-13185
File diff suppressed because it is too large
Load Diff
@@ -1,662 +0,0 @@
|
||||
# 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=2016-08-03.13; # UTC
|
||||
|
||||
# Copyright 2010, 2011, 2012, 2013, 2014, 2015 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# are permitted in any medium without royalty provided the copyright
|
||||
# notice and this notice are preserved.
|
||||
#
|
||||
# The latest version of this file is available at
|
||||
# http://ftpmirror.gnu.org/texinfo/htmlxref.cnf.
|
||||
# Email corrections or additions to bug-texinfo@gnu.org.
|
||||
# The primary goal is to list all relevant GNU manuals;
|
||||
# other free manuals are also welcome.
|
||||
#
|
||||
# To be included in this list, a manual must:
|
||||
#
|
||||
# - have a generic url, e.g., no version numbers;
|
||||
# - have a unique file name (e.g., manual identifier), i.e., be related to the
|
||||
# package name. Things like "refman" or "tutorial" don't work.
|
||||
# - follow the naming convention for nodes described at
|
||||
# http://www.gnu.org/software/texinfo/manual/texinfo/html_node/HTML-Xref.html
|
||||
# This is what makeinfo and texi2html implement.
|
||||
#
|
||||
# Unless the above criteria are met, it's not possible to generate
|
||||
# reliable cross-manual references.
|
||||
#
|
||||
# For information on automatically generating all the useful formats for
|
||||
# a manual to put on the web, see
|
||||
# http://www.gnu.org/prep/maintain/html_node/Manuals-on-Web-Pages.html.
|
||||
|
||||
# For people editing this file: when a manual named foo is related to a
|
||||
# package named bar, the url should contain a variable reference ${BAR}.
|
||||
# Otherwise, the gnumaint scripts have no way of knowing they are
|
||||
# associated, and thus gnu.org/manual can't include them.
|
||||
|
||||
# shorten references to manuals on www.gnu.org.
|
||||
G = http://www.gnu.org
|
||||
GS = ${G}/software
|
||||
|
||||
3dldf mono ${GS}/3dldf/manual/user_ref/3DLDF.html
|
||||
3dldf node ${GS}/3dldf/manual/user_ref/
|
||||
|
||||
alive mono ${GS}/alive/manual/alive.html
|
||||
alive node ${GS}/alive/manual/html_node/
|
||||
|
||||
anubis chapter ${GS}/anubis/manual/html_chapter/
|
||||
anubis section ${GS}/anubis/manual/html_section/
|
||||
anubis node ${GS}/anubis/manual/html_node/
|
||||
|
||||
artanis mono ${GS}/artanis/manual/artanis.html
|
||||
artanis node ${GS}/artanis/manual/html_node/
|
||||
|
||||
aspell section http://aspell.net/man-html/index.html
|
||||
|
||||
auctex mono ${GS}/auctex/manual/auctex.html
|
||||
auctex node ${GS}/auctex/manual/auctex/
|
||||
|
||||
autoconf mono ${GS}/autoconf/manual/autoconf.html
|
||||
autoconf node ${GS}/autoconf/manual/html_node/
|
||||
|
||||
autogen mono ${GS}/autogen/manual/html_mono/autogen.html
|
||||
autogen chapter ${GS}/autogen/manual/html_chapter/
|
||||
autogen node ${GS}/autoconf/manual/html_node/
|
||||
|
||||
automake mono ${GS}/automake/manual/automake.html
|
||||
automake node ${GS}/automake/manual/html_node/
|
||||
|
||||
avl node http://www.stanford.edu/~blp/avl/libavl.html/
|
||||
|
||||
bash mono ${GS}/bash/manual/bash.html
|
||||
bash node ${GS}/bash/manual/html_node/
|
||||
|
||||
BINUTILS = http://sourceware.org/binutils/docs
|
||||
binutils node ${BINUTILS}/binutils/
|
||||
as node ${BINUTILS}/as/
|
||||
bfd node ${BINUTILS}/bfd/
|
||||
gprof node ${BINUTILS}/gprof/
|
||||
ld node ${BINUTILS}/ld/
|
||||
|
||||
bison mono ${GS}/bison/manual/bison.html
|
||||
bison node ${GS}/bison/manual/html_node/
|
||||
|
||||
bpel2owfn mono ${GS}/bpel2owfn/manual/2.0.x/bpel2owfn.html
|
||||
|
||||
ccd2cue mono ${GS}/ccd2cue/manual/ccd2cue.html
|
||||
ccd2cue node ${GS}/ccd2cue/manual/html_node/
|
||||
|
||||
cflow mono ${GS}/cflow/manual/cflow.html
|
||||
cflow node ${GS}/cflow/manual/html_node/
|
||||
|
||||
chess mono ${GS}/chess/manual/gnuchess.html
|
||||
chess node ${GS}/chess/manual/html_node/
|
||||
|
||||
combine mono ${GS}/combine/manual/combine.html
|
||||
combine chapter ${GS}/combine/manual/html_chapter/
|
||||
combine section ${GS}/combine/manual/html_section/
|
||||
combine node ${GS}/combine/manual/html_node/
|
||||
|
||||
complexity mono ${GS}/complexity/manual/complexity.html
|
||||
complexity node ${GS}/complexity/manual/html_node/
|
||||
|
||||
coreutils mono ${GS}/coreutils/manual/coreutils
|
||||
coreutils node ${GS}/coreutils/manual/html_node/
|
||||
|
||||
cpio mono ${GS}/cpio/manual/cpio
|
||||
cpio node ${GS}/cpio/manual/html_node/
|
||||
|
||||
cssc node ${GS}/cssc/manual/
|
||||
|
||||
#cvs cannot be handled here; see http://ximbiot.com/cvs/manual.
|
||||
|
||||
ddd mono ${GS}/ddd/manual/html_mono/ddd.html
|
||||
|
||||
ddrescue mono ${GS}/ddrescue/manual/ddrescue_manual.html
|
||||
|
||||
DICO = http://puszcza.gnu.org.ua/software/dico/manual
|
||||
dico mono ${DICO}/dico.html
|
||||
dico chapter ${DICO}/html_chapter/
|
||||
dico section ${DICO}/html_section/
|
||||
dico node ${DICO}/html_node/
|
||||
|
||||
diffutils mono ${GS}/diffutils/manual/diffutils
|
||||
diffutils node ${GS}/diffutils/manual/html_node/
|
||||
|
||||
ed mono ${GS}/ed/manual/ed_manual.html
|
||||
|
||||
EMACS = ${GS}/emacs/manual
|
||||
emacs mono ${EMACS}/html_mono/emacs.html
|
||||
emacs node ${EMACS}/html_node/emacs/
|
||||
#
|
||||
ada-mode mono ${EMACS}/html_mono/ada-mode.html
|
||||
ada-mode node ${EMACS}/html_node/ada-mode/
|
||||
#
|
||||
autotype mono ${EMACS}/html_mono/autotype.html
|
||||
autotype node ${EMACS}/html_node/autotype/
|
||||
#
|
||||
ccmode mono ${EMACS}/html_mono/ccmode.html
|
||||
ccmode node ${EMACS}/html_node/ccmode/
|
||||
#
|
||||
cl mono ${EMACS}/html_mono/cl.html
|
||||
cl node ${EMACS}/html_node/cl/
|
||||
#
|
||||
ebrowse mono ${EMACS}/html_mono/ebrowse.html
|
||||
ebrowse node ${EMACS}/html_node/ebrowse/
|
||||
#
|
||||
ediff mono ${EMACS}/html_mono/ediff.html
|
||||
ediff node ${EMACS}/html_node/ediff/
|
||||
#
|
||||
eieio mono ${EMACS}/html_mono/eieio.html
|
||||
eieio node ${EMACS}/html_node/eieio/
|
||||
#
|
||||
elisp mono ${EMACS}/html_mono/elisp.html
|
||||
elisp node ${EMACS}/html_node/elisp/
|
||||
#
|
||||
epa mono ${EMACS}/html_mono/epa.html
|
||||
epa node ${EMACS}/html_node/epa/
|
||||
#
|
||||
erc mono ${EMACS}/html_mono/erc.html
|
||||
erc node ${EMACS}/html_node/erc/
|
||||
#
|
||||
dired-x mono ${EMACS}/html_mono/dired-x.html
|
||||
dired-x node ${EMACS}/html_node/dired-x/
|
||||
#
|
||||
eshell mono ${EMACS}/html_mono/eshell.html
|
||||
eshell node ${EMACS}/html_node/eshell/
|
||||
#
|
||||
flymake mono ${EMACS}/html_mono/flymake.html
|
||||
flymake node ${EMACS}/html_node/flymake/
|
||||
#
|
||||
gnus mono ${EMACS}/html_mono/gnus.html
|
||||
gnus node ${EMACS}/html_node/gnus/
|
||||
#
|
||||
idlwave mono ${EMACS}/html_mono/idlwave.html
|
||||
idlwave node ${EMACS}/html_node/idlwave/
|
||||
#
|
||||
message mono ${EMACS}/html_mono/message.html
|
||||
message node ${EMACS}/html_node/message/
|
||||
#
|
||||
mh-e mono ${EMACS}/html_mono/mh-e.html
|
||||
mh-e node ${EMACS}/html_node/mh-e/
|
||||
#
|
||||
nxml-mode mono ${EMACS}/html_mono/nxml-mode.html
|
||||
nxml-mode node ${EMACS}/html_node/nxml-mode/
|
||||
#
|
||||
org mono ${EMACS}/html_mono/org.html
|
||||
org node ${EMACS}/html_node/org/
|
||||
#
|
||||
pcl-cvs mono ${EMACS}/html_mono/pcl-cvs.html
|
||||
pcl-cvs node ${EMACS}/html_node/pcl-cvs/
|
||||
#
|
||||
rcirc mono ${EMACS}/html_mono/rcirc.html
|
||||
rcirc node ${EMACS}/html_node/rcirc/
|
||||
#
|
||||
semantic mono ${EMACS}/html_mono/semantic.html
|
||||
semantic node ${EMACS}/html_node/semantic/
|
||||
#
|
||||
smtp mono ${EMACS}/html_mono/smtpmail.html
|
||||
smtp node ${EMACS}/html_node/smtpmail/
|
||||
#
|
||||
speedbar mono ${EMACS}/html_mono/speedbar.html
|
||||
speedbar node ${EMACS}/html_node/speedbar/
|
||||
#
|
||||
tramp mono ${EMACS}/html_mono/tramp.html
|
||||
tramp node ${EMACS}/html_node/tramp/
|
||||
#
|
||||
vip mono ${EMACS}/html_mono/vip.html
|
||||
vip node ${EMACS}/html_node/vip/
|
||||
#
|
||||
viper mono ${EMACS}/html_mono/viper.html
|
||||
viper node ${EMACS}/html_node/viper/
|
||||
#
|
||||
woman mono ${EMACS}/html_mono/woman.html
|
||||
woman node ${EMACS}/html_node/woman/
|
||||
# (end emacs manuals)
|
||||
|
||||
easejs mono ${GS}/easejs/manual/easejs.html
|
||||
easejs node ${GS}/easejs/manual/
|
||||
|
||||
EMACS_GUIX = https://alezost.github.io/guix.el/manual/latest
|
||||
emacs-guix mono ${EMACS_GUIX}/emacs-guix.html
|
||||
emacs-guix node ${EMACS_GUIX}/html_node/
|
||||
|
||||
emacs-muse node ${GS}/emacs-muse/manual/muse.html
|
||||
emacs-muse node ${GS}/emacs-muse/manual/html_node/
|
||||
|
||||
emms node ${GS}/emms/manual/
|
||||
|
||||
# The file is called 'find.info' but the package is 'findutils'.
|
||||
find mono ${GS}/findutils/manual/html_mono/find.html
|
||||
find node ${GS}/findutils/manual/html_node/find_html
|
||||
findutils mono ${GS}/findutils/manual/html_mono/find.html
|
||||
findutils node ${GS}/findutils/manual/html_node/find_html
|
||||
|
||||
FLEX = http://flex.sourceforge.net
|
||||
flex node ${FLEX}/manual/
|
||||
|
||||
gama mono ${GS}/gama/manual/gama.html
|
||||
gama node ${GS}/gama/manual/html_node/
|
||||
|
||||
GAWK = ${GS}/gawk/manual
|
||||
gawk mono ${GAWK}/gawk.html
|
||||
gawk node ${GAWK}/html_node/
|
||||
gawkinet mono ${GAWK}/gawkinet/gawkinet.html
|
||||
gawkinet node ${GAWK}/gawkinet/html_node/
|
||||
|
||||
gcal mono ${GS}/gcal/manual/gcal.html
|
||||
gcal node ${GS}/gcal/manual/html_node/
|
||||
|
||||
GCC = http://gcc.gnu.org/onlinedocs
|
||||
gcc node ${GCC}/gcc/
|
||||
cpp node ${GCC}/cpp/
|
||||
gcj node ${GCC}/gcj/
|
||||
gfortran node ${GCC}/gfortran/
|
||||
gnat_rm node ${GCC}/gnat_rm/
|
||||
gnat_ugn_unw node ${GCC}/gnat_ugn_unw/
|
||||
libgomp node ${GCC}/libgomp/
|
||||
libstdc++ node ${GCC}/libstdc++/
|
||||
#
|
||||
gccint node ${GCC}/gccint/
|
||||
cppinternals node ${GCC}/cppinternals/
|
||||
gfc-internals node ${GCC}/gfc-internals/
|
||||
gnat-style node ${GCC}/gnat-style/
|
||||
libiberty node ${GCC}/libiberty/
|
||||
|
||||
GDB = http://sourceware.org/gdb/current/onlinedocs
|
||||
gdb node ${GDB}/gdb/
|
||||
stabs node ${GDB}/stabs/
|
||||
|
||||
GDBM = http://www.gnu.org.ua/software/gdbm/manual
|
||||
gdbm mono ${GDBM}/gdbm.html
|
||||
gdbm chapter ${GDBM}/html_chapter/
|
||||
gdbm section ${GDBM}/html_section/
|
||||
gdbm node ${GDBM}/html_node/
|
||||
|
||||
gettext mono ${GS}/gettext/manual/gettext.html
|
||||
gettext node ${GS}/gettext/manual/html_node/
|
||||
|
||||
gforth node http://www.complang.tuwien.ac.at/forth/gforth/Docs-html/
|
||||
|
||||
global mono ${GS}/global/manual/global.html
|
||||
|
||||
gmediaserver node ${GS}/gmediaserver/manual/
|
||||
|
||||
gmp node http://www.gmplib.org/manual/
|
||||
|
||||
gnu-arch node ${GS}/gnu-arch/tutorial/
|
||||
|
||||
gnu-c-manual mono ${GS}/gnu-c-manual/gnu-c-manual.html
|
||||
|
||||
gnu-crypto node ${GS}/gnu-crypto/manual/
|
||||
|
||||
gnubg mono ${GS}/gnubg/manual/gnubg.html
|
||||
gnubg node ${GS}/gnubg/manual/html_node/
|
||||
|
||||
gnubik mono ${GS}/gnubik/manual/gnubik.html
|
||||
gnubik node ${GS}/gnubik/manual/html_node/
|
||||
|
||||
gnulib mono ${GS}/gnulib/manual/gnulib.html
|
||||
gnulib node ${GS}/gnulib/manual/html_node/
|
||||
|
||||
GNUN = ${GS}/trans-coord/manual
|
||||
gnun mono ${GNUN}/gnun/gnun.html
|
||||
gnun node ${GNUN}/gnun/html_node/
|
||||
web-trans mono ${GNUN}/web-trans/web-trans.html
|
||||
web-trans node ${GNUN}/web-trans/html_node/
|
||||
|
||||
GNUPG = http://www.gnupg.org/documentation/manuals
|
||||
gnupg node ${GNUPG}/gnupg/
|
||||
dirmngr node ${GNUPG}/dirmngr/
|
||||
gcrypt node ${GNUPG}/gcrypt/
|
||||
libgcrypt node ${GNUPG}/gcrypt/
|
||||
ksba node ${GNUPG}/ksba/
|
||||
assuan node ${GNUPG}/assuan/
|
||||
gpgme node ${GNUPG}/gpgme/
|
||||
|
||||
gnuprologjava node ${GS}/gnuprologjava/manual/
|
||||
|
||||
gnuschool mono ${GS}/gnuschool/gnuschool.html
|
||||
|
||||
GNUSTANDARDS = ${G}/prep
|
||||
maintain mono ${GNUSTANDARDS}/maintain/maintain.html
|
||||
maintain node ${GNUSTANDARDS}/maintain/html_node/
|
||||
#
|
||||
standards mono ${GNUSTANDARDS}/standards/standards.html
|
||||
standards node ${GNUSTANDARDS}/standards/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/
|
||||
|
||||
gperf mono ${GS}/gperf/manual/gperf.html
|
||||
gperf node ${GS}/gperf/manual/html_node/
|
||||
|
||||
grep mono ${GS}/grep/manual/grep.html
|
||||
grep node ${GS}/grep/manual/html_node/
|
||||
|
||||
groff node ${GS}/groff/manual/html_node/
|
||||
|
||||
GRUB = ${GS}/grub/manual
|
||||
grub mono ${GRUB}/grub.html
|
||||
grub node ${GRUB}/html_node/
|
||||
#
|
||||
multiboot mono ${GRUB}/multiboot/multiboot.html
|
||||
multiboot node ${GRUB}/multiboot/html_node/
|
||||
|
||||
gsasl mono ${GS}/gsasl/manual/gsasl.html
|
||||
gsasl node ${GS}/gsasl/manual/html_node/
|
||||
|
||||
gsl node ${GS}/gsl/manual/html_node/
|
||||
|
||||
gsrc mono ${GS}/gsrc/manual/gsrc.html
|
||||
gsrc node ${GS}/gsrc/manual/html_node/
|
||||
|
||||
gss mono ${GS}/gss/manual/gss.html
|
||||
gss node ${GS}/gss/manual/html_node/
|
||||
|
||||
gtypist mono ${GS}/gtypist/doc/
|
||||
|
||||
guile mono ${GS}/guile/manual/guile.html
|
||||
guile node ${GS}/guile/manual/html_node/
|
||||
|
||||
guile-avahi mono http://nongnu.org/guile-avahi/doc/guile-avahi.html
|
||||
|
||||
GUILE_GNOME = ${GS}/guile-gnome/docs
|
||||
gobject node ${GUILE_GNOME}/gobject/html/
|
||||
glib node ${GUILE_GNOME}/glib/html/
|
||||
atk node ${GUILE_GNOME}/atk/html/
|
||||
pango node ${GUILE_GNOME}/pango/html/
|
||||
pangocairo node ${GUILE_GNOME}/pangocairo/html/
|
||||
gdk node ${GUILE_GNOME}/gdk/html/
|
||||
gtk node ${GUILE_GNOME}/gtk/html/
|
||||
libglade node ${GUILE_GNOME}/libglade/html/
|
||||
gnome-vfs node ${GUILE_GNOME}/gnome-vfs/html/
|
||||
libgnomecanvas node ${GUILE_GNOME}/libgnomecanvas/html/
|
||||
gconf node ${GUILE_GNOME}/gconf/html/
|
||||
libgnome node ${GUILE_GNOME}/libgnome/html/
|
||||
libgnomeui node ${GUILE_GNOME}/libgnomeui/html/
|
||||
corba node ${GUILE_GNOME}/corba/html/
|
||||
clutter node ${GUILE_GNOME}/clutter/html/
|
||||
clutter-glx node ${GUILE_GNOME}/clutter-glx/html/
|
||||
|
||||
guile-gtk node ${GS}/guile-gtk/docs/guile-gtk/
|
||||
|
||||
guile-rpc mono ${GS}/guile-rpc/manual/guile-rpc.html
|
||||
guile-rpc node ${GS}/guile-rpc/manual/html_node/
|
||||
|
||||
guix mono ${GS}/guix/manual/guix.html
|
||||
guix node ${GS}/guix/manual/html_node/
|
||||
|
||||
gv mono ${GS}/gv/manual/gv.html
|
||||
gv node ${GS}/gv/manual/html_node/
|
||||
|
||||
gzip mono ${GS}/gzip/manual/gzip.html
|
||||
gzip node ${GS}/gzip/manual/html_node/
|
||||
|
||||
hello mono ${GS}/hello/manual/hello.html
|
||||
hello node ${GS}/hello/manual/html_node/
|
||||
|
||||
help2man mono ${GS}/help2man/help2man.html
|
||||
|
||||
idutils mono ${GS}/idutils/manual/idutils.html
|
||||
idutils node ${GS}/idutils/manual/html_node/
|
||||
|
||||
inetutils mono ${GS}/inetutils/manual/inetutils.html
|
||||
inetutils node ${GS}/inetutils/manual/html_node/
|
||||
|
||||
jwhois mono ${GS}/jwhois/manual/jwhois.html
|
||||
jwhois node ${GS}/jwhois/manual/html_node/
|
||||
|
||||
libc mono ${GS}/libc/manual/html_mono/libc.html
|
||||
libc node ${GS}/libc/manual/html_node/
|
||||
|
||||
LIBCDIO = ${GS}/libcdio
|
||||
libcdio mono ${LIBCDIO}/libcdio.html
|
||||
cd-text mono ${LIBCDIO}/cd-text-format.html
|
||||
|
||||
libextractor mono ${GS}/libextractor/manual/libextractor.html
|
||||
libextractor node ${GS}/libextractor/manual/html_node/
|
||||
|
||||
libidn mono ${GS}/libidn/manual/libidn.html
|
||||
libidn node ${GS}/libidn/manual/html_node/
|
||||
|
||||
librejs mono ${GS}/librejs/manual/librejs.html
|
||||
librejs node ${GS}/librejs/manual/html_node/
|
||||
|
||||
libmatheval mono ${GS}/libmatheval/manual/libmatheval.html
|
||||
|
||||
LIBMICROHTTPD = ${GS}/libmicrohttpd
|
||||
libmicrohttpd mono ${LIBMICROHTTPD}/manual/libmicrohttpd.html
|
||||
libmicrohttpd node ${LIBMICROHTTPD}/manual/html_node/
|
||||
microhttpd-tutorial mono ${LIBMICROHTTPD}/tutorial.html
|
||||
|
||||
libtasn1 mono ${GS}/libtasn1/manual/libtasn1.html
|
||||
libtasn1 node ${GS}/libtasn1/manual/html_node/
|
||||
|
||||
libtool mono ${GS}/libtool/manual/libtool.html
|
||||
libtool node ${GS}/libtool/manual/html_node/
|
||||
|
||||
lightning mono ${GS}/lightning/manual/lightning.html
|
||||
lightning node ${GS}/lightning/manual/html_node/
|
||||
|
||||
# The stable/ url redirects immediately, but that's ok.
|
||||
# The .html extension is omitted on their web site, but it works if given.
|
||||
LILYPOND = http://lilypond.org/doc/stable/Documentation
|
||||
lilypond-internals node ${LILYPOND}/internals/
|
||||
lilypond-learning node ${LILYPOND}/learning/
|
||||
lilypond-notation node ${LILYPOND}/notation/
|
||||
lilypond-snippets node ${LILYPOND}/snippets/
|
||||
lilypond-usage node ${LILYPOND}/usage/
|
||||
lilypond-web node ${LILYPOND}/web/
|
||||
music-glossary node ${LILYPOND}/music-glossary/
|
||||
|
||||
liquidwar6 mono ${GS}/liquidwar6/manual/liquidwar6.html
|
||||
liquidwar6 node ${GS}/liquidwar6/manual/html_node/
|
||||
|
||||
lispintro mono ${GS}/emacs/emacs-lisp-intro/html_mono/emacs-lisp-intro.html
|
||||
lispintro node ${GS}/emacs/emacs-lisp-intro/html_node/index.html
|
||||
|
||||
LSH = http://www.lysator.liu.se/~nisse/lsh
|
||||
lsh mono ${LSH}/lsh.html
|
||||
|
||||
m4 mono ${GS}/m4/manual/m4.html
|
||||
m4 node ${GS}/m4/manual/html_node/
|
||||
|
||||
mailutils mono ${GS}/mailutils/manual/mailutils.html
|
||||
mailutils chapter ${GS}/mailutils/manual/html_chapter/
|
||||
mailutils section ${GS}/mailutils/manual/html_section/
|
||||
mailutils node ${GS}/mailutils/manual/html_node/
|
||||
|
||||
make mono ${GS}/make/manual/make.html
|
||||
make node ${GS}/make/manual/html_node/
|
||||
|
||||
mcron mono ${GS}/mcron/manual/mcron.html
|
||||
mcron node ${GS}/mcron/manual/html_node/
|
||||
|
||||
mdk mono ${GS}/mdk/manual/mdk.html
|
||||
mdk node ${GS}/mdk/manual/html_node/
|
||||
|
||||
METAEXCHANGE = http://ftp.gwdg.de/pub/gnu2/iwfmdh/doc/texinfo
|
||||
iwf_mh node ${METAEXCHANGE}/iwf_mh.html
|
||||
scantest node ${METAEXCHANGE}/scantest.html
|
||||
|
||||
MIT_SCHEME = ${GS}/mit-scheme/documentation
|
||||
mit-scheme-ref node ${MIT_SCHEME}/mit-scheme-ref/
|
||||
mit-scheme-user node ${MIT_SCHEME}/mit-scheme-user/
|
||||
sos node ${MIT_SCHEME}/mit-scheme-sos/
|
||||
mit-scheme-imail node ${MIT_SCHEME}/mit-scheme-imail/
|
||||
|
||||
moe mono ${GS}/moe/manual/moe_manual.html
|
||||
|
||||
motti node ${GS}/motti/manual/
|
||||
|
||||
mpc node http://www.multiprecision.org/index.php?prog=mpc&page=html
|
||||
|
||||
mpfr mono http://www.mpfr.org/mpfr-current/mpfr.html
|
||||
|
||||
mtools mono ${GS}/mtools/manual/mtools.html
|
||||
|
||||
myserver node http://www.myserverproject.net/documentation/
|
||||
|
||||
nano mono http://www.nano-editor.org/dist/latest/nano.html
|
||||
|
||||
nettle chapter http://www.lysator.liu.se/~nisse/nettle/nettle.html
|
||||
|
||||
ocrad mono ${GS}/ocrad/manual/ocrad_manual.html
|
||||
|
||||
parted mono ${GS}/parted/manual/parted.html
|
||||
parted node ${GS}/parted/manual/html_node/
|
||||
|
||||
pascal mono http://www.gnu-pascal.de/gpc/
|
||||
|
||||
# can't use pcb since url's contain dates --30nov10
|
||||
|
||||
perl mono ${GS}/perl/manual/perldoc-all.html
|
||||
|
||||
PIES = http://www.gnu.org.ua/software/pies/manual
|
||||
pies mono ${PIES}/pies.html
|
||||
pies chapter ${PIES}/html_chapter/
|
||||
pies section ${PIES}/html_section/
|
||||
pies node ${PIES}/html_node/
|
||||
|
||||
plotutils mono ${GS}/plotutils/manual/en/plotutils.html
|
||||
plotutils node ${GS}/plotutils/manual/en/html_node/
|
||||
|
||||
proxyknife mono ${GS}/proxyknife/manual/proxyknife.html
|
||||
proxyknife node ${GS}/proxyknife/manual/html_node/
|
||||
|
||||
pspp mono ${GS}/pspp/manual/pspp.html
|
||||
pspp node ${GS}/pspp/manual/html_node/
|
||||
|
||||
pyconfigure mono ${GS}/pyconfigure/manual/pyconfigure.html
|
||||
pyconfigure node ${GS}/pyconfigure/manual/html_node/
|
||||
|
||||
R = http://cran.r-project.org/doc/manuals
|
||||
R-intro mono ${R}/R-intro.html
|
||||
R-lang mono ${R}/R-lang.html
|
||||
R-exts mono ${R}/R-exts.html
|
||||
R-data mono ${R}/R-data.html
|
||||
R-admin mono ${R}/R-admin.html
|
||||
R-ints mono ${R}/R-ints.html
|
||||
|
||||
rcs mono ${GS}/rcs/manual/rcs.html
|
||||
rcs node ${GS}/rcs/manual/html_node/
|
||||
|
||||
READLINE = http://cnswww.cns.cwru.edu/php/chet/readline
|
||||
readline mono ${READLINE}/readline.html
|
||||
rluserman mono ${READLINE}/rluserman.html
|
||||
history mono ${READLINE}/history.html
|
||||
|
||||
recode mono http://recode.progiciels-bpi.ca/manual/index.html
|
||||
|
||||
recutils mono ${GS}/recutils/manual/recutils.html
|
||||
recutils node ${GS}/recutils/manual/html_node/
|
||||
|
||||
reftex mono ${GS}/auctex/manual/reftex.html
|
||||
reftex node ${GS}/auctex/manual/reftex/
|
||||
|
||||
remotecontrol mono ${GS}/remotecontrol/manual/remotecontrol.html
|
||||
remotecontrol node ${GS}/remotecontrol/manual/html_node/
|
||||
|
||||
rottlog mono ${GS}/rottlog/manual/rottlog.html
|
||||
rottlog node ${GS}/rottlog/manual/html_node/
|
||||
|
||||
RUSH = http://www.gnu.org.ua/software/rush/manual
|
||||
rush mono ${RUSH}/rush.html
|
||||
rush chapter ${RUSH}/html_chapter/
|
||||
rush section ${RUSH}/html_section/
|
||||
rush node ${RUSH}/html_node/
|
||||
|
||||
screen mono ${GS}/screen/manual/screen.html
|
||||
screen node ${GS}/screen/manual/html_node/
|
||||
|
||||
sed mono ${GS}/sed/manual/sed.html
|
||||
sed node ${GS}/sed/manual/html_node/
|
||||
|
||||
sharutils mono ${GS}/sharutils/manual/html_mono/sharutils.html
|
||||
sharutils chapter ${GS}/sharutils/manual/html_chapter/
|
||||
sharutils node ${GS}/sharutils/manual/html_node/
|
||||
|
||||
shepherd mono ${GS}/shepherd/manual/shepherd.html
|
||||
shepherd node ${GS}/shepherd/manual/html_node/
|
||||
|
||||
# can't use mono files since they have generic names
|
||||
SMALLTALK = ${GS}/smalltalk
|
||||
smalltalk node ${SMALLTALK}/manual/html_node/
|
||||
smalltalk-base node ${SMALLTALK}/manual-base/html_node/
|
||||
smalltalk-libs node ${SMALLTALK}/manual-libs/html_node/
|
||||
|
||||
sourceinstall mono ${GS}/sourceinstall/manual/sourceinstall.html
|
||||
sourceinstall node ${GS}/sourceinstall/manual/html_node/
|
||||
|
||||
sqltutor mono ${GS}/sqltutor/manual/sqltutor.html
|
||||
sqltutor node ${GS}/sqltutor/manual/html_node/
|
||||
|
||||
src-highlite mono ${GS}/src-highlite/source-highlight.html
|
||||
|
||||
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}/autoconf/manual/html_node/
|
||||
|
||||
teseq mono ${GS}/teseq/teseq.html
|
||||
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/
|
||||
|
||||
thales node ${GS}/thales/manual/
|
||||
|
||||
units mono ${GS}/units/manual/units.html
|
||||
units node ${GS}/units/manual/html_node/
|
||||
|
||||
vc-dwim mono ${GS}/vc-dwim/manual/vc-dwim.html
|
||||
vc-dwim node ${GS}/vc-dwim/manual/html_node/
|
||||
|
||||
wdiff mono ${GS}/wdiff/manual/wdiff.html
|
||||
wdiff node ${GS}/wdiff/manual/html_node/
|
||||
|
||||
websocket4j mono ${GS}/websocket4j/manual/websocket4j.html
|
||||
websocket4j node ${GS}/websocket4j/manual/html_node/
|
||||
|
||||
wget mono ${GS}/wget/manual/wget.html
|
||||
wget node ${GS}/wget/manual/html_node/
|
||||
|
||||
xboard mono ${GS}/xboard/manual/xboard.html
|
||||
xboard node ${GS}/xboard/manual/html_node/
|
||||
|
||||
# emacs-page
|
||||
# Free TeX-related Texinfo manuals on tug.org.
|
||||
|
||||
T = http://tug.org/texinfohtml
|
||||
|
||||
dvipng mono ${T}/dvipng.html
|
||||
dvips mono ${T}/dvips.html
|
||||
eplain mono ${T}/eplain.html
|
||||
kpathsea mono ${T}/kpathsea.html
|
||||
latex2e mono ${T}/latex2e.html
|
||||
tlbuild mono ${T}/tlbuild.html
|
||||
web2c mono ${T}/web2c.html
|
||||
|
||||
|
||||
# Local Variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "htmlxrefversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
@@ -1,111 +0,0 @@
|
||||
digraph "Guix bag" {
|
||||
"/gnu/store/aymf6jlxxpwgr71rkiz24m646nqsyii6-glibc-intermediate-2.24.drv" [label = "glibc-intermediate-2.24", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/aymf6jlxxpwgr71rkiz24m646nqsyii6-glibc-intermediate-2.24.drv" -> "/gnu/store/wx8ifbb7x22cl4998fyldsr24fcv18j3-texinfo-6.3.drv" [color = magenta];
|
||||
"/gnu/store/aymf6jlxxpwgr71rkiz24m646nqsyii6-glibc-intermediate-2.24.drv" -> "/gnu/store/ccj3as3258l70lmphi48hs7n017wv75s-perl-boot0-5.24.0.drv" [color = magenta];
|
||||
"/gnu/store/aymf6jlxxpwgr71rkiz24m646nqsyii6-glibc-intermediate-2.24.drv" -> "/gnu/store/w9adgzgdqkwz0w13zxf2fn363v9wcllc-gcc-cross-boot0-4.9.4.drv" [color = magenta];
|
||||
"/gnu/store/aymf6jlxxpwgr71rkiz24m646nqsyii6-glibc-intermediate-2.24.drv" -> "/gnu/store/72snmrnjphwjxffknjhzm3xg38wd08al-ld-wrapper-x86_64-guix-linux-gnu-0.drv" [color = magenta];
|
||||
"/gnu/store/aymf6jlxxpwgr71rkiz24m646nqsyii6-glibc-intermediate-2.24.drv" -> "/gnu/store/v1v7jp438hc5rpgriwpjp04x049vh0g4-binutils-cross-boot0-2.27.drv" [color = magenta];
|
||||
"/gnu/store/aymf6jlxxpwgr71rkiz24m646nqsyii6-glibc-intermediate-2.24.drv" -> "/gnu/store/1jpld53g41rzv2bmjp6v9mckmyw75vs3-make-boot0-4.2.1.drv" [color = magenta];
|
||||
"/gnu/store/aymf6jlxxpwgr71rkiz24m646nqsyii6-glibc-intermediate-2.24.drv" -> "/gnu/store/zpphawi07xidhfs2dja3w7hmnfp99j02-diffutils-boot0-3.5.drv" [color = magenta];
|
||||
"/gnu/store/aymf6jlxxpwgr71rkiz24m646nqsyii6-glibc-intermediate-2.24.drv" -> "/gnu/store/m4900ip34w4rcgn5620iqdi1wv198d9s-findutils-boot0-4.6.0.drv" [color = magenta];
|
||||
"/gnu/store/aymf6jlxxpwgr71rkiz24m646nqsyii6-glibc-intermediate-2.24.drv" -> "/gnu/store/nwzyr3xskw0ms8cndffsfvhvm5xz96pc-file-boot0-5.28.drv" [color = magenta];
|
||||
"/gnu/store/aymf6jlxxpwgr71rkiz24m646nqsyii6-glibc-intermediate-2.24.drv" -> "/gnu/store/wda0p45jlbzg6w9j8zxw2sd11n2a4pbv-glibc-bootstrap-0.drv" [color = magenta];
|
||||
"/gnu/store/aymf6jlxxpwgr71rkiz24m646nqsyii6-glibc-intermediate-2.24.drv" -> "/gnu/store/jxlg2pb4bhxjld9kimc0vgc1pvgifzag-gcc-bootstrap-0.drv" [color = magenta];
|
||||
"/gnu/store/aymf6jlxxpwgr71rkiz24m646nqsyii6-glibc-intermediate-2.24.drv" -> "/gnu/store/pmvh852v0x1zbl4r37pcpdqnq6m3bwfk-bootstrap-binaries-0.drv" [color = magenta];
|
||||
"/gnu/store/aymf6jlxxpwgr71rkiz24m646nqsyii6-glibc-intermediate-2.24.drv" -> "/gnu/store/pmvh852v0x1zbl4r37pcpdqnq6m3bwfk-bootstrap-binaries-0.drv" [color = magenta];
|
||||
"/gnu/store/aymf6jlxxpwgr71rkiz24m646nqsyii6-glibc-intermediate-2.24.drv" -> "/gnu/store/jxlg2pb4bhxjld9kimc0vgc1pvgifzag-gcc-bootstrap-0.drv" [color = magenta];
|
||||
"/gnu/store/aymf6jlxxpwgr71rkiz24m646nqsyii6-glibc-intermediate-2.24.drv" -> "/gnu/store/pmvh852v0x1zbl4r37pcpdqnq6m3bwfk-bootstrap-binaries-0.drv" [color = magenta];
|
||||
"/gnu/store/aymf6jlxxpwgr71rkiz24m646nqsyii6-glibc-intermediate-2.24.drv" -> "/gnu/store/5syba2bxhh8z79jhq83fzy8fxcx5xb4s-linux-libre-headers-4.4.18.drv" [color = magenta];
|
||||
"/gnu/store/wx8ifbb7x22cl4998fyldsr24fcv18j3-texinfo-6.3.drv" [label = "texinfo-6.3", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/wx8ifbb7x22cl4998fyldsr24fcv18j3-texinfo-6.3.drv" -> "/gnu/store/1jpld53g41rzv2bmjp6v9mckmyw75vs3-make-boot0-4.2.1.drv" [color = cyan3];
|
||||
"/gnu/store/wx8ifbb7x22cl4998fyldsr24fcv18j3-texinfo-6.3.drv" -> "/gnu/store/zpphawi07xidhfs2dja3w7hmnfp99j02-diffutils-boot0-3.5.drv" [color = cyan3];
|
||||
"/gnu/store/wx8ifbb7x22cl4998fyldsr24fcv18j3-texinfo-6.3.drv" -> "/gnu/store/m4900ip34w4rcgn5620iqdi1wv198d9s-findutils-boot0-4.6.0.drv" [color = cyan3];
|
||||
"/gnu/store/wx8ifbb7x22cl4998fyldsr24fcv18j3-texinfo-6.3.drv" -> "/gnu/store/nwzyr3xskw0ms8cndffsfvhvm5xz96pc-file-boot0-5.28.drv" [color = cyan3];
|
||||
"/gnu/store/wx8ifbb7x22cl4998fyldsr24fcv18j3-texinfo-6.3.drv" -> "/gnu/store/wda0p45jlbzg6w9j8zxw2sd11n2a4pbv-glibc-bootstrap-0.drv" [color = cyan3];
|
||||
"/gnu/store/wx8ifbb7x22cl4998fyldsr24fcv18j3-texinfo-6.3.drv" -> "/gnu/store/jxlg2pb4bhxjld9kimc0vgc1pvgifzag-gcc-bootstrap-0.drv" [color = cyan3];
|
||||
"/gnu/store/wx8ifbb7x22cl4998fyldsr24fcv18j3-texinfo-6.3.drv" -> "/gnu/store/wv8sf8h4n9s5cdya223iy2wp3alr92x8-binutils-bootstrap-0.drv" [color = cyan3];
|
||||
"/gnu/store/wx8ifbb7x22cl4998fyldsr24fcv18j3-texinfo-6.3.drv" -> "/gnu/store/pmvh852v0x1zbl4r37pcpdqnq6m3bwfk-bootstrap-binaries-0.drv" [color = cyan3];
|
||||
"/gnu/store/wx8ifbb7x22cl4998fyldsr24fcv18j3-texinfo-6.3.drv" -> "/gnu/store/pmvh852v0x1zbl4r37pcpdqnq6m3bwfk-bootstrap-binaries-0.drv" [color = cyan3];
|
||||
"/gnu/store/wx8ifbb7x22cl4998fyldsr24fcv18j3-texinfo-6.3.drv" -> "/gnu/store/ccj3as3258l70lmphi48hs7n017wv75s-perl-boot0-5.24.0.drv" [color = cyan3];
|
||||
"/gnu/store/1jpld53g41rzv2bmjp6v9mckmyw75vs3-make-boot0-4.2.1.drv" [label = "make-boot0-4.2.1", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/1jpld53g41rzv2bmjp6v9mckmyw75vs3-make-boot0-4.2.1.drv" -> "/gnu/store/wda0p45jlbzg6w9j8zxw2sd11n2a4pbv-glibc-bootstrap-0.drv" [color = dimgrey];
|
||||
"/gnu/store/1jpld53g41rzv2bmjp6v9mckmyw75vs3-make-boot0-4.2.1.drv" -> "/gnu/store/jxlg2pb4bhxjld9kimc0vgc1pvgifzag-gcc-bootstrap-0.drv" [color = dimgrey];
|
||||
"/gnu/store/1jpld53g41rzv2bmjp6v9mckmyw75vs3-make-boot0-4.2.1.drv" -> "/gnu/store/wv8sf8h4n9s5cdya223iy2wp3alr92x8-binutils-bootstrap-0.drv" [color = dimgrey];
|
||||
"/gnu/store/1jpld53g41rzv2bmjp6v9mckmyw75vs3-make-boot0-4.2.1.drv" -> "/gnu/store/pmvh852v0x1zbl4r37pcpdqnq6m3bwfk-bootstrap-binaries-0.drv" [color = dimgrey];
|
||||
"/gnu/store/1jpld53g41rzv2bmjp6v9mckmyw75vs3-make-boot0-4.2.1.drv" -> "/gnu/store/pmvh852v0x1zbl4r37pcpdqnq6m3bwfk-bootstrap-binaries-0.drv" [color = dimgrey];
|
||||
"/gnu/store/wda0p45jlbzg6w9j8zxw2sd11n2a4pbv-glibc-bootstrap-0.drv" [label = "glibc-bootstrap-0", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/jxlg2pb4bhxjld9kimc0vgc1pvgifzag-gcc-bootstrap-0.drv" [label = "gcc-bootstrap-0", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/jxlg2pb4bhxjld9kimc0vgc1pvgifzag-gcc-bootstrap-0.drv" -> "/gnu/store/wda0p45jlbzg6w9j8zxw2sd11n2a4pbv-glibc-bootstrap-0.drv" [color = darkseagreen];
|
||||
"/gnu/store/wv8sf8h4n9s5cdya223iy2wp3alr92x8-binutils-bootstrap-0.drv" [label = "binutils-bootstrap-0", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/pmvh852v0x1zbl4r37pcpdqnq6m3bwfk-bootstrap-binaries-0.drv" [label = "bootstrap-binaries-0", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/zpphawi07xidhfs2dja3w7hmnfp99j02-diffutils-boot0-3.5.drv" [label = "diffutils-boot0-3.5", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/zpphawi07xidhfs2dja3w7hmnfp99j02-diffutils-boot0-3.5.drv" -> "/gnu/store/1jpld53g41rzv2bmjp6v9mckmyw75vs3-make-boot0-4.2.1.drv" [color = blue];
|
||||
"/gnu/store/zpphawi07xidhfs2dja3w7hmnfp99j02-diffutils-boot0-3.5.drv" -> "/gnu/store/wda0p45jlbzg6w9j8zxw2sd11n2a4pbv-glibc-bootstrap-0.drv" [color = blue];
|
||||
"/gnu/store/zpphawi07xidhfs2dja3w7hmnfp99j02-diffutils-boot0-3.5.drv" -> "/gnu/store/jxlg2pb4bhxjld9kimc0vgc1pvgifzag-gcc-bootstrap-0.drv" [color = blue];
|
||||
"/gnu/store/zpphawi07xidhfs2dja3w7hmnfp99j02-diffutils-boot0-3.5.drv" -> "/gnu/store/wv8sf8h4n9s5cdya223iy2wp3alr92x8-binutils-bootstrap-0.drv" [color = blue];
|
||||
"/gnu/store/zpphawi07xidhfs2dja3w7hmnfp99j02-diffutils-boot0-3.5.drv" -> "/gnu/store/pmvh852v0x1zbl4r37pcpdqnq6m3bwfk-bootstrap-binaries-0.drv" [color = blue];
|
||||
"/gnu/store/zpphawi07xidhfs2dja3w7hmnfp99j02-diffutils-boot0-3.5.drv" -> "/gnu/store/pmvh852v0x1zbl4r37pcpdqnq6m3bwfk-bootstrap-binaries-0.drv" [color = blue];
|
||||
"/gnu/store/m4900ip34w4rcgn5620iqdi1wv198d9s-findutils-boot0-4.6.0.drv" [label = "findutils-boot0-4.6.0", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/m4900ip34w4rcgn5620iqdi1wv198d9s-findutils-boot0-4.6.0.drv" -> "/gnu/store/1jpld53g41rzv2bmjp6v9mckmyw75vs3-make-boot0-4.2.1.drv" [color = blue];
|
||||
"/gnu/store/m4900ip34w4rcgn5620iqdi1wv198d9s-findutils-boot0-4.6.0.drv" -> "/gnu/store/zpphawi07xidhfs2dja3w7hmnfp99j02-diffutils-boot0-3.5.drv" [color = blue];
|
||||
"/gnu/store/m4900ip34w4rcgn5620iqdi1wv198d9s-findutils-boot0-4.6.0.drv" -> "/gnu/store/wda0p45jlbzg6w9j8zxw2sd11n2a4pbv-glibc-bootstrap-0.drv" [color = blue];
|
||||
"/gnu/store/m4900ip34w4rcgn5620iqdi1wv198d9s-findutils-boot0-4.6.0.drv" -> "/gnu/store/jxlg2pb4bhxjld9kimc0vgc1pvgifzag-gcc-bootstrap-0.drv" [color = blue];
|
||||
"/gnu/store/m4900ip34w4rcgn5620iqdi1wv198d9s-findutils-boot0-4.6.0.drv" -> "/gnu/store/wv8sf8h4n9s5cdya223iy2wp3alr92x8-binutils-bootstrap-0.drv" [color = blue];
|
||||
"/gnu/store/m4900ip34w4rcgn5620iqdi1wv198d9s-findutils-boot0-4.6.0.drv" -> "/gnu/store/pmvh852v0x1zbl4r37pcpdqnq6m3bwfk-bootstrap-binaries-0.drv" [color = blue];
|
||||
"/gnu/store/m4900ip34w4rcgn5620iqdi1wv198d9s-findutils-boot0-4.6.0.drv" -> "/gnu/store/pmvh852v0x1zbl4r37pcpdqnq6m3bwfk-bootstrap-binaries-0.drv" [color = blue];
|
||||
"/gnu/store/nwzyr3xskw0ms8cndffsfvhvm5xz96pc-file-boot0-5.28.drv" [label = "file-boot0-5.28", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/nwzyr3xskw0ms8cndffsfvhvm5xz96pc-file-boot0-5.28.drv" -> "/gnu/store/1jpld53g41rzv2bmjp6v9mckmyw75vs3-make-boot0-4.2.1.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/nwzyr3xskw0ms8cndffsfvhvm5xz96pc-file-boot0-5.28.drv" -> "/gnu/store/wda0p45jlbzg6w9j8zxw2sd11n2a4pbv-glibc-bootstrap-0.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/nwzyr3xskw0ms8cndffsfvhvm5xz96pc-file-boot0-5.28.drv" -> "/gnu/store/jxlg2pb4bhxjld9kimc0vgc1pvgifzag-gcc-bootstrap-0.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/nwzyr3xskw0ms8cndffsfvhvm5xz96pc-file-boot0-5.28.drv" -> "/gnu/store/wv8sf8h4n9s5cdya223iy2wp3alr92x8-binutils-bootstrap-0.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/nwzyr3xskw0ms8cndffsfvhvm5xz96pc-file-boot0-5.28.drv" -> "/gnu/store/pmvh852v0x1zbl4r37pcpdqnq6m3bwfk-bootstrap-binaries-0.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/nwzyr3xskw0ms8cndffsfvhvm5xz96pc-file-boot0-5.28.drv" -> "/gnu/store/pmvh852v0x1zbl4r37pcpdqnq6m3bwfk-bootstrap-binaries-0.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/ccj3as3258l70lmphi48hs7n017wv75s-perl-boot0-5.24.0.drv" [label = "perl-boot0-5.24.0", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/ccj3as3258l70lmphi48hs7n017wv75s-perl-boot0-5.24.0.drv" -> "/gnu/store/1jpld53g41rzv2bmjp6v9mckmyw75vs3-make-boot0-4.2.1.drv" [color = peachpuff4];
|
||||
"/gnu/store/ccj3as3258l70lmphi48hs7n017wv75s-perl-boot0-5.24.0.drv" -> "/gnu/store/zpphawi07xidhfs2dja3w7hmnfp99j02-diffutils-boot0-3.5.drv" [color = peachpuff4];
|
||||
"/gnu/store/ccj3as3258l70lmphi48hs7n017wv75s-perl-boot0-5.24.0.drv" -> "/gnu/store/m4900ip34w4rcgn5620iqdi1wv198d9s-findutils-boot0-4.6.0.drv" [color = peachpuff4];
|
||||
"/gnu/store/ccj3as3258l70lmphi48hs7n017wv75s-perl-boot0-5.24.0.drv" -> "/gnu/store/nwzyr3xskw0ms8cndffsfvhvm5xz96pc-file-boot0-5.28.drv" [color = peachpuff4];
|
||||
"/gnu/store/ccj3as3258l70lmphi48hs7n017wv75s-perl-boot0-5.24.0.drv" -> "/gnu/store/wda0p45jlbzg6w9j8zxw2sd11n2a4pbv-glibc-bootstrap-0.drv" [color = peachpuff4];
|
||||
"/gnu/store/ccj3as3258l70lmphi48hs7n017wv75s-perl-boot0-5.24.0.drv" -> "/gnu/store/jxlg2pb4bhxjld9kimc0vgc1pvgifzag-gcc-bootstrap-0.drv" [color = peachpuff4];
|
||||
"/gnu/store/ccj3as3258l70lmphi48hs7n017wv75s-perl-boot0-5.24.0.drv" -> "/gnu/store/wv8sf8h4n9s5cdya223iy2wp3alr92x8-binutils-bootstrap-0.drv" [color = peachpuff4];
|
||||
"/gnu/store/ccj3as3258l70lmphi48hs7n017wv75s-perl-boot0-5.24.0.drv" -> "/gnu/store/pmvh852v0x1zbl4r37pcpdqnq6m3bwfk-bootstrap-binaries-0.drv" [color = peachpuff4];
|
||||
"/gnu/store/ccj3as3258l70lmphi48hs7n017wv75s-perl-boot0-5.24.0.drv" -> "/gnu/store/pmvh852v0x1zbl4r37pcpdqnq6m3bwfk-bootstrap-binaries-0.drv" [color = peachpuff4];
|
||||
"/gnu/store/w9adgzgdqkwz0w13zxf2fn363v9wcllc-gcc-cross-boot0-4.9.4.drv" [label = "gcc-cross-boot0-4.9.4", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/w9adgzgdqkwz0w13zxf2fn363v9wcllc-gcc-cross-boot0-4.9.4.drv" -> "/gnu/store/v1v7jp438hc5rpgriwpjp04x049vh0g4-binutils-cross-boot0-2.27.drv" [color = darkseagreen];
|
||||
"/gnu/store/w9adgzgdqkwz0w13zxf2fn363v9wcllc-gcc-cross-boot0-4.9.4.drv" -> "/gnu/store/wda0p45jlbzg6w9j8zxw2sd11n2a4pbv-glibc-bootstrap-0.drv" [color = darkseagreen];
|
||||
"/gnu/store/w9adgzgdqkwz0w13zxf2fn363v9wcllc-gcc-cross-boot0-4.9.4.drv" -> "/gnu/store/1jpld53g41rzv2bmjp6v9mckmyw75vs3-make-boot0-4.2.1.drv" [color = darkseagreen];
|
||||
"/gnu/store/w9adgzgdqkwz0w13zxf2fn363v9wcllc-gcc-cross-boot0-4.9.4.drv" -> "/gnu/store/zpphawi07xidhfs2dja3w7hmnfp99j02-diffutils-boot0-3.5.drv" [color = darkseagreen];
|
||||
"/gnu/store/w9adgzgdqkwz0w13zxf2fn363v9wcllc-gcc-cross-boot0-4.9.4.drv" -> "/gnu/store/m4900ip34w4rcgn5620iqdi1wv198d9s-findutils-boot0-4.6.0.drv" [color = darkseagreen];
|
||||
"/gnu/store/w9adgzgdqkwz0w13zxf2fn363v9wcllc-gcc-cross-boot0-4.9.4.drv" -> "/gnu/store/nwzyr3xskw0ms8cndffsfvhvm5xz96pc-file-boot0-5.28.drv" [color = darkseagreen];
|
||||
"/gnu/store/w9adgzgdqkwz0w13zxf2fn363v9wcllc-gcc-cross-boot0-4.9.4.drv" -> "/gnu/store/jxlg2pb4bhxjld9kimc0vgc1pvgifzag-gcc-bootstrap-0.drv" [color = darkseagreen];
|
||||
"/gnu/store/w9adgzgdqkwz0w13zxf2fn363v9wcllc-gcc-cross-boot0-4.9.4.drv" -> "/gnu/store/wv8sf8h4n9s5cdya223iy2wp3alr92x8-binutils-bootstrap-0.drv" [color = darkseagreen];
|
||||
"/gnu/store/w9adgzgdqkwz0w13zxf2fn363v9wcllc-gcc-cross-boot0-4.9.4.drv" -> "/gnu/store/pmvh852v0x1zbl4r37pcpdqnq6m3bwfk-bootstrap-binaries-0.drv" [color = darkseagreen];
|
||||
"/gnu/store/w9adgzgdqkwz0w13zxf2fn363v9wcllc-gcc-cross-boot0-4.9.4.drv" -> "/gnu/store/pmvh852v0x1zbl4r37pcpdqnq6m3bwfk-bootstrap-binaries-0.drv" [color = darkseagreen];
|
||||
"/gnu/store/v1v7jp438hc5rpgriwpjp04x049vh0g4-binutils-cross-boot0-2.27.drv" [label = "binutils-cross-boot0-2.27", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/v1v7jp438hc5rpgriwpjp04x049vh0g4-binutils-cross-boot0-2.27.drv" -> "/gnu/store/1jpld53g41rzv2bmjp6v9mckmyw75vs3-make-boot0-4.2.1.drv" [color = dimgrey];
|
||||
"/gnu/store/v1v7jp438hc5rpgriwpjp04x049vh0g4-binutils-cross-boot0-2.27.drv" -> "/gnu/store/zpphawi07xidhfs2dja3w7hmnfp99j02-diffutils-boot0-3.5.drv" [color = dimgrey];
|
||||
"/gnu/store/v1v7jp438hc5rpgriwpjp04x049vh0g4-binutils-cross-boot0-2.27.drv" -> "/gnu/store/m4900ip34w4rcgn5620iqdi1wv198d9s-findutils-boot0-4.6.0.drv" [color = dimgrey];
|
||||
"/gnu/store/v1v7jp438hc5rpgriwpjp04x049vh0g4-binutils-cross-boot0-2.27.drv" -> "/gnu/store/nwzyr3xskw0ms8cndffsfvhvm5xz96pc-file-boot0-5.28.drv" [color = dimgrey];
|
||||
"/gnu/store/v1v7jp438hc5rpgriwpjp04x049vh0g4-binutils-cross-boot0-2.27.drv" -> "/gnu/store/wda0p45jlbzg6w9j8zxw2sd11n2a4pbv-glibc-bootstrap-0.drv" [color = dimgrey];
|
||||
"/gnu/store/v1v7jp438hc5rpgriwpjp04x049vh0g4-binutils-cross-boot0-2.27.drv" -> "/gnu/store/jxlg2pb4bhxjld9kimc0vgc1pvgifzag-gcc-bootstrap-0.drv" [color = dimgrey];
|
||||
"/gnu/store/v1v7jp438hc5rpgriwpjp04x049vh0g4-binutils-cross-boot0-2.27.drv" -> "/gnu/store/wv8sf8h4n9s5cdya223iy2wp3alr92x8-binutils-bootstrap-0.drv" [color = dimgrey];
|
||||
"/gnu/store/v1v7jp438hc5rpgriwpjp04x049vh0g4-binutils-cross-boot0-2.27.drv" -> "/gnu/store/pmvh852v0x1zbl4r37pcpdqnq6m3bwfk-bootstrap-binaries-0.drv" [color = dimgrey];
|
||||
"/gnu/store/v1v7jp438hc5rpgriwpjp04x049vh0g4-binutils-cross-boot0-2.27.drv" -> "/gnu/store/pmvh852v0x1zbl4r37pcpdqnq6m3bwfk-bootstrap-binaries-0.drv" [color = dimgrey];
|
||||
"/gnu/store/72snmrnjphwjxffknjhzm3xg38wd08al-ld-wrapper-x86_64-guix-linux-gnu-0.drv" [label = "ld-wrapper-x86_64-guix-linux-gnu-0", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/72snmrnjphwjxffknjhzm3xg38wd08al-ld-wrapper-x86_64-guix-linux-gnu-0.drv" -> "/gnu/store/v1v7jp438hc5rpgriwpjp04x049vh0g4-binutils-cross-boot0-2.27.drv" [color = dimgrey];
|
||||
"/gnu/store/72snmrnjphwjxffknjhzm3xg38wd08al-ld-wrapper-x86_64-guix-linux-gnu-0.drv" -> "/gnu/store/af19ma2vm3qhvh3rw6cdivyp98s18bj3-guile-bootstrap-2.0.drv" [color = dimgrey];
|
||||
"/gnu/store/72snmrnjphwjxffknjhzm3xg38wd08al-ld-wrapper-x86_64-guix-linux-gnu-0.drv" -> "/gnu/store/pmvh852v0x1zbl4r37pcpdqnq6m3bwfk-bootstrap-binaries-0.drv" [color = dimgrey];
|
||||
"/gnu/store/af19ma2vm3qhvh3rw6cdivyp98s18bj3-guile-bootstrap-2.0.drv" [label = "guile-bootstrap-2.0", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/5syba2bxhh8z79jhq83fzy8fxcx5xb4s-linux-libre-headers-4.4.18.drv" [label = "linux-libre-headers-4.4.18", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/5syba2bxhh8z79jhq83fzy8fxcx5xb4s-linux-libre-headers-4.4.18.drv" -> "/gnu/store/ccj3as3258l70lmphi48hs7n017wv75s-perl-boot0-5.24.0.drv" [color = blue];
|
||||
"/gnu/store/5syba2bxhh8z79jhq83fzy8fxcx5xb4s-linux-libre-headers-4.4.18.drv" -> "/gnu/store/1jpld53g41rzv2bmjp6v9mckmyw75vs3-make-boot0-4.2.1.drv" [color = blue];
|
||||
"/gnu/store/5syba2bxhh8z79jhq83fzy8fxcx5xb4s-linux-libre-headers-4.4.18.drv" -> "/gnu/store/zpphawi07xidhfs2dja3w7hmnfp99j02-diffutils-boot0-3.5.drv" [color = blue];
|
||||
"/gnu/store/5syba2bxhh8z79jhq83fzy8fxcx5xb4s-linux-libre-headers-4.4.18.drv" -> "/gnu/store/m4900ip34w4rcgn5620iqdi1wv198d9s-findutils-boot0-4.6.0.drv" [color = blue];
|
||||
"/gnu/store/5syba2bxhh8z79jhq83fzy8fxcx5xb4s-linux-libre-headers-4.4.18.drv" -> "/gnu/store/nwzyr3xskw0ms8cndffsfvhvm5xz96pc-file-boot0-5.28.drv" [color = blue];
|
||||
"/gnu/store/5syba2bxhh8z79jhq83fzy8fxcx5xb4s-linux-libre-headers-4.4.18.drv" -> "/gnu/store/wda0p45jlbzg6w9j8zxw2sd11n2a4pbv-glibc-bootstrap-0.drv" [color = blue];
|
||||
"/gnu/store/5syba2bxhh8z79jhq83fzy8fxcx5xb4s-linux-libre-headers-4.4.18.drv" -> "/gnu/store/jxlg2pb4bhxjld9kimc0vgc1pvgifzag-gcc-bootstrap-0.drv" [color = blue];
|
||||
"/gnu/store/5syba2bxhh8z79jhq83fzy8fxcx5xb4s-linux-libre-headers-4.4.18.drv" -> "/gnu/store/wv8sf8h4n9s5cdya223iy2wp3alr92x8-binutils-bootstrap-0.drv" [color = blue];
|
||||
"/gnu/store/5syba2bxhh8z79jhq83fzy8fxcx5xb4s-linux-libre-headers-4.4.18.drv" -> "/gnu/store/pmvh852v0x1zbl4r37pcpdqnq6m3bwfk-bootstrap-binaries-0.drv" [color = blue];
|
||||
"/gnu/store/5syba2bxhh8z79jhq83fzy8fxcx5xb4s-linux-libre-headers-4.4.18.drv" -> "/gnu/store/pmvh852v0x1zbl4r37pcpdqnq6m3bwfk-bootstrap-binaries-0.drv" [color = blue];
|
||||
|
||||
}
|
||||
+212
-212
@@ -1,215 +1,215 @@
|
||||
digraph "Guix bag-emerged" {
|
||||
"/gnu/store/yv2r96w2dvbb0sjrf9f2imybpnyd616b-coreutils-8.25.drv" [label = "coreutils-8.25", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/yv2r96w2dvbb0sjrf9f2imybpnyd616b-coreutils-8.25.drv" -> "/gnu/store/jxcx1jcvzxb17dc69sfwb352vgwyr108-perl-5.24.0.drv" [color = cyan3];
|
||||
"/gnu/store/yv2r96w2dvbb0sjrf9f2imybpnyd616b-coreutils-8.25.drv" -> "/gnu/store/7ijl8lybdx95kndajavdrpz05jdiwy9g-tar-1.29.drv" [color = cyan3];
|
||||
"/gnu/store/yv2r96w2dvbb0sjrf9f2imybpnyd616b-coreutils-8.25.drv" -> "/gnu/store/0ykf3p023pzfcg2bw8ahjc7cvmc12zjq-gzip-1.8.drv" [color = cyan3];
|
||||
"/gnu/store/yv2r96w2dvbb0sjrf9f2imybpnyd616b-coreutils-8.25.drv" -> "/gnu/store/xx3hiqhqn0d94zz7b46hgggwsz3wjiiw-bzip2-1.0.6.drv" [color = cyan3];
|
||||
"/gnu/store/yv2r96w2dvbb0sjrf9f2imybpnyd616b-coreutils-8.25.drv" -> "/gnu/store/kz8rzasivw4aflsv4rll3m539xybf226-xz-5.2.2.drv" [color = cyan3];
|
||||
"/gnu/store/yv2r96w2dvbb0sjrf9f2imybpnyd616b-coreutils-8.25.drv" -> "/gnu/store/3pwrlsd23k2h104akxfj3cxhqcp973g9-file-5.28.drv" [color = cyan3];
|
||||
"/gnu/store/yv2r96w2dvbb0sjrf9f2imybpnyd616b-coreutils-8.25.drv" -> "/gnu/store/f1ww5vh5abnvr8b24llipm5dl89s5lq2-diffutils-3.5.drv" [color = cyan3];
|
||||
"/gnu/store/yv2r96w2dvbb0sjrf9f2imybpnyd616b-coreutils-8.25.drv" -> "/gnu/store/0cbgdhhyh7hsgwq1x54n9vnq99rfjch9-patch-2.7.5.drv" [color = cyan3];
|
||||
"/gnu/store/yv2r96w2dvbb0sjrf9f2imybpnyd616b-coreutils-8.25.drv" -> "/gnu/store/8xjnm44dfwwxp90hxq6zhb6qvia7rb3l-sed-4.2.2.drv" [color = cyan3];
|
||||
"/gnu/store/yv2r96w2dvbb0sjrf9f2imybpnyd616b-coreutils-8.25.drv" -> "/gnu/store/54wjl6dp6rp47r67f4nyfqyv8nh456yc-findutils-4.6.0.drv" [color = cyan3];
|
||||
"/gnu/store/yv2r96w2dvbb0sjrf9f2imybpnyd616b-coreutils-8.25.drv" -> "/gnu/store/k951w49yw74ikg19l4mmlwfrq9w7a7zd-gawk-4.1.4.drv" [color = cyan3];
|
||||
"/gnu/store/yv2r96w2dvbb0sjrf9f2imybpnyd616b-coreutils-8.25.drv" -> "/gnu/store/n48xdjkvhlhj5mgdzy59n0dpb9vn0v78-grep-2.25.drv" [color = cyan3];
|
||||
"/gnu/store/yv2r96w2dvbb0sjrf9f2imybpnyd616b-coreutils-8.25.drv" -> "/gnu/store/i52csyja3036ns0zj6z85lkgz3wfyym7-coreutils-8.25.drv" [color = cyan3];
|
||||
"/gnu/store/yv2r96w2dvbb0sjrf9f2imybpnyd616b-coreutils-8.25.drv" -> "/gnu/store/nv4mnbz3mpd4gv80djk7762wyvxpccqk-make-4.2.1.drv" [color = cyan3];
|
||||
"/gnu/store/yv2r96w2dvbb0sjrf9f2imybpnyd616b-coreutils-8.25.drv" -> "/gnu/store/2c60vlcvpj5dvmgklajkp7cpynhcqixr-bash-4.4.0.drv" [color = cyan3];
|
||||
"/gnu/store/yv2r96w2dvbb0sjrf9f2imybpnyd616b-coreutils-8.25.drv" -> "/gnu/store/zhc5c4s0xvzizpgpq2za6x84vxv57iy6-ld-wrapper-0.drv" [color = cyan3];
|
||||
"/gnu/store/yv2r96w2dvbb0sjrf9f2imybpnyd616b-coreutils-8.25.drv" -> "/gnu/store/9k1js0kalh4s6q4hf0rgg2n0zdyrwi69-binutils-2.27.drv" [color = cyan3];
|
||||
"/gnu/store/yv2r96w2dvbb0sjrf9f2imybpnyd616b-coreutils-8.25.drv" -> "/gnu/store/hv3dl3my12mq0gkwvckmnqccnckn39l0-gcc-4.9.4.drv" [color = cyan3];
|
||||
"/gnu/store/yv2r96w2dvbb0sjrf9f2imybpnyd616b-coreutils-8.25.drv" -> "/gnu/store/qbfynm50snyn31w2c3paiw2n6wvzksg8-glibc-2.24.drv" [color = cyan3];
|
||||
"/gnu/store/yv2r96w2dvbb0sjrf9f2imybpnyd616b-coreutils-8.25.drv" -> "/gnu/store/ir0lq2x7h64g2z5mlqvnlysjk2bc9xka-glibc-utf8-locales-2.24.drv" [color = cyan3];
|
||||
"/gnu/store/yv2r96w2dvbb0sjrf9f2imybpnyd616b-coreutils-8.25.drv" -> "/gnu/store/ywmblv73pqa8lqqz368g46ysz65pnm0v-acl-2.2.52.drv" [color = cyan3];
|
||||
"/gnu/store/yv2r96w2dvbb0sjrf9f2imybpnyd616b-coreutils-8.25.drv" -> "/gnu/store/7gqg2kmrm1bjgphnd70ps5c11gqml571-gmp-6.1.1.drv" [color = cyan3];
|
||||
"/gnu/store/yv2r96w2dvbb0sjrf9f2imybpnyd616b-coreutils-8.25.drv" -> "/gnu/store/ijv3y5l1fbbzwb77lc867r1qbsf147i8-libcap-2.24.drv" [color = cyan3];
|
||||
"/gnu/store/jxcx1jcvzxb17dc69sfwb352vgwyr108-perl-5.24.0.drv" [label = "perl-5.24.0", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/jxcx1jcvzxb17dc69sfwb352vgwyr108-perl-5.24.0.drv" -> "/gnu/store/7ijl8lybdx95kndajavdrpz05jdiwy9g-tar-1.29.drv" [color = blue];
|
||||
"/gnu/store/jxcx1jcvzxb17dc69sfwb352vgwyr108-perl-5.24.0.drv" -> "/gnu/store/0ykf3p023pzfcg2bw8ahjc7cvmc12zjq-gzip-1.8.drv" [color = blue];
|
||||
"/gnu/store/jxcx1jcvzxb17dc69sfwb352vgwyr108-perl-5.24.0.drv" -> "/gnu/store/xx3hiqhqn0d94zz7b46hgggwsz3wjiiw-bzip2-1.0.6.drv" [color = blue];
|
||||
"/gnu/store/jxcx1jcvzxb17dc69sfwb352vgwyr108-perl-5.24.0.drv" -> "/gnu/store/kz8rzasivw4aflsv4rll3m539xybf226-xz-5.2.2.drv" [color = blue];
|
||||
"/gnu/store/jxcx1jcvzxb17dc69sfwb352vgwyr108-perl-5.24.0.drv" -> "/gnu/store/3pwrlsd23k2h104akxfj3cxhqcp973g9-file-5.28.drv" [color = blue];
|
||||
"/gnu/store/jxcx1jcvzxb17dc69sfwb352vgwyr108-perl-5.24.0.drv" -> "/gnu/store/f1ww5vh5abnvr8b24llipm5dl89s5lq2-diffutils-3.5.drv" [color = blue];
|
||||
"/gnu/store/jxcx1jcvzxb17dc69sfwb352vgwyr108-perl-5.24.0.drv" -> "/gnu/store/0cbgdhhyh7hsgwq1x54n9vnq99rfjch9-patch-2.7.5.drv" [color = blue];
|
||||
"/gnu/store/jxcx1jcvzxb17dc69sfwb352vgwyr108-perl-5.24.0.drv" -> "/gnu/store/8xjnm44dfwwxp90hxq6zhb6qvia7rb3l-sed-4.2.2.drv" [color = blue];
|
||||
"/gnu/store/jxcx1jcvzxb17dc69sfwb352vgwyr108-perl-5.24.0.drv" -> "/gnu/store/54wjl6dp6rp47r67f4nyfqyv8nh456yc-findutils-4.6.0.drv" [color = blue];
|
||||
"/gnu/store/jxcx1jcvzxb17dc69sfwb352vgwyr108-perl-5.24.0.drv" -> "/gnu/store/k951w49yw74ikg19l4mmlwfrq9w7a7zd-gawk-4.1.4.drv" [color = blue];
|
||||
"/gnu/store/jxcx1jcvzxb17dc69sfwb352vgwyr108-perl-5.24.0.drv" -> "/gnu/store/n48xdjkvhlhj5mgdzy59n0dpb9vn0v78-grep-2.25.drv" [color = blue];
|
||||
"/gnu/store/jxcx1jcvzxb17dc69sfwb352vgwyr108-perl-5.24.0.drv" -> "/gnu/store/i52csyja3036ns0zj6z85lkgz3wfyym7-coreutils-8.25.drv" [color = blue];
|
||||
"/gnu/store/jxcx1jcvzxb17dc69sfwb352vgwyr108-perl-5.24.0.drv" -> "/gnu/store/nv4mnbz3mpd4gv80djk7762wyvxpccqk-make-4.2.1.drv" [color = blue];
|
||||
"/gnu/store/jxcx1jcvzxb17dc69sfwb352vgwyr108-perl-5.24.0.drv" -> "/gnu/store/2c60vlcvpj5dvmgklajkp7cpynhcqixr-bash-4.4.0.drv" [color = blue];
|
||||
"/gnu/store/jxcx1jcvzxb17dc69sfwb352vgwyr108-perl-5.24.0.drv" -> "/gnu/store/zhc5c4s0xvzizpgpq2za6x84vxv57iy6-ld-wrapper-0.drv" [color = blue];
|
||||
"/gnu/store/jxcx1jcvzxb17dc69sfwb352vgwyr108-perl-5.24.0.drv" -> "/gnu/store/9k1js0kalh4s6q4hf0rgg2n0zdyrwi69-binutils-2.27.drv" [color = blue];
|
||||
"/gnu/store/jxcx1jcvzxb17dc69sfwb352vgwyr108-perl-5.24.0.drv" -> "/gnu/store/hv3dl3my12mq0gkwvckmnqccnckn39l0-gcc-4.9.4.drv" [color = blue];
|
||||
"/gnu/store/jxcx1jcvzxb17dc69sfwb352vgwyr108-perl-5.24.0.drv" -> "/gnu/store/qbfynm50snyn31w2c3paiw2n6wvzksg8-glibc-2.24.drv" [color = blue];
|
||||
"/gnu/store/jxcx1jcvzxb17dc69sfwb352vgwyr108-perl-5.24.0.drv" -> "/gnu/store/ir0lq2x7h64g2z5mlqvnlysjk2bc9xka-glibc-utf8-locales-2.24.drv" [color = blue];
|
||||
"/gnu/store/7ijl8lybdx95kndajavdrpz05jdiwy9g-tar-1.29.drv" [label = "tar-1.29", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/0ykf3p023pzfcg2bw8ahjc7cvmc12zjq-gzip-1.8.drv" [label = "gzip-1.8", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/xx3hiqhqn0d94zz7b46hgggwsz3wjiiw-bzip2-1.0.6.drv" [label = "bzip2-1.0.6", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/kz8rzasivw4aflsv4rll3m539xybf226-xz-5.2.2.drv" [label = "xz-5.2.2", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/3pwrlsd23k2h104akxfj3cxhqcp973g9-file-5.28.drv" [label = "file-5.28", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/f1ww5vh5abnvr8b24llipm5dl89s5lq2-diffutils-3.5.drv" [label = "diffutils-3.5", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/0cbgdhhyh7hsgwq1x54n9vnq99rfjch9-patch-2.7.5.drv" [label = "patch-2.7.5", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/8xjnm44dfwwxp90hxq6zhb6qvia7rb3l-sed-4.2.2.drv" [label = "sed-4.2.2", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/54wjl6dp6rp47r67f4nyfqyv8nh456yc-findutils-4.6.0.drv" [label = "findutils-4.6.0", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/k951w49yw74ikg19l4mmlwfrq9w7a7zd-gawk-4.1.4.drv" [label = "gawk-4.1.4", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/n48xdjkvhlhj5mgdzy59n0dpb9vn0v78-grep-2.25.drv" [label = "grep-2.25", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/i52csyja3036ns0zj6z85lkgz3wfyym7-coreutils-8.25.drv" [label = "coreutils-8.25", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/nv4mnbz3mpd4gv80djk7762wyvxpccqk-make-4.2.1.drv" [label = "make-4.2.1", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/2c60vlcvpj5dvmgklajkp7cpynhcqixr-bash-4.4.0.drv" [label = "bash-4.4.0", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/zhc5c4s0xvzizpgpq2za6x84vxv57iy6-ld-wrapper-0.drv" [label = "ld-wrapper-0", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/9k1js0kalh4s6q4hf0rgg2n0zdyrwi69-binutils-2.27.drv" [label = "binutils-2.27", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/hv3dl3my12mq0gkwvckmnqccnckn39l0-gcc-4.9.4.drv" [label = "gcc-4.9.4", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/qbfynm50snyn31w2c3paiw2n6wvzksg8-glibc-2.24.drv" [label = "glibc-2.24", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/ir0lq2x7h64g2z5mlqvnlysjk2bc9xka-glibc-utf8-locales-2.24.drv" [label = "glibc-utf8-locales-2.24", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/ywmblv73pqa8lqqz368g46ysz65pnm0v-acl-2.2.52.drv" [label = "acl-2.2.52", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/ywmblv73pqa8lqqz368g46ysz65pnm0v-acl-2.2.52.drv" -> "/gnu/store/nw68wjvbw505klgpsavq7dk195wg8ffj-gettext-minimal-0.19.8.1.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/ywmblv73pqa8lqqz368g46ysz65pnm0v-acl-2.2.52.drv" -> "/gnu/store/jxcx1jcvzxb17dc69sfwb352vgwyr108-perl-5.24.0.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/ywmblv73pqa8lqqz368g46ysz65pnm0v-acl-2.2.52.drv" -> "/gnu/store/7ijl8lybdx95kndajavdrpz05jdiwy9g-tar-1.29.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/ywmblv73pqa8lqqz368g46ysz65pnm0v-acl-2.2.52.drv" -> "/gnu/store/0ykf3p023pzfcg2bw8ahjc7cvmc12zjq-gzip-1.8.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/ywmblv73pqa8lqqz368g46ysz65pnm0v-acl-2.2.52.drv" -> "/gnu/store/xx3hiqhqn0d94zz7b46hgggwsz3wjiiw-bzip2-1.0.6.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/ywmblv73pqa8lqqz368g46ysz65pnm0v-acl-2.2.52.drv" -> "/gnu/store/kz8rzasivw4aflsv4rll3m539xybf226-xz-5.2.2.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/ywmblv73pqa8lqqz368g46ysz65pnm0v-acl-2.2.52.drv" -> "/gnu/store/3pwrlsd23k2h104akxfj3cxhqcp973g9-file-5.28.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/ywmblv73pqa8lqqz368g46ysz65pnm0v-acl-2.2.52.drv" -> "/gnu/store/f1ww5vh5abnvr8b24llipm5dl89s5lq2-diffutils-3.5.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/ywmblv73pqa8lqqz368g46ysz65pnm0v-acl-2.2.52.drv" -> "/gnu/store/0cbgdhhyh7hsgwq1x54n9vnq99rfjch9-patch-2.7.5.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/ywmblv73pqa8lqqz368g46ysz65pnm0v-acl-2.2.52.drv" -> "/gnu/store/8xjnm44dfwwxp90hxq6zhb6qvia7rb3l-sed-4.2.2.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/ywmblv73pqa8lqqz368g46ysz65pnm0v-acl-2.2.52.drv" -> "/gnu/store/54wjl6dp6rp47r67f4nyfqyv8nh456yc-findutils-4.6.0.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/ywmblv73pqa8lqqz368g46ysz65pnm0v-acl-2.2.52.drv" -> "/gnu/store/k951w49yw74ikg19l4mmlwfrq9w7a7zd-gawk-4.1.4.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/ywmblv73pqa8lqqz368g46ysz65pnm0v-acl-2.2.52.drv" -> "/gnu/store/n48xdjkvhlhj5mgdzy59n0dpb9vn0v78-grep-2.25.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/ywmblv73pqa8lqqz368g46ysz65pnm0v-acl-2.2.52.drv" -> "/gnu/store/i52csyja3036ns0zj6z85lkgz3wfyym7-coreutils-8.25.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/ywmblv73pqa8lqqz368g46ysz65pnm0v-acl-2.2.52.drv" -> "/gnu/store/nv4mnbz3mpd4gv80djk7762wyvxpccqk-make-4.2.1.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/ywmblv73pqa8lqqz368g46ysz65pnm0v-acl-2.2.52.drv" -> "/gnu/store/2c60vlcvpj5dvmgklajkp7cpynhcqixr-bash-4.4.0.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/ywmblv73pqa8lqqz368g46ysz65pnm0v-acl-2.2.52.drv" -> "/gnu/store/zhc5c4s0xvzizpgpq2za6x84vxv57iy6-ld-wrapper-0.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/ywmblv73pqa8lqqz368g46ysz65pnm0v-acl-2.2.52.drv" -> "/gnu/store/9k1js0kalh4s6q4hf0rgg2n0zdyrwi69-binutils-2.27.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/ywmblv73pqa8lqqz368g46ysz65pnm0v-acl-2.2.52.drv" -> "/gnu/store/hv3dl3my12mq0gkwvckmnqccnckn39l0-gcc-4.9.4.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/ywmblv73pqa8lqqz368g46ysz65pnm0v-acl-2.2.52.drv" -> "/gnu/store/qbfynm50snyn31w2c3paiw2n6wvzksg8-glibc-2.24.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/ywmblv73pqa8lqqz368g46ysz65pnm0v-acl-2.2.52.drv" -> "/gnu/store/ir0lq2x7h64g2z5mlqvnlysjk2bc9xka-glibc-utf8-locales-2.24.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/ywmblv73pqa8lqqz368g46ysz65pnm0v-acl-2.2.52.drv" -> "/gnu/store/gplx9i7c01f2r6qvm6d5w60iam73zmin-attr-2.4.47.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/nw68wjvbw505klgpsavq7dk195wg8ffj-gettext-minimal-0.19.8.1.drv" [label = "gettext-minimal-0.19.8.1", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/nw68wjvbw505klgpsavq7dk195wg8ffj-gettext-minimal-0.19.8.1.drv" -> "/gnu/store/7ijl8lybdx95kndajavdrpz05jdiwy9g-tar-1.29.drv" [color = dimgrey];
|
||||
"/gnu/store/nw68wjvbw505klgpsavq7dk195wg8ffj-gettext-minimal-0.19.8.1.drv" -> "/gnu/store/0ykf3p023pzfcg2bw8ahjc7cvmc12zjq-gzip-1.8.drv" [color = dimgrey];
|
||||
"/gnu/store/nw68wjvbw505klgpsavq7dk195wg8ffj-gettext-minimal-0.19.8.1.drv" -> "/gnu/store/xx3hiqhqn0d94zz7b46hgggwsz3wjiiw-bzip2-1.0.6.drv" [color = dimgrey];
|
||||
"/gnu/store/nw68wjvbw505klgpsavq7dk195wg8ffj-gettext-minimal-0.19.8.1.drv" -> "/gnu/store/kz8rzasivw4aflsv4rll3m539xybf226-xz-5.2.2.drv" [color = dimgrey];
|
||||
"/gnu/store/nw68wjvbw505klgpsavq7dk195wg8ffj-gettext-minimal-0.19.8.1.drv" -> "/gnu/store/3pwrlsd23k2h104akxfj3cxhqcp973g9-file-5.28.drv" [color = dimgrey];
|
||||
"/gnu/store/nw68wjvbw505klgpsavq7dk195wg8ffj-gettext-minimal-0.19.8.1.drv" -> "/gnu/store/f1ww5vh5abnvr8b24llipm5dl89s5lq2-diffutils-3.5.drv" [color = dimgrey];
|
||||
"/gnu/store/nw68wjvbw505klgpsavq7dk195wg8ffj-gettext-minimal-0.19.8.1.drv" -> "/gnu/store/0cbgdhhyh7hsgwq1x54n9vnq99rfjch9-patch-2.7.5.drv" [color = dimgrey];
|
||||
"/gnu/store/nw68wjvbw505klgpsavq7dk195wg8ffj-gettext-minimal-0.19.8.1.drv" -> "/gnu/store/8xjnm44dfwwxp90hxq6zhb6qvia7rb3l-sed-4.2.2.drv" [color = dimgrey];
|
||||
"/gnu/store/nw68wjvbw505klgpsavq7dk195wg8ffj-gettext-minimal-0.19.8.1.drv" -> "/gnu/store/54wjl6dp6rp47r67f4nyfqyv8nh456yc-findutils-4.6.0.drv" [color = dimgrey];
|
||||
"/gnu/store/nw68wjvbw505klgpsavq7dk195wg8ffj-gettext-minimal-0.19.8.1.drv" -> "/gnu/store/k951w49yw74ikg19l4mmlwfrq9w7a7zd-gawk-4.1.4.drv" [color = dimgrey];
|
||||
"/gnu/store/nw68wjvbw505klgpsavq7dk195wg8ffj-gettext-minimal-0.19.8.1.drv" -> "/gnu/store/n48xdjkvhlhj5mgdzy59n0dpb9vn0v78-grep-2.25.drv" [color = dimgrey];
|
||||
"/gnu/store/nw68wjvbw505klgpsavq7dk195wg8ffj-gettext-minimal-0.19.8.1.drv" -> "/gnu/store/i52csyja3036ns0zj6z85lkgz3wfyym7-coreutils-8.25.drv" [color = dimgrey];
|
||||
"/gnu/store/nw68wjvbw505klgpsavq7dk195wg8ffj-gettext-minimal-0.19.8.1.drv" -> "/gnu/store/nv4mnbz3mpd4gv80djk7762wyvxpccqk-make-4.2.1.drv" [color = dimgrey];
|
||||
"/gnu/store/nw68wjvbw505klgpsavq7dk195wg8ffj-gettext-minimal-0.19.8.1.drv" -> "/gnu/store/2c60vlcvpj5dvmgklajkp7cpynhcqixr-bash-4.4.0.drv" [color = dimgrey];
|
||||
"/gnu/store/nw68wjvbw505klgpsavq7dk195wg8ffj-gettext-minimal-0.19.8.1.drv" -> "/gnu/store/zhc5c4s0xvzizpgpq2za6x84vxv57iy6-ld-wrapper-0.drv" [color = dimgrey];
|
||||
"/gnu/store/nw68wjvbw505klgpsavq7dk195wg8ffj-gettext-minimal-0.19.8.1.drv" -> "/gnu/store/9k1js0kalh4s6q4hf0rgg2n0zdyrwi69-binutils-2.27.drv" [color = dimgrey];
|
||||
"/gnu/store/nw68wjvbw505klgpsavq7dk195wg8ffj-gettext-minimal-0.19.8.1.drv" -> "/gnu/store/hv3dl3my12mq0gkwvckmnqccnckn39l0-gcc-4.9.4.drv" [color = dimgrey];
|
||||
"/gnu/store/nw68wjvbw505klgpsavq7dk195wg8ffj-gettext-minimal-0.19.8.1.drv" -> "/gnu/store/qbfynm50snyn31w2c3paiw2n6wvzksg8-glibc-2.24.drv" [color = dimgrey];
|
||||
"/gnu/store/nw68wjvbw505klgpsavq7dk195wg8ffj-gettext-minimal-0.19.8.1.drv" -> "/gnu/store/ir0lq2x7h64g2z5mlqvnlysjk2bc9xka-glibc-utf8-locales-2.24.drv" [color = dimgrey];
|
||||
"/gnu/store/nw68wjvbw505klgpsavq7dk195wg8ffj-gettext-minimal-0.19.8.1.drv" -> "/gnu/store/4dql1pzyivg87jwyfmmkwc6jll1vnizc-expat-2.2.0.drv" [color = dimgrey];
|
||||
"/gnu/store/4dql1pzyivg87jwyfmmkwc6jll1vnizc-expat-2.2.0.drv" [label = "expat-2.2.0", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/4dql1pzyivg87jwyfmmkwc6jll1vnizc-expat-2.2.0.drv" -> "/gnu/store/7ijl8lybdx95kndajavdrpz05jdiwy9g-tar-1.29.drv" [color = darkviolet];
|
||||
"/gnu/store/4dql1pzyivg87jwyfmmkwc6jll1vnizc-expat-2.2.0.drv" -> "/gnu/store/0ykf3p023pzfcg2bw8ahjc7cvmc12zjq-gzip-1.8.drv" [color = darkviolet];
|
||||
"/gnu/store/4dql1pzyivg87jwyfmmkwc6jll1vnizc-expat-2.2.0.drv" -> "/gnu/store/xx3hiqhqn0d94zz7b46hgggwsz3wjiiw-bzip2-1.0.6.drv" [color = darkviolet];
|
||||
"/gnu/store/4dql1pzyivg87jwyfmmkwc6jll1vnizc-expat-2.2.0.drv" -> "/gnu/store/kz8rzasivw4aflsv4rll3m539xybf226-xz-5.2.2.drv" [color = darkviolet];
|
||||
"/gnu/store/4dql1pzyivg87jwyfmmkwc6jll1vnizc-expat-2.2.0.drv" -> "/gnu/store/3pwrlsd23k2h104akxfj3cxhqcp973g9-file-5.28.drv" [color = darkviolet];
|
||||
"/gnu/store/4dql1pzyivg87jwyfmmkwc6jll1vnizc-expat-2.2.0.drv" -> "/gnu/store/f1ww5vh5abnvr8b24llipm5dl89s5lq2-diffutils-3.5.drv" [color = darkviolet];
|
||||
"/gnu/store/4dql1pzyivg87jwyfmmkwc6jll1vnizc-expat-2.2.0.drv" -> "/gnu/store/0cbgdhhyh7hsgwq1x54n9vnq99rfjch9-patch-2.7.5.drv" [color = darkviolet];
|
||||
"/gnu/store/4dql1pzyivg87jwyfmmkwc6jll1vnizc-expat-2.2.0.drv" -> "/gnu/store/8xjnm44dfwwxp90hxq6zhb6qvia7rb3l-sed-4.2.2.drv" [color = darkviolet];
|
||||
"/gnu/store/4dql1pzyivg87jwyfmmkwc6jll1vnizc-expat-2.2.0.drv" -> "/gnu/store/54wjl6dp6rp47r67f4nyfqyv8nh456yc-findutils-4.6.0.drv" [color = darkviolet];
|
||||
"/gnu/store/4dql1pzyivg87jwyfmmkwc6jll1vnizc-expat-2.2.0.drv" -> "/gnu/store/k951w49yw74ikg19l4mmlwfrq9w7a7zd-gawk-4.1.4.drv" [color = darkviolet];
|
||||
"/gnu/store/4dql1pzyivg87jwyfmmkwc6jll1vnizc-expat-2.2.0.drv" -> "/gnu/store/n48xdjkvhlhj5mgdzy59n0dpb9vn0v78-grep-2.25.drv" [color = darkviolet];
|
||||
"/gnu/store/4dql1pzyivg87jwyfmmkwc6jll1vnizc-expat-2.2.0.drv" -> "/gnu/store/i52csyja3036ns0zj6z85lkgz3wfyym7-coreutils-8.25.drv" [color = darkviolet];
|
||||
"/gnu/store/4dql1pzyivg87jwyfmmkwc6jll1vnizc-expat-2.2.0.drv" -> "/gnu/store/nv4mnbz3mpd4gv80djk7762wyvxpccqk-make-4.2.1.drv" [color = darkviolet];
|
||||
"/gnu/store/4dql1pzyivg87jwyfmmkwc6jll1vnizc-expat-2.2.0.drv" -> "/gnu/store/2c60vlcvpj5dvmgklajkp7cpynhcqixr-bash-4.4.0.drv" [color = darkviolet];
|
||||
"/gnu/store/4dql1pzyivg87jwyfmmkwc6jll1vnizc-expat-2.2.0.drv" -> "/gnu/store/zhc5c4s0xvzizpgpq2za6x84vxv57iy6-ld-wrapper-0.drv" [color = darkviolet];
|
||||
"/gnu/store/4dql1pzyivg87jwyfmmkwc6jll1vnizc-expat-2.2.0.drv" -> "/gnu/store/9k1js0kalh4s6q4hf0rgg2n0zdyrwi69-binutils-2.27.drv" [color = darkviolet];
|
||||
"/gnu/store/4dql1pzyivg87jwyfmmkwc6jll1vnizc-expat-2.2.0.drv" -> "/gnu/store/hv3dl3my12mq0gkwvckmnqccnckn39l0-gcc-4.9.4.drv" [color = darkviolet];
|
||||
"/gnu/store/4dql1pzyivg87jwyfmmkwc6jll1vnizc-expat-2.2.0.drv" -> "/gnu/store/qbfynm50snyn31w2c3paiw2n6wvzksg8-glibc-2.24.drv" [color = darkviolet];
|
||||
"/gnu/store/4dql1pzyivg87jwyfmmkwc6jll1vnizc-expat-2.2.0.drv" -> "/gnu/store/ir0lq2x7h64g2z5mlqvnlysjk2bc9xka-glibc-utf8-locales-2.24.drv" [color = darkviolet];
|
||||
"/gnu/store/gplx9i7c01f2r6qvm6d5w60iam73zmin-attr-2.4.47.drv" [label = "attr-2.4.47", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/gplx9i7c01f2r6qvm6d5w60iam73zmin-attr-2.4.47.drv" -> "/gnu/store/nw68wjvbw505klgpsavq7dk195wg8ffj-gettext-minimal-0.19.8.1.drv" [color = peachpuff4];
|
||||
"/gnu/store/gplx9i7c01f2r6qvm6d5w60iam73zmin-attr-2.4.47.drv" -> "/gnu/store/7ijl8lybdx95kndajavdrpz05jdiwy9g-tar-1.29.drv" [color = peachpuff4];
|
||||
"/gnu/store/gplx9i7c01f2r6qvm6d5w60iam73zmin-attr-2.4.47.drv" -> "/gnu/store/0ykf3p023pzfcg2bw8ahjc7cvmc12zjq-gzip-1.8.drv" [color = peachpuff4];
|
||||
"/gnu/store/gplx9i7c01f2r6qvm6d5w60iam73zmin-attr-2.4.47.drv" -> "/gnu/store/xx3hiqhqn0d94zz7b46hgggwsz3wjiiw-bzip2-1.0.6.drv" [color = peachpuff4];
|
||||
"/gnu/store/gplx9i7c01f2r6qvm6d5w60iam73zmin-attr-2.4.47.drv" -> "/gnu/store/kz8rzasivw4aflsv4rll3m539xybf226-xz-5.2.2.drv" [color = peachpuff4];
|
||||
"/gnu/store/gplx9i7c01f2r6qvm6d5w60iam73zmin-attr-2.4.47.drv" -> "/gnu/store/3pwrlsd23k2h104akxfj3cxhqcp973g9-file-5.28.drv" [color = peachpuff4];
|
||||
"/gnu/store/gplx9i7c01f2r6qvm6d5w60iam73zmin-attr-2.4.47.drv" -> "/gnu/store/f1ww5vh5abnvr8b24llipm5dl89s5lq2-diffutils-3.5.drv" [color = peachpuff4];
|
||||
"/gnu/store/gplx9i7c01f2r6qvm6d5w60iam73zmin-attr-2.4.47.drv" -> "/gnu/store/0cbgdhhyh7hsgwq1x54n9vnq99rfjch9-patch-2.7.5.drv" [color = peachpuff4];
|
||||
"/gnu/store/gplx9i7c01f2r6qvm6d5w60iam73zmin-attr-2.4.47.drv" -> "/gnu/store/8xjnm44dfwwxp90hxq6zhb6qvia7rb3l-sed-4.2.2.drv" [color = peachpuff4];
|
||||
"/gnu/store/gplx9i7c01f2r6qvm6d5w60iam73zmin-attr-2.4.47.drv" -> "/gnu/store/54wjl6dp6rp47r67f4nyfqyv8nh456yc-findutils-4.6.0.drv" [color = peachpuff4];
|
||||
"/gnu/store/gplx9i7c01f2r6qvm6d5w60iam73zmin-attr-2.4.47.drv" -> "/gnu/store/k951w49yw74ikg19l4mmlwfrq9w7a7zd-gawk-4.1.4.drv" [color = peachpuff4];
|
||||
"/gnu/store/gplx9i7c01f2r6qvm6d5w60iam73zmin-attr-2.4.47.drv" -> "/gnu/store/n48xdjkvhlhj5mgdzy59n0dpb9vn0v78-grep-2.25.drv" [color = peachpuff4];
|
||||
"/gnu/store/gplx9i7c01f2r6qvm6d5w60iam73zmin-attr-2.4.47.drv" -> "/gnu/store/i52csyja3036ns0zj6z85lkgz3wfyym7-coreutils-8.25.drv" [color = peachpuff4];
|
||||
"/gnu/store/gplx9i7c01f2r6qvm6d5w60iam73zmin-attr-2.4.47.drv" -> "/gnu/store/nv4mnbz3mpd4gv80djk7762wyvxpccqk-make-4.2.1.drv" [color = peachpuff4];
|
||||
"/gnu/store/gplx9i7c01f2r6qvm6d5w60iam73zmin-attr-2.4.47.drv" -> "/gnu/store/2c60vlcvpj5dvmgklajkp7cpynhcqixr-bash-4.4.0.drv" [color = peachpuff4];
|
||||
"/gnu/store/gplx9i7c01f2r6qvm6d5w60iam73zmin-attr-2.4.47.drv" -> "/gnu/store/zhc5c4s0xvzizpgpq2za6x84vxv57iy6-ld-wrapper-0.drv" [color = peachpuff4];
|
||||
"/gnu/store/gplx9i7c01f2r6qvm6d5w60iam73zmin-attr-2.4.47.drv" -> "/gnu/store/9k1js0kalh4s6q4hf0rgg2n0zdyrwi69-binutils-2.27.drv" [color = peachpuff4];
|
||||
"/gnu/store/gplx9i7c01f2r6qvm6d5w60iam73zmin-attr-2.4.47.drv" -> "/gnu/store/hv3dl3my12mq0gkwvckmnqccnckn39l0-gcc-4.9.4.drv" [color = peachpuff4];
|
||||
"/gnu/store/gplx9i7c01f2r6qvm6d5w60iam73zmin-attr-2.4.47.drv" -> "/gnu/store/qbfynm50snyn31w2c3paiw2n6wvzksg8-glibc-2.24.drv" [color = peachpuff4];
|
||||
"/gnu/store/gplx9i7c01f2r6qvm6d5w60iam73zmin-attr-2.4.47.drv" -> "/gnu/store/ir0lq2x7h64g2z5mlqvnlysjk2bc9xka-glibc-utf8-locales-2.24.drv" [color = peachpuff4];
|
||||
"/gnu/store/gplx9i7c01f2r6qvm6d5w60iam73zmin-attr-2.4.47.drv" -> "/gnu/store/jxcx1jcvzxb17dc69sfwb352vgwyr108-perl-5.24.0.drv" [color = peachpuff4];
|
||||
"/gnu/store/7gqg2kmrm1bjgphnd70ps5c11gqml571-gmp-6.1.1.drv" [label = "gmp-6.1.1", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/7gqg2kmrm1bjgphnd70ps5c11gqml571-gmp-6.1.1.drv" -> "/gnu/store/d1n7i55s1zcwzi21pnsxhamk3b1zf61d-m4-1.4.17.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/7gqg2kmrm1bjgphnd70ps5c11gqml571-gmp-6.1.1.drv" -> "/gnu/store/7ijl8lybdx95kndajavdrpz05jdiwy9g-tar-1.29.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/7gqg2kmrm1bjgphnd70ps5c11gqml571-gmp-6.1.1.drv" -> "/gnu/store/0ykf3p023pzfcg2bw8ahjc7cvmc12zjq-gzip-1.8.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/7gqg2kmrm1bjgphnd70ps5c11gqml571-gmp-6.1.1.drv" -> "/gnu/store/xx3hiqhqn0d94zz7b46hgggwsz3wjiiw-bzip2-1.0.6.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/7gqg2kmrm1bjgphnd70ps5c11gqml571-gmp-6.1.1.drv" -> "/gnu/store/kz8rzasivw4aflsv4rll3m539xybf226-xz-5.2.2.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/7gqg2kmrm1bjgphnd70ps5c11gqml571-gmp-6.1.1.drv" -> "/gnu/store/3pwrlsd23k2h104akxfj3cxhqcp973g9-file-5.28.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/7gqg2kmrm1bjgphnd70ps5c11gqml571-gmp-6.1.1.drv" -> "/gnu/store/f1ww5vh5abnvr8b24llipm5dl89s5lq2-diffutils-3.5.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/7gqg2kmrm1bjgphnd70ps5c11gqml571-gmp-6.1.1.drv" -> "/gnu/store/0cbgdhhyh7hsgwq1x54n9vnq99rfjch9-patch-2.7.5.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/7gqg2kmrm1bjgphnd70ps5c11gqml571-gmp-6.1.1.drv" -> "/gnu/store/8xjnm44dfwwxp90hxq6zhb6qvia7rb3l-sed-4.2.2.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/7gqg2kmrm1bjgphnd70ps5c11gqml571-gmp-6.1.1.drv" -> "/gnu/store/54wjl6dp6rp47r67f4nyfqyv8nh456yc-findutils-4.6.0.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/7gqg2kmrm1bjgphnd70ps5c11gqml571-gmp-6.1.1.drv" -> "/gnu/store/k951w49yw74ikg19l4mmlwfrq9w7a7zd-gawk-4.1.4.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/7gqg2kmrm1bjgphnd70ps5c11gqml571-gmp-6.1.1.drv" -> "/gnu/store/n48xdjkvhlhj5mgdzy59n0dpb9vn0v78-grep-2.25.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/7gqg2kmrm1bjgphnd70ps5c11gqml571-gmp-6.1.1.drv" -> "/gnu/store/i52csyja3036ns0zj6z85lkgz3wfyym7-coreutils-8.25.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/7gqg2kmrm1bjgphnd70ps5c11gqml571-gmp-6.1.1.drv" -> "/gnu/store/nv4mnbz3mpd4gv80djk7762wyvxpccqk-make-4.2.1.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/7gqg2kmrm1bjgphnd70ps5c11gqml571-gmp-6.1.1.drv" -> "/gnu/store/2c60vlcvpj5dvmgklajkp7cpynhcqixr-bash-4.4.0.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/7gqg2kmrm1bjgphnd70ps5c11gqml571-gmp-6.1.1.drv" -> "/gnu/store/zhc5c4s0xvzizpgpq2za6x84vxv57iy6-ld-wrapper-0.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/7gqg2kmrm1bjgphnd70ps5c11gqml571-gmp-6.1.1.drv" -> "/gnu/store/9k1js0kalh4s6q4hf0rgg2n0zdyrwi69-binutils-2.27.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/7gqg2kmrm1bjgphnd70ps5c11gqml571-gmp-6.1.1.drv" -> "/gnu/store/hv3dl3my12mq0gkwvckmnqccnckn39l0-gcc-4.9.4.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/7gqg2kmrm1bjgphnd70ps5c11gqml571-gmp-6.1.1.drv" -> "/gnu/store/qbfynm50snyn31w2c3paiw2n6wvzksg8-glibc-2.24.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/7gqg2kmrm1bjgphnd70ps5c11gqml571-gmp-6.1.1.drv" -> "/gnu/store/ir0lq2x7h64g2z5mlqvnlysjk2bc9xka-glibc-utf8-locales-2.24.drv" [color = darkgoldenrod];
|
||||
"/gnu/store/d1n7i55s1zcwzi21pnsxhamk3b1zf61d-m4-1.4.17.drv" [label = "m4-1.4.17", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/d1n7i55s1zcwzi21pnsxhamk3b1zf61d-m4-1.4.17.drv" -> "/gnu/store/7ijl8lybdx95kndajavdrpz05jdiwy9g-tar-1.29.drv" [color = cyan3];
|
||||
"/gnu/store/d1n7i55s1zcwzi21pnsxhamk3b1zf61d-m4-1.4.17.drv" -> "/gnu/store/0ykf3p023pzfcg2bw8ahjc7cvmc12zjq-gzip-1.8.drv" [color = cyan3];
|
||||
"/gnu/store/d1n7i55s1zcwzi21pnsxhamk3b1zf61d-m4-1.4.17.drv" -> "/gnu/store/xx3hiqhqn0d94zz7b46hgggwsz3wjiiw-bzip2-1.0.6.drv" [color = cyan3];
|
||||
"/gnu/store/d1n7i55s1zcwzi21pnsxhamk3b1zf61d-m4-1.4.17.drv" -> "/gnu/store/kz8rzasivw4aflsv4rll3m539xybf226-xz-5.2.2.drv" [color = cyan3];
|
||||
"/gnu/store/d1n7i55s1zcwzi21pnsxhamk3b1zf61d-m4-1.4.17.drv" -> "/gnu/store/3pwrlsd23k2h104akxfj3cxhqcp973g9-file-5.28.drv" [color = cyan3];
|
||||
"/gnu/store/d1n7i55s1zcwzi21pnsxhamk3b1zf61d-m4-1.4.17.drv" -> "/gnu/store/f1ww5vh5abnvr8b24llipm5dl89s5lq2-diffutils-3.5.drv" [color = cyan3];
|
||||
"/gnu/store/d1n7i55s1zcwzi21pnsxhamk3b1zf61d-m4-1.4.17.drv" -> "/gnu/store/0cbgdhhyh7hsgwq1x54n9vnq99rfjch9-patch-2.7.5.drv" [color = cyan3];
|
||||
"/gnu/store/d1n7i55s1zcwzi21pnsxhamk3b1zf61d-m4-1.4.17.drv" -> "/gnu/store/8xjnm44dfwwxp90hxq6zhb6qvia7rb3l-sed-4.2.2.drv" [color = cyan3];
|
||||
"/gnu/store/d1n7i55s1zcwzi21pnsxhamk3b1zf61d-m4-1.4.17.drv" -> "/gnu/store/54wjl6dp6rp47r67f4nyfqyv8nh456yc-findutils-4.6.0.drv" [color = cyan3];
|
||||
"/gnu/store/d1n7i55s1zcwzi21pnsxhamk3b1zf61d-m4-1.4.17.drv" -> "/gnu/store/k951w49yw74ikg19l4mmlwfrq9w7a7zd-gawk-4.1.4.drv" [color = cyan3];
|
||||
"/gnu/store/d1n7i55s1zcwzi21pnsxhamk3b1zf61d-m4-1.4.17.drv" -> "/gnu/store/n48xdjkvhlhj5mgdzy59n0dpb9vn0v78-grep-2.25.drv" [color = cyan3];
|
||||
"/gnu/store/d1n7i55s1zcwzi21pnsxhamk3b1zf61d-m4-1.4.17.drv" -> "/gnu/store/i52csyja3036ns0zj6z85lkgz3wfyym7-coreutils-8.25.drv" [color = cyan3];
|
||||
"/gnu/store/d1n7i55s1zcwzi21pnsxhamk3b1zf61d-m4-1.4.17.drv" -> "/gnu/store/nv4mnbz3mpd4gv80djk7762wyvxpccqk-make-4.2.1.drv" [color = cyan3];
|
||||
"/gnu/store/d1n7i55s1zcwzi21pnsxhamk3b1zf61d-m4-1.4.17.drv" -> "/gnu/store/2c60vlcvpj5dvmgklajkp7cpynhcqixr-bash-4.4.0.drv" [color = cyan3];
|
||||
"/gnu/store/d1n7i55s1zcwzi21pnsxhamk3b1zf61d-m4-1.4.17.drv" -> "/gnu/store/zhc5c4s0xvzizpgpq2za6x84vxv57iy6-ld-wrapper-0.drv" [color = cyan3];
|
||||
"/gnu/store/d1n7i55s1zcwzi21pnsxhamk3b1zf61d-m4-1.4.17.drv" -> "/gnu/store/9k1js0kalh4s6q4hf0rgg2n0zdyrwi69-binutils-2.27.drv" [color = cyan3];
|
||||
"/gnu/store/d1n7i55s1zcwzi21pnsxhamk3b1zf61d-m4-1.4.17.drv" -> "/gnu/store/hv3dl3my12mq0gkwvckmnqccnckn39l0-gcc-4.9.4.drv" [color = cyan3];
|
||||
"/gnu/store/d1n7i55s1zcwzi21pnsxhamk3b1zf61d-m4-1.4.17.drv" -> "/gnu/store/qbfynm50snyn31w2c3paiw2n6wvzksg8-glibc-2.24.drv" [color = cyan3];
|
||||
"/gnu/store/d1n7i55s1zcwzi21pnsxhamk3b1zf61d-m4-1.4.17.drv" -> "/gnu/store/ir0lq2x7h64g2z5mlqvnlysjk2bc9xka-glibc-utf8-locales-2.24.drv" [color = cyan3];
|
||||
"/gnu/store/ijv3y5l1fbbzwb77lc867r1qbsf147i8-libcap-2.24.drv" [label = "libcap-2.24", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/ijv3y5l1fbbzwb77lc867r1qbsf147i8-libcap-2.24.drv" -> "/gnu/store/jxcx1jcvzxb17dc69sfwb352vgwyr108-perl-5.24.0.drv" [color = blue];
|
||||
"/gnu/store/ijv3y5l1fbbzwb77lc867r1qbsf147i8-libcap-2.24.drv" -> "/gnu/store/7ijl8lybdx95kndajavdrpz05jdiwy9g-tar-1.29.drv" [color = blue];
|
||||
"/gnu/store/ijv3y5l1fbbzwb77lc867r1qbsf147i8-libcap-2.24.drv" -> "/gnu/store/0ykf3p023pzfcg2bw8ahjc7cvmc12zjq-gzip-1.8.drv" [color = blue];
|
||||
"/gnu/store/ijv3y5l1fbbzwb77lc867r1qbsf147i8-libcap-2.24.drv" -> "/gnu/store/xx3hiqhqn0d94zz7b46hgggwsz3wjiiw-bzip2-1.0.6.drv" [color = blue];
|
||||
"/gnu/store/ijv3y5l1fbbzwb77lc867r1qbsf147i8-libcap-2.24.drv" -> "/gnu/store/kz8rzasivw4aflsv4rll3m539xybf226-xz-5.2.2.drv" [color = blue];
|
||||
"/gnu/store/ijv3y5l1fbbzwb77lc867r1qbsf147i8-libcap-2.24.drv" -> "/gnu/store/3pwrlsd23k2h104akxfj3cxhqcp973g9-file-5.28.drv" [color = blue];
|
||||
"/gnu/store/ijv3y5l1fbbzwb77lc867r1qbsf147i8-libcap-2.24.drv" -> "/gnu/store/f1ww5vh5abnvr8b24llipm5dl89s5lq2-diffutils-3.5.drv" [color = blue];
|
||||
"/gnu/store/ijv3y5l1fbbzwb77lc867r1qbsf147i8-libcap-2.24.drv" -> "/gnu/store/0cbgdhhyh7hsgwq1x54n9vnq99rfjch9-patch-2.7.5.drv" [color = blue];
|
||||
"/gnu/store/ijv3y5l1fbbzwb77lc867r1qbsf147i8-libcap-2.24.drv" -> "/gnu/store/8xjnm44dfwwxp90hxq6zhb6qvia7rb3l-sed-4.2.2.drv" [color = blue];
|
||||
"/gnu/store/ijv3y5l1fbbzwb77lc867r1qbsf147i8-libcap-2.24.drv" -> "/gnu/store/54wjl6dp6rp47r67f4nyfqyv8nh456yc-findutils-4.6.0.drv" [color = blue];
|
||||
"/gnu/store/ijv3y5l1fbbzwb77lc867r1qbsf147i8-libcap-2.24.drv" -> "/gnu/store/k951w49yw74ikg19l4mmlwfrq9w7a7zd-gawk-4.1.4.drv" [color = blue];
|
||||
"/gnu/store/ijv3y5l1fbbzwb77lc867r1qbsf147i8-libcap-2.24.drv" -> "/gnu/store/n48xdjkvhlhj5mgdzy59n0dpb9vn0v78-grep-2.25.drv" [color = blue];
|
||||
"/gnu/store/ijv3y5l1fbbzwb77lc867r1qbsf147i8-libcap-2.24.drv" -> "/gnu/store/i52csyja3036ns0zj6z85lkgz3wfyym7-coreutils-8.25.drv" [color = blue];
|
||||
"/gnu/store/ijv3y5l1fbbzwb77lc867r1qbsf147i8-libcap-2.24.drv" -> "/gnu/store/nv4mnbz3mpd4gv80djk7762wyvxpccqk-make-4.2.1.drv" [color = blue];
|
||||
"/gnu/store/ijv3y5l1fbbzwb77lc867r1qbsf147i8-libcap-2.24.drv" -> "/gnu/store/2c60vlcvpj5dvmgklajkp7cpynhcqixr-bash-4.4.0.drv" [color = blue];
|
||||
"/gnu/store/ijv3y5l1fbbzwb77lc867r1qbsf147i8-libcap-2.24.drv" -> "/gnu/store/zhc5c4s0xvzizpgpq2za6x84vxv57iy6-ld-wrapper-0.drv" [color = blue];
|
||||
"/gnu/store/ijv3y5l1fbbzwb77lc867r1qbsf147i8-libcap-2.24.drv" -> "/gnu/store/9k1js0kalh4s6q4hf0rgg2n0zdyrwi69-binutils-2.27.drv" [color = blue];
|
||||
"/gnu/store/ijv3y5l1fbbzwb77lc867r1qbsf147i8-libcap-2.24.drv" -> "/gnu/store/hv3dl3my12mq0gkwvckmnqccnckn39l0-gcc-4.9.4.drv" [color = blue];
|
||||
"/gnu/store/ijv3y5l1fbbzwb77lc867r1qbsf147i8-libcap-2.24.drv" -> "/gnu/store/qbfynm50snyn31w2c3paiw2n6wvzksg8-glibc-2.24.drv" [color = blue];
|
||||
"/gnu/store/ijv3y5l1fbbzwb77lc867r1qbsf147i8-libcap-2.24.drv" -> "/gnu/store/ir0lq2x7h64g2z5mlqvnlysjk2bc9xka-glibc-utf8-locales-2.24.drv" [color = blue];
|
||||
"/gnu/store/ijv3y5l1fbbzwb77lc867r1qbsf147i8-libcap-2.24.drv" -> "/gnu/store/gplx9i7c01f2r6qvm6d5w60iam73zmin-attr-2.4.47.drv" [color = blue];
|
||||
"/gnu/store/xpgn2qn54c323liliyqj6q11b5xnb1db-coreutils-8.24.drv" [label = "coreutils-8.24", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/xpgn2qn54c323liliyqj6q11b5xnb1db-coreutils-8.24.drv" -> "/gnu/store/mi4a8m41ssrp7lv3b8vibw0a7ahv2mmg-perl-5.16.1.drv" [color = red];
|
||||
"/gnu/store/xpgn2qn54c323liliyqj6q11b5xnb1db-coreutils-8.24.drv" -> "/gnu/store/0pr679inn5xj91z4d63scc7vgfji9vpp-tar-1.28.drv" [color = red];
|
||||
"/gnu/store/xpgn2qn54c323liliyqj6q11b5xnb1db-coreutils-8.24.drv" -> "/gnu/store/p3szkb87bp9fxhn715g88skry8g3jgkq-gzip-1.6.drv" [color = red];
|
||||
"/gnu/store/xpgn2qn54c323liliyqj6q11b5xnb1db-coreutils-8.24.drv" -> "/gnu/store/i398qn04cwvnzph7a0cckxqr9q0k3lyr-bzip2-1.0.6.drv" [color = red];
|
||||
"/gnu/store/xpgn2qn54c323liliyqj6q11b5xnb1db-coreutils-8.24.drv" -> "/gnu/store/wvnnsn89magnvn39zm3fv245s9m7yn5f-xz-5.0.4.drv" [color = red];
|
||||
"/gnu/store/xpgn2qn54c323liliyqj6q11b5xnb1db-coreutils-8.24.drv" -> "/gnu/store/sag0sx1zycnwixwfdrxwj1i9g2phxrh4-file-5.22.drv" [color = red];
|
||||
"/gnu/store/xpgn2qn54c323liliyqj6q11b5xnb1db-coreutils-8.24.drv" -> "/gnu/store/p61bsw6093x3wfg5vz3172wl9bzrlc3w-diffutils-3.3.drv" [color = red];
|
||||
"/gnu/store/xpgn2qn54c323liliyqj6q11b5xnb1db-coreutils-8.24.drv" -> "/gnu/store/rzsyx70vnfb8cm40r0b591vyvww2i5y6-patch-2.7.5.drv" [color = red];
|
||||
"/gnu/store/xpgn2qn54c323liliyqj6q11b5xnb1db-coreutils-8.24.drv" -> "/gnu/store/mc5fgclyr0v26242hmg30srv9ij27wyv-sed-4.2.2.drv" [color = red];
|
||||
"/gnu/store/xpgn2qn54c323liliyqj6q11b5xnb1db-coreutils-8.24.drv" -> "/gnu/store/ig9nr2f5hvr88br028r9nsdg4xpmmybg-findutils-4.4.2.drv" [color = red];
|
||||
"/gnu/store/xpgn2qn54c323liliyqj6q11b5xnb1db-coreutils-8.24.drv" -> "/gnu/store/jls1kj3pvqjpbmm7c09fhszfd3m61zif-gawk-4.1.3.drv" [color = red];
|
||||
"/gnu/store/xpgn2qn54c323liliyqj6q11b5xnb1db-coreutils-8.24.drv" -> "/gnu/store/vvlh6szjxr5iy192fsv9p4dwf39nhapf-grep-2.21.drv" [color = red];
|
||||
"/gnu/store/xpgn2qn54c323liliyqj6q11b5xnb1db-coreutils-8.24.drv" -> "/gnu/store/mysb2grsl1wc931xm08adncnqjwvdds7-coreutils-8.24.drv" [color = red];
|
||||
"/gnu/store/xpgn2qn54c323liliyqj6q11b5xnb1db-coreutils-8.24.drv" -> "/gnu/store/n0n20i1brmhmjvw9lx33f2l3dmzx873n-make-4.1.drv" [color = red];
|
||||
"/gnu/store/xpgn2qn54c323liliyqj6q11b5xnb1db-coreutils-8.24.drv" -> "/gnu/store/64cizlhq38x99dvjvza6c5ha226a9bf5-bash-4.3.39.drv" [color = red];
|
||||
"/gnu/store/xpgn2qn54c323liliyqj6q11b5xnb1db-coreutils-8.24.drv" -> "/gnu/store/mbshnjz590h3l1c3y2rxzqvn45bhx32b-ld-wrapper-0.drv" [color = red];
|
||||
"/gnu/store/xpgn2qn54c323liliyqj6q11b5xnb1db-coreutils-8.24.drv" -> "/gnu/store/hf62yhvyrr1rm5y8mq5afih12s9jasic-binutils-2.25.1.drv" [color = red];
|
||||
"/gnu/store/xpgn2qn54c323liliyqj6q11b5xnb1db-coreutils-8.24.drv" -> "/gnu/store/8mff0w2203h6m5s495knxg09is3qj15f-gcc-4.9.3.drv" [color = red];
|
||||
"/gnu/store/xpgn2qn54c323liliyqj6q11b5xnb1db-coreutils-8.24.drv" -> "/gnu/store/2pspbpclj4yq5dqd71fnqwa69s8xxryf-glibc-2.22.drv" [color = red];
|
||||
"/gnu/store/xpgn2qn54c323liliyqj6q11b5xnb1db-coreutils-8.24.drv" -> "/gnu/store/nflynk1n90yh41yfi91raczynka2mf86-glibc-utf8-locales-2.22.drv" [color = red];
|
||||
"/gnu/store/xpgn2qn54c323liliyqj6q11b5xnb1db-coreutils-8.24.drv" -> "/gnu/store/6i8brik0khb2s5r6ih7h6g22l9s2xmph-acl-2.2.52.drv" [color = red];
|
||||
"/gnu/store/xpgn2qn54c323liliyqj6q11b5xnb1db-coreutils-8.24.drv" -> "/gnu/store/wmvpskqsw6hgriy0vbmmm6c4wp8rxp2c-gmp-6.0.0a.drv" [color = red];
|
||||
"/gnu/store/xpgn2qn54c323liliyqj6q11b5xnb1db-coreutils-8.24.drv" -> "/gnu/store/d7d6k5bhk7gz3pvhxdn2f33jzlxg4c5l-libcap-2.24.drv" [color = red];
|
||||
"/gnu/store/mi4a8m41ssrp7lv3b8vibw0a7ahv2mmg-perl-5.16.1.drv" [label = "perl-5.16.1", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/mi4a8m41ssrp7lv3b8vibw0a7ahv2mmg-perl-5.16.1.drv" -> "/gnu/store/0pr679inn5xj91z4d63scc7vgfji9vpp-tar-1.28.drv" [color = red];
|
||||
"/gnu/store/mi4a8m41ssrp7lv3b8vibw0a7ahv2mmg-perl-5.16.1.drv" -> "/gnu/store/p3szkb87bp9fxhn715g88skry8g3jgkq-gzip-1.6.drv" [color = red];
|
||||
"/gnu/store/mi4a8m41ssrp7lv3b8vibw0a7ahv2mmg-perl-5.16.1.drv" -> "/gnu/store/i398qn04cwvnzph7a0cckxqr9q0k3lyr-bzip2-1.0.6.drv" [color = red];
|
||||
"/gnu/store/mi4a8m41ssrp7lv3b8vibw0a7ahv2mmg-perl-5.16.1.drv" -> "/gnu/store/wvnnsn89magnvn39zm3fv245s9m7yn5f-xz-5.0.4.drv" [color = red];
|
||||
"/gnu/store/mi4a8m41ssrp7lv3b8vibw0a7ahv2mmg-perl-5.16.1.drv" -> "/gnu/store/sag0sx1zycnwixwfdrxwj1i9g2phxrh4-file-5.22.drv" [color = red];
|
||||
"/gnu/store/mi4a8m41ssrp7lv3b8vibw0a7ahv2mmg-perl-5.16.1.drv" -> "/gnu/store/p61bsw6093x3wfg5vz3172wl9bzrlc3w-diffutils-3.3.drv" [color = red];
|
||||
"/gnu/store/mi4a8m41ssrp7lv3b8vibw0a7ahv2mmg-perl-5.16.1.drv" -> "/gnu/store/rzsyx70vnfb8cm40r0b591vyvww2i5y6-patch-2.7.5.drv" [color = red];
|
||||
"/gnu/store/mi4a8m41ssrp7lv3b8vibw0a7ahv2mmg-perl-5.16.1.drv" -> "/gnu/store/mc5fgclyr0v26242hmg30srv9ij27wyv-sed-4.2.2.drv" [color = red];
|
||||
"/gnu/store/mi4a8m41ssrp7lv3b8vibw0a7ahv2mmg-perl-5.16.1.drv" -> "/gnu/store/ig9nr2f5hvr88br028r9nsdg4xpmmybg-findutils-4.4.2.drv" [color = red];
|
||||
"/gnu/store/mi4a8m41ssrp7lv3b8vibw0a7ahv2mmg-perl-5.16.1.drv" -> "/gnu/store/jls1kj3pvqjpbmm7c09fhszfd3m61zif-gawk-4.1.3.drv" [color = red];
|
||||
"/gnu/store/mi4a8m41ssrp7lv3b8vibw0a7ahv2mmg-perl-5.16.1.drv" -> "/gnu/store/vvlh6szjxr5iy192fsv9p4dwf39nhapf-grep-2.21.drv" [color = red];
|
||||
"/gnu/store/mi4a8m41ssrp7lv3b8vibw0a7ahv2mmg-perl-5.16.1.drv" -> "/gnu/store/mysb2grsl1wc931xm08adncnqjwvdds7-coreutils-8.24.drv" [color = red];
|
||||
"/gnu/store/mi4a8m41ssrp7lv3b8vibw0a7ahv2mmg-perl-5.16.1.drv" -> "/gnu/store/n0n20i1brmhmjvw9lx33f2l3dmzx873n-make-4.1.drv" [color = red];
|
||||
"/gnu/store/mi4a8m41ssrp7lv3b8vibw0a7ahv2mmg-perl-5.16.1.drv" -> "/gnu/store/64cizlhq38x99dvjvza6c5ha226a9bf5-bash-4.3.39.drv" [color = red];
|
||||
"/gnu/store/mi4a8m41ssrp7lv3b8vibw0a7ahv2mmg-perl-5.16.1.drv" -> "/gnu/store/mbshnjz590h3l1c3y2rxzqvn45bhx32b-ld-wrapper-0.drv" [color = red];
|
||||
"/gnu/store/mi4a8m41ssrp7lv3b8vibw0a7ahv2mmg-perl-5.16.1.drv" -> "/gnu/store/hf62yhvyrr1rm5y8mq5afih12s9jasic-binutils-2.25.1.drv" [color = red];
|
||||
"/gnu/store/mi4a8m41ssrp7lv3b8vibw0a7ahv2mmg-perl-5.16.1.drv" -> "/gnu/store/8mff0w2203h6m5s495knxg09is3qj15f-gcc-4.9.3.drv" [color = red];
|
||||
"/gnu/store/mi4a8m41ssrp7lv3b8vibw0a7ahv2mmg-perl-5.16.1.drv" -> "/gnu/store/2pspbpclj4yq5dqd71fnqwa69s8xxryf-glibc-2.22.drv" [color = red];
|
||||
"/gnu/store/mi4a8m41ssrp7lv3b8vibw0a7ahv2mmg-perl-5.16.1.drv" -> "/gnu/store/nflynk1n90yh41yfi91raczynka2mf86-glibc-utf8-locales-2.22.drv" [color = red];
|
||||
"/gnu/store/0pr679inn5xj91z4d63scc7vgfji9vpp-tar-1.28.drv" [label = "tar-1.28", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/p3szkb87bp9fxhn715g88skry8g3jgkq-gzip-1.6.drv" [label = "gzip-1.6", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/i398qn04cwvnzph7a0cckxqr9q0k3lyr-bzip2-1.0.6.drv" [label = "bzip2-1.0.6", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/wvnnsn89magnvn39zm3fv245s9m7yn5f-xz-5.0.4.drv" [label = "xz-5.0.4", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/sag0sx1zycnwixwfdrxwj1i9g2phxrh4-file-5.22.drv" [label = "file-5.22", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/p61bsw6093x3wfg5vz3172wl9bzrlc3w-diffutils-3.3.drv" [label = "diffutils-3.3", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/rzsyx70vnfb8cm40r0b591vyvww2i5y6-patch-2.7.5.drv" [label = "patch-2.7.5", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/mc5fgclyr0v26242hmg30srv9ij27wyv-sed-4.2.2.drv" [label = "sed-4.2.2", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/ig9nr2f5hvr88br028r9nsdg4xpmmybg-findutils-4.4.2.drv" [label = "findutils-4.4.2", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/jls1kj3pvqjpbmm7c09fhszfd3m61zif-gawk-4.1.3.drv" [label = "gawk-4.1.3", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/vvlh6szjxr5iy192fsv9p4dwf39nhapf-grep-2.21.drv" [label = "grep-2.21", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/mysb2grsl1wc931xm08adncnqjwvdds7-coreutils-8.24.drv" [label = "coreutils-8.24", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/n0n20i1brmhmjvw9lx33f2l3dmzx873n-make-4.1.drv" [label = "make-4.1", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/64cizlhq38x99dvjvza6c5ha226a9bf5-bash-4.3.39.drv" [label = "bash-4.3.39", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/mbshnjz590h3l1c3y2rxzqvn45bhx32b-ld-wrapper-0.drv" [label = "ld-wrapper-0", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/hf62yhvyrr1rm5y8mq5afih12s9jasic-binutils-2.25.1.drv" [label = "binutils-2.25.1", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/8mff0w2203h6m5s495knxg09is3qj15f-gcc-4.9.3.drv" [label = "gcc-4.9.3", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/2pspbpclj4yq5dqd71fnqwa69s8xxryf-glibc-2.22.drv" [label = "glibc-2.22", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/nflynk1n90yh41yfi91raczynka2mf86-glibc-utf8-locales-2.22.drv" [label = "glibc-utf8-locales-2.22", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/6i8brik0khb2s5r6ih7h6g22l9s2xmph-acl-2.2.52.drv" [label = "acl-2.2.52", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/6i8brik0khb2s5r6ih7h6g22l9s2xmph-acl-2.2.52.drv" -> "/gnu/store/a076d7ng0h3ynr1hsiyk4fmh3w1g4cv8-gettext-0.19.6.drv" [color = red];
|
||||
"/gnu/store/6i8brik0khb2s5r6ih7h6g22l9s2xmph-acl-2.2.52.drv" -> "/gnu/store/mi4a8m41ssrp7lv3b8vibw0a7ahv2mmg-perl-5.16.1.drv" [color = red];
|
||||
"/gnu/store/6i8brik0khb2s5r6ih7h6g22l9s2xmph-acl-2.2.52.drv" -> "/gnu/store/0pr679inn5xj91z4d63scc7vgfji9vpp-tar-1.28.drv" [color = red];
|
||||
"/gnu/store/6i8brik0khb2s5r6ih7h6g22l9s2xmph-acl-2.2.52.drv" -> "/gnu/store/p3szkb87bp9fxhn715g88skry8g3jgkq-gzip-1.6.drv" [color = red];
|
||||
"/gnu/store/6i8brik0khb2s5r6ih7h6g22l9s2xmph-acl-2.2.52.drv" -> "/gnu/store/i398qn04cwvnzph7a0cckxqr9q0k3lyr-bzip2-1.0.6.drv" [color = red];
|
||||
"/gnu/store/6i8brik0khb2s5r6ih7h6g22l9s2xmph-acl-2.2.52.drv" -> "/gnu/store/wvnnsn89magnvn39zm3fv245s9m7yn5f-xz-5.0.4.drv" [color = red];
|
||||
"/gnu/store/6i8brik0khb2s5r6ih7h6g22l9s2xmph-acl-2.2.52.drv" -> "/gnu/store/sag0sx1zycnwixwfdrxwj1i9g2phxrh4-file-5.22.drv" [color = red];
|
||||
"/gnu/store/6i8brik0khb2s5r6ih7h6g22l9s2xmph-acl-2.2.52.drv" -> "/gnu/store/p61bsw6093x3wfg5vz3172wl9bzrlc3w-diffutils-3.3.drv" [color = red];
|
||||
"/gnu/store/6i8brik0khb2s5r6ih7h6g22l9s2xmph-acl-2.2.52.drv" -> "/gnu/store/rzsyx70vnfb8cm40r0b591vyvww2i5y6-patch-2.7.5.drv" [color = red];
|
||||
"/gnu/store/6i8brik0khb2s5r6ih7h6g22l9s2xmph-acl-2.2.52.drv" -> "/gnu/store/mc5fgclyr0v26242hmg30srv9ij27wyv-sed-4.2.2.drv" [color = red];
|
||||
"/gnu/store/6i8brik0khb2s5r6ih7h6g22l9s2xmph-acl-2.2.52.drv" -> "/gnu/store/ig9nr2f5hvr88br028r9nsdg4xpmmybg-findutils-4.4.2.drv" [color = red];
|
||||
"/gnu/store/6i8brik0khb2s5r6ih7h6g22l9s2xmph-acl-2.2.52.drv" -> "/gnu/store/jls1kj3pvqjpbmm7c09fhszfd3m61zif-gawk-4.1.3.drv" [color = red];
|
||||
"/gnu/store/6i8brik0khb2s5r6ih7h6g22l9s2xmph-acl-2.2.52.drv" -> "/gnu/store/vvlh6szjxr5iy192fsv9p4dwf39nhapf-grep-2.21.drv" [color = red];
|
||||
"/gnu/store/6i8brik0khb2s5r6ih7h6g22l9s2xmph-acl-2.2.52.drv" -> "/gnu/store/mysb2grsl1wc931xm08adncnqjwvdds7-coreutils-8.24.drv" [color = red];
|
||||
"/gnu/store/6i8brik0khb2s5r6ih7h6g22l9s2xmph-acl-2.2.52.drv" -> "/gnu/store/n0n20i1brmhmjvw9lx33f2l3dmzx873n-make-4.1.drv" [color = red];
|
||||
"/gnu/store/6i8brik0khb2s5r6ih7h6g22l9s2xmph-acl-2.2.52.drv" -> "/gnu/store/64cizlhq38x99dvjvza6c5ha226a9bf5-bash-4.3.39.drv" [color = red];
|
||||
"/gnu/store/6i8brik0khb2s5r6ih7h6g22l9s2xmph-acl-2.2.52.drv" -> "/gnu/store/mbshnjz590h3l1c3y2rxzqvn45bhx32b-ld-wrapper-0.drv" [color = red];
|
||||
"/gnu/store/6i8brik0khb2s5r6ih7h6g22l9s2xmph-acl-2.2.52.drv" -> "/gnu/store/hf62yhvyrr1rm5y8mq5afih12s9jasic-binutils-2.25.1.drv" [color = red];
|
||||
"/gnu/store/6i8brik0khb2s5r6ih7h6g22l9s2xmph-acl-2.2.52.drv" -> "/gnu/store/8mff0w2203h6m5s495knxg09is3qj15f-gcc-4.9.3.drv" [color = red];
|
||||
"/gnu/store/6i8brik0khb2s5r6ih7h6g22l9s2xmph-acl-2.2.52.drv" -> "/gnu/store/2pspbpclj4yq5dqd71fnqwa69s8xxryf-glibc-2.22.drv" [color = red];
|
||||
"/gnu/store/6i8brik0khb2s5r6ih7h6g22l9s2xmph-acl-2.2.52.drv" -> "/gnu/store/nflynk1n90yh41yfi91raczynka2mf86-glibc-utf8-locales-2.22.drv" [color = red];
|
||||
"/gnu/store/6i8brik0khb2s5r6ih7h6g22l9s2xmph-acl-2.2.52.drv" -> "/gnu/store/3lq0fkjmjb917asbj9f24vcxxnq3kwai-attr-2.4.46.drv" [color = red];
|
||||
"/gnu/store/a076d7ng0h3ynr1hsiyk4fmh3w1g4cv8-gettext-0.19.6.drv" [label = "gettext-0.19.6", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/a076d7ng0h3ynr1hsiyk4fmh3w1g4cv8-gettext-0.19.6.drv" -> "/gnu/store/0pr679inn5xj91z4d63scc7vgfji9vpp-tar-1.28.drv" [color = red];
|
||||
"/gnu/store/a076d7ng0h3ynr1hsiyk4fmh3w1g4cv8-gettext-0.19.6.drv" -> "/gnu/store/p3szkb87bp9fxhn715g88skry8g3jgkq-gzip-1.6.drv" [color = red];
|
||||
"/gnu/store/a076d7ng0h3ynr1hsiyk4fmh3w1g4cv8-gettext-0.19.6.drv" -> "/gnu/store/i398qn04cwvnzph7a0cckxqr9q0k3lyr-bzip2-1.0.6.drv" [color = red];
|
||||
"/gnu/store/a076d7ng0h3ynr1hsiyk4fmh3w1g4cv8-gettext-0.19.6.drv" -> "/gnu/store/wvnnsn89magnvn39zm3fv245s9m7yn5f-xz-5.0.4.drv" [color = red];
|
||||
"/gnu/store/a076d7ng0h3ynr1hsiyk4fmh3w1g4cv8-gettext-0.19.6.drv" -> "/gnu/store/sag0sx1zycnwixwfdrxwj1i9g2phxrh4-file-5.22.drv" [color = red];
|
||||
"/gnu/store/a076d7ng0h3ynr1hsiyk4fmh3w1g4cv8-gettext-0.19.6.drv" -> "/gnu/store/p61bsw6093x3wfg5vz3172wl9bzrlc3w-diffutils-3.3.drv" [color = red];
|
||||
"/gnu/store/a076d7ng0h3ynr1hsiyk4fmh3w1g4cv8-gettext-0.19.6.drv" -> "/gnu/store/rzsyx70vnfb8cm40r0b591vyvww2i5y6-patch-2.7.5.drv" [color = red];
|
||||
"/gnu/store/a076d7ng0h3ynr1hsiyk4fmh3w1g4cv8-gettext-0.19.6.drv" -> "/gnu/store/mc5fgclyr0v26242hmg30srv9ij27wyv-sed-4.2.2.drv" [color = red];
|
||||
"/gnu/store/a076d7ng0h3ynr1hsiyk4fmh3w1g4cv8-gettext-0.19.6.drv" -> "/gnu/store/ig9nr2f5hvr88br028r9nsdg4xpmmybg-findutils-4.4.2.drv" [color = red];
|
||||
"/gnu/store/a076d7ng0h3ynr1hsiyk4fmh3w1g4cv8-gettext-0.19.6.drv" -> "/gnu/store/jls1kj3pvqjpbmm7c09fhszfd3m61zif-gawk-4.1.3.drv" [color = red];
|
||||
"/gnu/store/a076d7ng0h3ynr1hsiyk4fmh3w1g4cv8-gettext-0.19.6.drv" -> "/gnu/store/vvlh6szjxr5iy192fsv9p4dwf39nhapf-grep-2.21.drv" [color = red];
|
||||
"/gnu/store/a076d7ng0h3ynr1hsiyk4fmh3w1g4cv8-gettext-0.19.6.drv" -> "/gnu/store/mysb2grsl1wc931xm08adncnqjwvdds7-coreutils-8.24.drv" [color = red];
|
||||
"/gnu/store/a076d7ng0h3ynr1hsiyk4fmh3w1g4cv8-gettext-0.19.6.drv" -> "/gnu/store/n0n20i1brmhmjvw9lx33f2l3dmzx873n-make-4.1.drv" [color = red];
|
||||
"/gnu/store/a076d7ng0h3ynr1hsiyk4fmh3w1g4cv8-gettext-0.19.6.drv" -> "/gnu/store/64cizlhq38x99dvjvza6c5ha226a9bf5-bash-4.3.39.drv" [color = red];
|
||||
"/gnu/store/a076d7ng0h3ynr1hsiyk4fmh3w1g4cv8-gettext-0.19.6.drv" -> "/gnu/store/mbshnjz590h3l1c3y2rxzqvn45bhx32b-ld-wrapper-0.drv" [color = red];
|
||||
"/gnu/store/a076d7ng0h3ynr1hsiyk4fmh3w1g4cv8-gettext-0.19.6.drv" -> "/gnu/store/hf62yhvyrr1rm5y8mq5afih12s9jasic-binutils-2.25.1.drv" [color = red];
|
||||
"/gnu/store/a076d7ng0h3ynr1hsiyk4fmh3w1g4cv8-gettext-0.19.6.drv" -> "/gnu/store/8mff0w2203h6m5s495knxg09is3qj15f-gcc-4.9.3.drv" [color = red];
|
||||
"/gnu/store/a076d7ng0h3ynr1hsiyk4fmh3w1g4cv8-gettext-0.19.6.drv" -> "/gnu/store/2pspbpclj4yq5dqd71fnqwa69s8xxryf-glibc-2.22.drv" [color = red];
|
||||
"/gnu/store/a076d7ng0h3ynr1hsiyk4fmh3w1g4cv8-gettext-0.19.6.drv" -> "/gnu/store/nflynk1n90yh41yfi91raczynka2mf86-glibc-utf8-locales-2.22.drv" [color = red];
|
||||
"/gnu/store/a076d7ng0h3ynr1hsiyk4fmh3w1g4cv8-gettext-0.19.6.drv" -> "/gnu/store/n3ix2bl79ijv1v1winwf4qj46hlhyrdv-expat-2.1.0.drv" [color = red];
|
||||
"/gnu/store/n3ix2bl79ijv1v1winwf4qj46hlhyrdv-expat-2.1.0.drv" [label = "expat-2.1.0", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/n3ix2bl79ijv1v1winwf4qj46hlhyrdv-expat-2.1.0.drv" -> "/gnu/store/0pr679inn5xj91z4d63scc7vgfji9vpp-tar-1.28.drv" [color = red];
|
||||
"/gnu/store/n3ix2bl79ijv1v1winwf4qj46hlhyrdv-expat-2.1.0.drv" -> "/gnu/store/p3szkb87bp9fxhn715g88skry8g3jgkq-gzip-1.6.drv" [color = red];
|
||||
"/gnu/store/n3ix2bl79ijv1v1winwf4qj46hlhyrdv-expat-2.1.0.drv" -> "/gnu/store/i398qn04cwvnzph7a0cckxqr9q0k3lyr-bzip2-1.0.6.drv" [color = red];
|
||||
"/gnu/store/n3ix2bl79ijv1v1winwf4qj46hlhyrdv-expat-2.1.0.drv" -> "/gnu/store/wvnnsn89magnvn39zm3fv245s9m7yn5f-xz-5.0.4.drv" [color = red];
|
||||
"/gnu/store/n3ix2bl79ijv1v1winwf4qj46hlhyrdv-expat-2.1.0.drv" -> "/gnu/store/sag0sx1zycnwixwfdrxwj1i9g2phxrh4-file-5.22.drv" [color = red];
|
||||
"/gnu/store/n3ix2bl79ijv1v1winwf4qj46hlhyrdv-expat-2.1.0.drv" -> "/gnu/store/p61bsw6093x3wfg5vz3172wl9bzrlc3w-diffutils-3.3.drv" [color = red];
|
||||
"/gnu/store/n3ix2bl79ijv1v1winwf4qj46hlhyrdv-expat-2.1.0.drv" -> "/gnu/store/rzsyx70vnfb8cm40r0b591vyvww2i5y6-patch-2.7.5.drv" [color = red];
|
||||
"/gnu/store/n3ix2bl79ijv1v1winwf4qj46hlhyrdv-expat-2.1.0.drv" -> "/gnu/store/mc5fgclyr0v26242hmg30srv9ij27wyv-sed-4.2.2.drv" [color = red];
|
||||
"/gnu/store/n3ix2bl79ijv1v1winwf4qj46hlhyrdv-expat-2.1.0.drv" -> "/gnu/store/ig9nr2f5hvr88br028r9nsdg4xpmmybg-findutils-4.4.2.drv" [color = red];
|
||||
"/gnu/store/n3ix2bl79ijv1v1winwf4qj46hlhyrdv-expat-2.1.0.drv" -> "/gnu/store/jls1kj3pvqjpbmm7c09fhszfd3m61zif-gawk-4.1.3.drv" [color = red];
|
||||
"/gnu/store/n3ix2bl79ijv1v1winwf4qj46hlhyrdv-expat-2.1.0.drv" -> "/gnu/store/vvlh6szjxr5iy192fsv9p4dwf39nhapf-grep-2.21.drv" [color = red];
|
||||
"/gnu/store/n3ix2bl79ijv1v1winwf4qj46hlhyrdv-expat-2.1.0.drv" -> "/gnu/store/mysb2grsl1wc931xm08adncnqjwvdds7-coreutils-8.24.drv" [color = red];
|
||||
"/gnu/store/n3ix2bl79ijv1v1winwf4qj46hlhyrdv-expat-2.1.0.drv" -> "/gnu/store/n0n20i1brmhmjvw9lx33f2l3dmzx873n-make-4.1.drv" [color = red];
|
||||
"/gnu/store/n3ix2bl79ijv1v1winwf4qj46hlhyrdv-expat-2.1.0.drv" -> "/gnu/store/64cizlhq38x99dvjvza6c5ha226a9bf5-bash-4.3.39.drv" [color = red];
|
||||
"/gnu/store/n3ix2bl79ijv1v1winwf4qj46hlhyrdv-expat-2.1.0.drv" -> "/gnu/store/mbshnjz590h3l1c3y2rxzqvn45bhx32b-ld-wrapper-0.drv" [color = red];
|
||||
"/gnu/store/n3ix2bl79ijv1v1winwf4qj46hlhyrdv-expat-2.1.0.drv" -> "/gnu/store/hf62yhvyrr1rm5y8mq5afih12s9jasic-binutils-2.25.1.drv" [color = red];
|
||||
"/gnu/store/n3ix2bl79ijv1v1winwf4qj46hlhyrdv-expat-2.1.0.drv" -> "/gnu/store/8mff0w2203h6m5s495knxg09is3qj15f-gcc-4.9.3.drv" [color = red];
|
||||
"/gnu/store/n3ix2bl79ijv1v1winwf4qj46hlhyrdv-expat-2.1.0.drv" -> "/gnu/store/2pspbpclj4yq5dqd71fnqwa69s8xxryf-glibc-2.22.drv" [color = red];
|
||||
"/gnu/store/n3ix2bl79ijv1v1winwf4qj46hlhyrdv-expat-2.1.0.drv" -> "/gnu/store/nflynk1n90yh41yfi91raczynka2mf86-glibc-utf8-locales-2.22.drv" [color = red];
|
||||
"/gnu/store/3lq0fkjmjb917asbj9f24vcxxnq3kwai-attr-2.4.46.drv" [label = "attr-2.4.46", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/3lq0fkjmjb917asbj9f24vcxxnq3kwai-attr-2.4.46.drv" -> "/gnu/store/a076d7ng0h3ynr1hsiyk4fmh3w1g4cv8-gettext-0.19.6.drv" [color = red];
|
||||
"/gnu/store/3lq0fkjmjb917asbj9f24vcxxnq3kwai-attr-2.4.46.drv" -> "/gnu/store/0pr679inn5xj91z4d63scc7vgfji9vpp-tar-1.28.drv" [color = red];
|
||||
"/gnu/store/3lq0fkjmjb917asbj9f24vcxxnq3kwai-attr-2.4.46.drv" -> "/gnu/store/p3szkb87bp9fxhn715g88skry8g3jgkq-gzip-1.6.drv" [color = red];
|
||||
"/gnu/store/3lq0fkjmjb917asbj9f24vcxxnq3kwai-attr-2.4.46.drv" -> "/gnu/store/i398qn04cwvnzph7a0cckxqr9q0k3lyr-bzip2-1.0.6.drv" [color = red];
|
||||
"/gnu/store/3lq0fkjmjb917asbj9f24vcxxnq3kwai-attr-2.4.46.drv" -> "/gnu/store/wvnnsn89magnvn39zm3fv245s9m7yn5f-xz-5.0.4.drv" [color = red];
|
||||
"/gnu/store/3lq0fkjmjb917asbj9f24vcxxnq3kwai-attr-2.4.46.drv" -> "/gnu/store/sag0sx1zycnwixwfdrxwj1i9g2phxrh4-file-5.22.drv" [color = red];
|
||||
"/gnu/store/3lq0fkjmjb917asbj9f24vcxxnq3kwai-attr-2.4.46.drv" -> "/gnu/store/p61bsw6093x3wfg5vz3172wl9bzrlc3w-diffutils-3.3.drv" [color = red];
|
||||
"/gnu/store/3lq0fkjmjb917asbj9f24vcxxnq3kwai-attr-2.4.46.drv" -> "/gnu/store/rzsyx70vnfb8cm40r0b591vyvww2i5y6-patch-2.7.5.drv" [color = red];
|
||||
"/gnu/store/3lq0fkjmjb917asbj9f24vcxxnq3kwai-attr-2.4.46.drv" -> "/gnu/store/mc5fgclyr0v26242hmg30srv9ij27wyv-sed-4.2.2.drv" [color = red];
|
||||
"/gnu/store/3lq0fkjmjb917asbj9f24vcxxnq3kwai-attr-2.4.46.drv" -> "/gnu/store/ig9nr2f5hvr88br028r9nsdg4xpmmybg-findutils-4.4.2.drv" [color = red];
|
||||
"/gnu/store/3lq0fkjmjb917asbj9f24vcxxnq3kwai-attr-2.4.46.drv" -> "/gnu/store/jls1kj3pvqjpbmm7c09fhszfd3m61zif-gawk-4.1.3.drv" [color = red];
|
||||
"/gnu/store/3lq0fkjmjb917asbj9f24vcxxnq3kwai-attr-2.4.46.drv" -> "/gnu/store/vvlh6szjxr5iy192fsv9p4dwf39nhapf-grep-2.21.drv" [color = red];
|
||||
"/gnu/store/3lq0fkjmjb917asbj9f24vcxxnq3kwai-attr-2.4.46.drv" -> "/gnu/store/mysb2grsl1wc931xm08adncnqjwvdds7-coreutils-8.24.drv" [color = red];
|
||||
"/gnu/store/3lq0fkjmjb917asbj9f24vcxxnq3kwai-attr-2.4.46.drv" -> "/gnu/store/n0n20i1brmhmjvw9lx33f2l3dmzx873n-make-4.1.drv" [color = red];
|
||||
"/gnu/store/3lq0fkjmjb917asbj9f24vcxxnq3kwai-attr-2.4.46.drv" -> "/gnu/store/64cizlhq38x99dvjvza6c5ha226a9bf5-bash-4.3.39.drv" [color = red];
|
||||
"/gnu/store/3lq0fkjmjb917asbj9f24vcxxnq3kwai-attr-2.4.46.drv" -> "/gnu/store/mbshnjz590h3l1c3y2rxzqvn45bhx32b-ld-wrapper-0.drv" [color = red];
|
||||
"/gnu/store/3lq0fkjmjb917asbj9f24vcxxnq3kwai-attr-2.4.46.drv" -> "/gnu/store/hf62yhvyrr1rm5y8mq5afih12s9jasic-binutils-2.25.1.drv" [color = red];
|
||||
"/gnu/store/3lq0fkjmjb917asbj9f24vcxxnq3kwai-attr-2.4.46.drv" -> "/gnu/store/8mff0w2203h6m5s495knxg09is3qj15f-gcc-4.9.3.drv" [color = red];
|
||||
"/gnu/store/3lq0fkjmjb917asbj9f24vcxxnq3kwai-attr-2.4.46.drv" -> "/gnu/store/2pspbpclj4yq5dqd71fnqwa69s8xxryf-glibc-2.22.drv" [color = red];
|
||||
"/gnu/store/3lq0fkjmjb917asbj9f24vcxxnq3kwai-attr-2.4.46.drv" -> "/gnu/store/nflynk1n90yh41yfi91raczynka2mf86-glibc-utf8-locales-2.22.drv" [color = red];
|
||||
"/gnu/store/3lq0fkjmjb917asbj9f24vcxxnq3kwai-attr-2.4.46.drv" -> "/gnu/store/mi4a8m41ssrp7lv3b8vibw0a7ahv2mmg-perl-5.16.1.drv" [color = red];
|
||||
"/gnu/store/wmvpskqsw6hgriy0vbmmm6c4wp8rxp2c-gmp-6.0.0a.drv" [label = "gmp-6.0.0a", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/wmvpskqsw6hgriy0vbmmm6c4wp8rxp2c-gmp-6.0.0a.drv" -> "/gnu/store/1mwk0rc4lfcy3vax50ss8x3qfa304g67-m4-1.4.17.drv" [color = red];
|
||||
"/gnu/store/wmvpskqsw6hgriy0vbmmm6c4wp8rxp2c-gmp-6.0.0a.drv" -> "/gnu/store/0pr679inn5xj91z4d63scc7vgfji9vpp-tar-1.28.drv" [color = red];
|
||||
"/gnu/store/wmvpskqsw6hgriy0vbmmm6c4wp8rxp2c-gmp-6.0.0a.drv" -> "/gnu/store/p3szkb87bp9fxhn715g88skry8g3jgkq-gzip-1.6.drv" [color = red];
|
||||
"/gnu/store/wmvpskqsw6hgriy0vbmmm6c4wp8rxp2c-gmp-6.0.0a.drv" -> "/gnu/store/i398qn04cwvnzph7a0cckxqr9q0k3lyr-bzip2-1.0.6.drv" [color = red];
|
||||
"/gnu/store/wmvpskqsw6hgriy0vbmmm6c4wp8rxp2c-gmp-6.0.0a.drv" -> "/gnu/store/wvnnsn89magnvn39zm3fv245s9m7yn5f-xz-5.0.4.drv" [color = red];
|
||||
"/gnu/store/wmvpskqsw6hgriy0vbmmm6c4wp8rxp2c-gmp-6.0.0a.drv" -> "/gnu/store/sag0sx1zycnwixwfdrxwj1i9g2phxrh4-file-5.22.drv" [color = red];
|
||||
"/gnu/store/wmvpskqsw6hgriy0vbmmm6c4wp8rxp2c-gmp-6.0.0a.drv" -> "/gnu/store/p61bsw6093x3wfg5vz3172wl9bzrlc3w-diffutils-3.3.drv" [color = red];
|
||||
"/gnu/store/wmvpskqsw6hgriy0vbmmm6c4wp8rxp2c-gmp-6.0.0a.drv" -> "/gnu/store/rzsyx70vnfb8cm40r0b591vyvww2i5y6-patch-2.7.5.drv" [color = red];
|
||||
"/gnu/store/wmvpskqsw6hgriy0vbmmm6c4wp8rxp2c-gmp-6.0.0a.drv" -> "/gnu/store/mc5fgclyr0v26242hmg30srv9ij27wyv-sed-4.2.2.drv" [color = red];
|
||||
"/gnu/store/wmvpskqsw6hgriy0vbmmm6c4wp8rxp2c-gmp-6.0.0a.drv" -> "/gnu/store/ig9nr2f5hvr88br028r9nsdg4xpmmybg-findutils-4.4.2.drv" [color = red];
|
||||
"/gnu/store/wmvpskqsw6hgriy0vbmmm6c4wp8rxp2c-gmp-6.0.0a.drv" -> "/gnu/store/jls1kj3pvqjpbmm7c09fhszfd3m61zif-gawk-4.1.3.drv" [color = red];
|
||||
"/gnu/store/wmvpskqsw6hgriy0vbmmm6c4wp8rxp2c-gmp-6.0.0a.drv" -> "/gnu/store/vvlh6szjxr5iy192fsv9p4dwf39nhapf-grep-2.21.drv" [color = red];
|
||||
"/gnu/store/wmvpskqsw6hgriy0vbmmm6c4wp8rxp2c-gmp-6.0.0a.drv" -> "/gnu/store/mysb2grsl1wc931xm08adncnqjwvdds7-coreutils-8.24.drv" [color = red];
|
||||
"/gnu/store/wmvpskqsw6hgriy0vbmmm6c4wp8rxp2c-gmp-6.0.0a.drv" -> "/gnu/store/n0n20i1brmhmjvw9lx33f2l3dmzx873n-make-4.1.drv" [color = red];
|
||||
"/gnu/store/wmvpskqsw6hgriy0vbmmm6c4wp8rxp2c-gmp-6.0.0a.drv" -> "/gnu/store/64cizlhq38x99dvjvza6c5ha226a9bf5-bash-4.3.39.drv" [color = red];
|
||||
"/gnu/store/wmvpskqsw6hgriy0vbmmm6c4wp8rxp2c-gmp-6.0.0a.drv" -> "/gnu/store/mbshnjz590h3l1c3y2rxzqvn45bhx32b-ld-wrapper-0.drv" [color = red];
|
||||
"/gnu/store/wmvpskqsw6hgriy0vbmmm6c4wp8rxp2c-gmp-6.0.0a.drv" -> "/gnu/store/hf62yhvyrr1rm5y8mq5afih12s9jasic-binutils-2.25.1.drv" [color = red];
|
||||
"/gnu/store/wmvpskqsw6hgriy0vbmmm6c4wp8rxp2c-gmp-6.0.0a.drv" -> "/gnu/store/8mff0w2203h6m5s495knxg09is3qj15f-gcc-4.9.3.drv" [color = red];
|
||||
"/gnu/store/wmvpskqsw6hgriy0vbmmm6c4wp8rxp2c-gmp-6.0.0a.drv" -> "/gnu/store/2pspbpclj4yq5dqd71fnqwa69s8xxryf-glibc-2.22.drv" [color = red];
|
||||
"/gnu/store/wmvpskqsw6hgriy0vbmmm6c4wp8rxp2c-gmp-6.0.0a.drv" -> "/gnu/store/nflynk1n90yh41yfi91raczynka2mf86-glibc-utf8-locales-2.22.drv" [color = red];
|
||||
"/gnu/store/1mwk0rc4lfcy3vax50ss8x3qfa304g67-m4-1.4.17.drv" [label = "m4-1.4.17", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/1mwk0rc4lfcy3vax50ss8x3qfa304g67-m4-1.4.17.drv" -> "/gnu/store/0pr679inn5xj91z4d63scc7vgfji9vpp-tar-1.28.drv" [color = red];
|
||||
"/gnu/store/1mwk0rc4lfcy3vax50ss8x3qfa304g67-m4-1.4.17.drv" -> "/gnu/store/p3szkb87bp9fxhn715g88skry8g3jgkq-gzip-1.6.drv" [color = red];
|
||||
"/gnu/store/1mwk0rc4lfcy3vax50ss8x3qfa304g67-m4-1.4.17.drv" -> "/gnu/store/i398qn04cwvnzph7a0cckxqr9q0k3lyr-bzip2-1.0.6.drv" [color = red];
|
||||
"/gnu/store/1mwk0rc4lfcy3vax50ss8x3qfa304g67-m4-1.4.17.drv" -> "/gnu/store/wvnnsn89magnvn39zm3fv245s9m7yn5f-xz-5.0.4.drv" [color = red];
|
||||
"/gnu/store/1mwk0rc4lfcy3vax50ss8x3qfa304g67-m4-1.4.17.drv" -> "/gnu/store/sag0sx1zycnwixwfdrxwj1i9g2phxrh4-file-5.22.drv" [color = red];
|
||||
"/gnu/store/1mwk0rc4lfcy3vax50ss8x3qfa304g67-m4-1.4.17.drv" -> "/gnu/store/p61bsw6093x3wfg5vz3172wl9bzrlc3w-diffutils-3.3.drv" [color = red];
|
||||
"/gnu/store/1mwk0rc4lfcy3vax50ss8x3qfa304g67-m4-1.4.17.drv" -> "/gnu/store/rzsyx70vnfb8cm40r0b591vyvww2i5y6-patch-2.7.5.drv" [color = red];
|
||||
"/gnu/store/1mwk0rc4lfcy3vax50ss8x3qfa304g67-m4-1.4.17.drv" -> "/gnu/store/mc5fgclyr0v26242hmg30srv9ij27wyv-sed-4.2.2.drv" [color = red];
|
||||
"/gnu/store/1mwk0rc4lfcy3vax50ss8x3qfa304g67-m4-1.4.17.drv" -> "/gnu/store/ig9nr2f5hvr88br028r9nsdg4xpmmybg-findutils-4.4.2.drv" [color = red];
|
||||
"/gnu/store/1mwk0rc4lfcy3vax50ss8x3qfa304g67-m4-1.4.17.drv" -> "/gnu/store/jls1kj3pvqjpbmm7c09fhszfd3m61zif-gawk-4.1.3.drv" [color = red];
|
||||
"/gnu/store/1mwk0rc4lfcy3vax50ss8x3qfa304g67-m4-1.4.17.drv" -> "/gnu/store/vvlh6szjxr5iy192fsv9p4dwf39nhapf-grep-2.21.drv" [color = red];
|
||||
"/gnu/store/1mwk0rc4lfcy3vax50ss8x3qfa304g67-m4-1.4.17.drv" -> "/gnu/store/mysb2grsl1wc931xm08adncnqjwvdds7-coreutils-8.24.drv" [color = red];
|
||||
"/gnu/store/1mwk0rc4lfcy3vax50ss8x3qfa304g67-m4-1.4.17.drv" -> "/gnu/store/n0n20i1brmhmjvw9lx33f2l3dmzx873n-make-4.1.drv" [color = red];
|
||||
"/gnu/store/1mwk0rc4lfcy3vax50ss8x3qfa304g67-m4-1.4.17.drv" -> "/gnu/store/64cizlhq38x99dvjvza6c5ha226a9bf5-bash-4.3.39.drv" [color = red];
|
||||
"/gnu/store/1mwk0rc4lfcy3vax50ss8x3qfa304g67-m4-1.4.17.drv" -> "/gnu/store/mbshnjz590h3l1c3y2rxzqvn45bhx32b-ld-wrapper-0.drv" [color = red];
|
||||
"/gnu/store/1mwk0rc4lfcy3vax50ss8x3qfa304g67-m4-1.4.17.drv" -> "/gnu/store/hf62yhvyrr1rm5y8mq5afih12s9jasic-binutils-2.25.1.drv" [color = red];
|
||||
"/gnu/store/1mwk0rc4lfcy3vax50ss8x3qfa304g67-m4-1.4.17.drv" -> "/gnu/store/8mff0w2203h6m5s495knxg09is3qj15f-gcc-4.9.3.drv" [color = red];
|
||||
"/gnu/store/1mwk0rc4lfcy3vax50ss8x3qfa304g67-m4-1.4.17.drv" -> "/gnu/store/2pspbpclj4yq5dqd71fnqwa69s8xxryf-glibc-2.22.drv" [color = red];
|
||||
"/gnu/store/1mwk0rc4lfcy3vax50ss8x3qfa304g67-m4-1.4.17.drv" -> "/gnu/store/nflynk1n90yh41yfi91raczynka2mf86-glibc-utf8-locales-2.22.drv" [color = red];
|
||||
"/gnu/store/d7d6k5bhk7gz3pvhxdn2f33jzlxg4c5l-libcap-2.24.drv" [label = "libcap-2.24", shape = box, fontname = Helvetica];
|
||||
"/gnu/store/d7d6k5bhk7gz3pvhxdn2f33jzlxg4c5l-libcap-2.24.drv" -> "/gnu/store/mi4a8m41ssrp7lv3b8vibw0a7ahv2mmg-perl-5.16.1.drv" [color = red];
|
||||
"/gnu/store/d7d6k5bhk7gz3pvhxdn2f33jzlxg4c5l-libcap-2.24.drv" -> "/gnu/store/0pr679inn5xj91z4d63scc7vgfji9vpp-tar-1.28.drv" [color = red];
|
||||
"/gnu/store/d7d6k5bhk7gz3pvhxdn2f33jzlxg4c5l-libcap-2.24.drv" -> "/gnu/store/p3szkb87bp9fxhn715g88skry8g3jgkq-gzip-1.6.drv" [color = red];
|
||||
"/gnu/store/d7d6k5bhk7gz3pvhxdn2f33jzlxg4c5l-libcap-2.24.drv" -> "/gnu/store/i398qn04cwvnzph7a0cckxqr9q0k3lyr-bzip2-1.0.6.drv" [color = red];
|
||||
"/gnu/store/d7d6k5bhk7gz3pvhxdn2f33jzlxg4c5l-libcap-2.24.drv" -> "/gnu/store/wvnnsn89magnvn39zm3fv245s9m7yn5f-xz-5.0.4.drv" [color = red];
|
||||
"/gnu/store/d7d6k5bhk7gz3pvhxdn2f33jzlxg4c5l-libcap-2.24.drv" -> "/gnu/store/sag0sx1zycnwixwfdrxwj1i9g2phxrh4-file-5.22.drv" [color = red];
|
||||
"/gnu/store/d7d6k5bhk7gz3pvhxdn2f33jzlxg4c5l-libcap-2.24.drv" -> "/gnu/store/p61bsw6093x3wfg5vz3172wl9bzrlc3w-diffutils-3.3.drv" [color = red];
|
||||
"/gnu/store/d7d6k5bhk7gz3pvhxdn2f33jzlxg4c5l-libcap-2.24.drv" -> "/gnu/store/rzsyx70vnfb8cm40r0b591vyvww2i5y6-patch-2.7.5.drv" [color = red];
|
||||
"/gnu/store/d7d6k5bhk7gz3pvhxdn2f33jzlxg4c5l-libcap-2.24.drv" -> "/gnu/store/mc5fgclyr0v26242hmg30srv9ij27wyv-sed-4.2.2.drv" [color = red];
|
||||
"/gnu/store/d7d6k5bhk7gz3pvhxdn2f33jzlxg4c5l-libcap-2.24.drv" -> "/gnu/store/ig9nr2f5hvr88br028r9nsdg4xpmmybg-findutils-4.4.2.drv" [color = red];
|
||||
"/gnu/store/d7d6k5bhk7gz3pvhxdn2f33jzlxg4c5l-libcap-2.24.drv" -> "/gnu/store/jls1kj3pvqjpbmm7c09fhszfd3m61zif-gawk-4.1.3.drv" [color = red];
|
||||
"/gnu/store/d7d6k5bhk7gz3pvhxdn2f33jzlxg4c5l-libcap-2.24.drv" -> "/gnu/store/vvlh6szjxr5iy192fsv9p4dwf39nhapf-grep-2.21.drv" [color = red];
|
||||
"/gnu/store/d7d6k5bhk7gz3pvhxdn2f33jzlxg4c5l-libcap-2.24.drv" -> "/gnu/store/mysb2grsl1wc931xm08adncnqjwvdds7-coreutils-8.24.drv" [color = red];
|
||||
"/gnu/store/d7d6k5bhk7gz3pvhxdn2f33jzlxg4c5l-libcap-2.24.drv" -> "/gnu/store/n0n20i1brmhmjvw9lx33f2l3dmzx873n-make-4.1.drv" [color = red];
|
||||
"/gnu/store/d7d6k5bhk7gz3pvhxdn2f33jzlxg4c5l-libcap-2.24.drv" -> "/gnu/store/64cizlhq38x99dvjvza6c5ha226a9bf5-bash-4.3.39.drv" [color = red];
|
||||
"/gnu/store/d7d6k5bhk7gz3pvhxdn2f33jzlxg4c5l-libcap-2.24.drv" -> "/gnu/store/mbshnjz590h3l1c3y2rxzqvn45bhx32b-ld-wrapper-0.drv" [color = red];
|
||||
"/gnu/store/d7d6k5bhk7gz3pvhxdn2f33jzlxg4c5l-libcap-2.24.drv" -> "/gnu/store/hf62yhvyrr1rm5y8mq5afih12s9jasic-binutils-2.25.1.drv" [color = red];
|
||||
"/gnu/store/d7d6k5bhk7gz3pvhxdn2f33jzlxg4c5l-libcap-2.24.drv" -> "/gnu/store/8mff0w2203h6m5s495knxg09is3qj15f-gcc-4.9.3.drv" [color = red];
|
||||
"/gnu/store/d7d6k5bhk7gz3pvhxdn2f33jzlxg4c5l-libcap-2.24.drv" -> "/gnu/store/2pspbpclj4yq5dqd71fnqwa69s8xxryf-glibc-2.22.drv" [color = red];
|
||||
"/gnu/store/d7d6k5bhk7gz3pvhxdn2f33jzlxg4c5l-libcap-2.24.drv" -> "/gnu/store/nflynk1n90yh41yfi91raczynka2mf86-glibc-utf8-locales-2.22.drv" [color = red];
|
||||
"/gnu/store/d7d6k5bhk7gz3pvhxdn2f33jzlxg4c5l-libcap-2.24.drv" -> "/gnu/store/3lq0fkjmjb917asbj9f24vcxxnq3kwai-attr-2.4.46.drv" [color = red];
|
||||
|
||||
}
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
digraph "Guix package" {
|
||||
"72851008" [label = "coreutils-8.25", shape = box, fontname = Helvetica];
|
||||
"72851008" -> "49728512" [color = darkseagreen];
|
||||
"72851008" -> "74872512" [color = darkseagreen];
|
||||
"72851008" -> "53180864" [color = darkseagreen];
|
||||
"72851008" -> "75199232" [color = darkseagreen];
|
||||
"49728512" [label = "perl-5.24.0", shape = box, fontname = Helvetica];
|
||||
"74872512" [label = "acl-2.2.52", shape = box, fontname = Helvetica];
|
||||
"74872512" -> "74873280" [color = red];
|
||||
"74872512" -> "49728512" [color = red];
|
||||
"74872512" -> "74872704" [color = red];
|
||||
"74873280" [label = "gettext-minimal-0.19.8.1", shape = box, fontname = Helvetica];
|
||||
"74873280" -> "41550784" [color = cyan3];
|
||||
"41550784" [label = "expat-2.2.0", shape = box, fontname = Helvetica];
|
||||
"74872704" [label = "attr-2.4.47", shape = box, fontname = Helvetica];
|
||||
"74872704" -> "74873280" [color = cyan3];
|
||||
"74872704" -> "49728512" [color = cyan3];
|
||||
"53180864" [label = "gmp-6.1.1", shape = box, fontname = Helvetica];
|
||||
"53180864" -> "50262784" [color = darkgoldenrod];
|
||||
"50262784" [label = "m4-1.4.17", shape = box, fontname = Helvetica];
|
||||
"75199232" [label = "libcap-2.24", shape = box, fontname = Helvetica];
|
||||
"75199232" -> "49728512" [color = blue];
|
||||
"75199232" -> "74872704" [color = blue];
|
||||
"70481600" [label = "coreutils-8.24", shape = box, fontname = Helvetica];
|
||||
"70481600" -> "50717824" [color = red];
|
||||
"70481600" -> "57499200" [color = red];
|
||||
"70481600" -> "57496320" [color = red];
|
||||
"70481600" -> "69877504" [color = red];
|
||||
"50717824" [label = "perl-5.16.1", shape = box, fontname = Helvetica];
|
||||
"57499200" [label = "acl-2.2.52", shape = box, fontname = Helvetica];
|
||||
"57499200" -> "70563904" [color = red];
|
||||
"57499200" -> "50717824" [color = red];
|
||||
"57499200" -> "70563520" [color = red];
|
||||
"70563904" [label = "gettext-0.19.6", shape = box, fontname = Helvetica];
|
||||
"70563904" -> "69316352" [color = red];
|
||||
"69316352" [label = "expat-2.1.0", shape = box, fontname = Helvetica];
|
||||
"70563520" [label = "attr-2.4.46", shape = box, fontname = Helvetica];
|
||||
"70563520" -> "70563904" [color = red];
|
||||
"70563520" -> "50717824" [color = red];
|
||||
"57496320" [label = "gmp-6.0.0a", shape = box, fontname = Helvetica];
|
||||
"57496320" -> "57498432" [color = red];
|
||||
"57498432" [label = "m4-1.4.17", shape = box, fontname = Helvetica];
|
||||
"69877504" [label = "libcap-2.24", shape = box, fontname = Helvetica];
|
||||
"69877504" -> "50717824" [color = red];
|
||||
"69877504" -> "70563520" [color = red];
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
digraph "Guix dmd-service" {
|
||||
"user-file-systems" [label = "user-file-systems", shape = box, fontname = Helvetica];
|
||||
"user-processes" -> "user-file-systems" [color = red];
|
||||
"user-processes" [label = "user-processes", shape = box, fontname = Helvetica];
|
||||
"nscd" -> "user-processes" [color = red];
|
||||
"guix-daemon" -> "user-processes" [color = red];
|
||||
"syslogd" -> "user-processes" [color = red];
|
||||
"term-tty6" -> "user-processes" [color = red];
|
||||
"term-tty5" -> "user-processes" [color = red];
|
||||
"term-tty4" -> "user-processes" [color = red];
|
||||
"term-tty3" -> "user-processes" [color = red];
|
||||
"term-tty2" -> "user-processes" [color = red];
|
||||
"term-tty1" -> "user-processes" [color = red];
|
||||
"networking" -> "user-processes" [color = red];
|
||||
"nscd" [label = "nscd", shape = box, fontname = Helvetica];
|
||||
"guix-daemon" [label = "guix-daemon", shape = box, fontname = Helvetica];
|
||||
"syslogd" [label = "syslogd", shape = box, fontname = Helvetica];
|
||||
"ssh-daemon" -> "syslogd" [color = red];
|
||||
"ssh-daemon" [label = "ssh-daemon", shape = box, fontname = Helvetica];
|
||||
"term-tty6" [label = "term-tty6", shape = box, fontname = Helvetica];
|
||||
"console-font-tty6" -> "term-tty6" [color = red];
|
||||
"console-font-tty6" [label = "console-font-tty6", shape = box, fontname = Helvetica];
|
||||
"term-tty5" [label = "term-tty5", shape = box, fontname = Helvetica];
|
||||
"console-font-tty5" -> "term-tty5" [color = red];
|
||||
"console-font-tty5" [label = "console-font-tty5", shape = box, fontname = Helvetica];
|
||||
"term-tty4" [label = "term-tty4", shape = box, fontname = Helvetica];
|
||||
"console-font-tty4" -> "term-tty4" [color = red];
|
||||
"console-font-tty4" [label = "console-font-tty4", shape = box, fontname = Helvetica];
|
||||
"term-tty3" [label = "term-tty3", shape = box, fontname = Helvetica];
|
||||
"console-font-tty3" -> "term-tty3" [color = red];
|
||||
"console-font-tty3" [label = "console-font-tty3", shape = box, fontname = Helvetica];
|
||||
"term-tty2" [label = "term-tty2", shape = box, fontname = Helvetica];
|
||||
"console-font-tty2" -> "term-tty2" [color = red];
|
||||
"console-font-tty2" [label = "console-font-tty2", shape = box, fontname = Helvetica];
|
||||
"term-tty1" [label = "term-tty1", shape = box, fontname = Helvetica];
|
||||
"console-font-tty1" -> "term-tty1" [color = red];
|
||||
"console-font-tty1" [label = "console-font-tty1", shape = box, fontname = Helvetica];
|
||||
"networking" [label = "networking", shape = box, fontname = Helvetica];
|
||||
"ssh-daemon" -> "networking" [color = red];
|
||||
"root-file-system" [label = "root-file-system", shape = box, fontname = Helvetica];
|
||||
"file-system-/run/user" -> "root-file-system" [color = red];
|
||||
"file-system-/run/systemd" -> "root-file-system" [color = red];
|
||||
"file-system-/gnu/store" -> "root-file-system" [color = red];
|
||||
"file-system-/dev/shm" -> "root-file-system" [color = red];
|
||||
"file-system-/dev/pts" -> "root-file-system" [color = red];
|
||||
"user-processes" -> "root-file-system" [color = red];
|
||||
"udev" -> "root-file-system" [color = red];
|
||||
"file-system-/run/user" [label = "file-system-/run/user", shape = box, fontname = Helvetica];
|
||||
"user-processes" -> "file-system-/run/user" [color = red];
|
||||
"file-system-/run/systemd" [label = "file-system-/run/systemd", shape = box, fontname = Helvetica];
|
||||
"user-processes" -> "file-system-/run/systemd" [color = red];
|
||||
"file-system-/gnu/store" [label = "file-system-/gnu/store", shape = box, fontname = Helvetica];
|
||||
"user-processes" -> "file-system-/gnu/store" [color = red];
|
||||
"file-system-/dev/shm" [label = "file-system-/dev/shm", shape = box, fontname = Helvetica];
|
||||
"user-processes" -> "file-system-/dev/shm" [color = red];
|
||||
"file-system-/dev/pts" [label = "file-system-/dev/pts", shape = box, fontname = Helvetica];
|
||||
"user-processes" -> "file-system-/dev/pts" [color = red];
|
||||
"udev" [label = "udev", shape = box, fontname = Helvetica];
|
||||
"term-tty6" -> "udev" [color = red];
|
||||
"term-tty5" -> "udev" [color = red];
|
||||
"term-tty4" -> "udev" [color = red];
|
||||
"term-tty3" -> "udev" [color = red];
|
||||
"term-tty2" -> "udev" [color = red];
|
||||
"term-tty1" -> "udev" [color = red];
|
||||
"networking" -> "udev" [color = red];
|
||||
"host-name" [label = "host-name", shape = box, fontname = Helvetica];
|
||||
"term-tty6" -> "host-name" [color = red];
|
||||
"term-tty5" -> "host-name" [color = red];
|
||||
"term-tty4" -> "host-name" [color = red];
|
||||
"term-tty3" -> "host-name" [color = red];
|
||||
"term-tty2" -> "host-name" [color = red];
|
||||
"term-tty1" -> "host-name" [color = red];
|
||||
"loopback" [label = "loopback", shape = box, fontname = Helvetica];
|
||||
|
||||
}
|
||||
@@ -1,20 +1,18 @@
|
||||
digraph "Service Type Dependencies" {
|
||||
shepherd [shape = box, fontname = Helvetica];
|
||||
dmd [shape = box, fontname = Helvetica];
|
||||
pam [shape = box, fontname = Helvetica];
|
||||
etc [shape = box, fontname = Helvetica];
|
||||
profile [shape = box, fontname = Helvetica];
|
||||
accounts [shape = box, fontname = Helvetica];
|
||||
activation [shape = box, fontname = Helvetica];
|
||||
boot [shape = box, fontname = Helvetica];
|
||||
system [shape = house, fontname = Helvetica];
|
||||
lshd -> shepherd;
|
||||
boot [shape = house, fontname = Helvetica];
|
||||
lshd -> dmd;
|
||||
lshd -> pam;
|
||||
udev -> shepherd;
|
||||
nscd -> shepherd [label = "extends"];
|
||||
udev -> dmd;
|
||||
nscd -> dmd [label = "extends"];
|
||||
"nss-mdns" -> nscd;
|
||||
"kvm-rules" -> udev;
|
||||
colord -> udev;
|
||||
dbus -> shepherd;
|
||||
dbus -> dmd;
|
||||
colord -> dbus;
|
||||
upower -> udev;
|
||||
upower -> dbus;
|
||||
@@ -23,7 +21,7 @@ digraph "Service Type Dependencies" {
|
||||
elogind -> dbus;
|
||||
elogind -> udev;
|
||||
elogind -> polkit [label = "extends"];
|
||||
shepherd -> boot;
|
||||
dmd -> boot;
|
||||
colord -> accounts;
|
||||
accounts -> activation;
|
||||
accounts -> etc;
|
||||
@@ -31,10 +29,7 @@ digraph "Service Type Dependencies" {
|
||||
activation -> boot;
|
||||
pam -> etc;
|
||||
elogind -> pam;
|
||||
guix -> shepherd;
|
||||
guix -> dmd;
|
||||
guix -> activation;
|
||||
guix -> accounts;
|
||||
boot -> system;
|
||||
etc -> system;
|
||||
profile -> system;
|
||||
}
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
digraph "Guix shepherd-service" {
|
||||
"user-file-systems" [label = "user-file-systems", shape = box, fontname = Helvetica];
|
||||
"user-processes" -> "user-file-systems" [color = cyan3];
|
||||
"user-processes" [label = "user-processes", shape = box, fontname = Helvetica];
|
||||
"nscd" -> "user-processes" [color = magenta];
|
||||
"guix-daemon" -> "user-processes" [color = blue];
|
||||
"urandom-seed" -> "user-processes" [color = dimgrey];
|
||||
"syslogd" -> "user-processes" [color = darkgoldenrod];
|
||||
"term-tty6" -> "user-processes" [color = magenta];
|
||||
"term-tty5" -> "user-processes" [color = red];
|
||||
"term-tty4" -> "user-processes" [color = darkgoldenrod];
|
||||
"term-tty3" -> "user-processes" [color = dimgrey];
|
||||
"term-tty2" -> "user-processes" [color = darkviolet];
|
||||
"term-tty1" -> "user-processes" [color = peachpuff4];
|
||||
"networking" -> "user-processes" [color = dimgrey];
|
||||
"nscd" [label = "nscd", shape = box, fontname = Helvetica];
|
||||
"guix-daemon" [label = "guix-daemon", shape = box, fontname = Helvetica];
|
||||
"urandom-seed" [label = "urandom-seed", shape = box, fontname = Helvetica];
|
||||
"syslogd" [label = "syslogd", shape = box, fontname = Helvetica];
|
||||
"ssh-daemon" -> "syslogd" [color = darkgoldenrod];
|
||||
"ssh-daemon" [label = "ssh-daemon", shape = box, fontname = Helvetica];
|
||||
"term-tty6" [label = "term-tty6", shape = box, fontname = Helvetica];
|
||||
"console-font-tty6" -> "term-tty6" [color = darkgoldenrod];
|
||||
"console-font-tty6" [label = "console-font-tty6", shape = box, fontname = Helvetica];
|
||||
"term-tty5" [label = "term-tty5", shape = box, fontname = Helvetica];
|
||||
"console-font-tty5" -> "term-tty5" [color = dimgrey];
|
||||
"console-font-tty5" [label = "console-font-tty5", shape = box, fontname = Helvetica];
|
||||
"term-tty4" [label = "term-tty4", shape = box, fontname = Helvetica];
|
||||
"console-font-tty4" -> "term-tty4" [color = darkviolet];
|
||||
"console-font-tty4" [label = "console-font-tty4", shape = box, fontname = Helvetica];
|
||||
"term-tty3" [label = "term-tty3", shape = box, fontname = Helvetica];
|
||||
"console-font-tty3" -> "term-tty3" [color = peachpuff4];
|
||||
"console-font-tty3" [label = "console-font-tty3", shape = box, fontname = Helvetica];
|
||||
"term-tty2" [label = "term-tty2", shape = box, fontname = Helvetica];
|
||||
"console-font-tty2" -> "term-tty2" [color = darkseagreen];
|
||||
"console-font-tty2" [label = "console-font-tty2", shape = box, fontname = Helvetica];
|
||||
"term-tty1" [label = "term-tty1", shape = box, fontname = Helvetica];
|
||||
"console-font-tty1" -> "term-tty1" [color = cyan3];
|
||||
"console-font-tty1" [label = "console-font-tty1", shape = box, fontname = Helvetica];
|
||||
"networking" [label = "networking", shape = box, fontname = Helvetica];
|
||||
"ssh-daemon" -> "networking" [color = darkgoldenrod];
|
||||
"root-file-system" [label = "root-file-system", shape = box, fontname = Helvetica];
|
||||
"file-system-/dev/pts" -> "root-file-system" [color = peachpuff4];
|
||||
"file-system-/dev/shm" -> "root-file-system" [color = darkgoldenrod];
|
||||
"file-system-/gnu/store" -> "root-file-system" [color = blue];
|
||||
"user-processes" -> "root-file-system" [color = cyan3];
|
||||
"udev" -> "root-file-system" [color = darkseagreen];
|
||||
"file-system-/dev/pts" [label = "file-system-/dev/pts", shape = box, fontname = Helvetica];
|
||||
"user-processes" -> "file-system-/dev/pts" [color = cyan3];
|
||||
"file-system-/dev/shm" [label = "file-system-/dev/shm", shape = box, fontname = Helvetica];
|
||||
"user-processes" -> "file-system-/dev/shm" [color = cyan3];
|
||||
"file-system-/gnu/store" [label = "file-system-/gnu/store", shape = box, fontname = Helvetica];
|
||||
"user-processes" -> "file-system-/gnu/store" [color = cyan3];
|
||||
"udev" [label = "udev", shape = box, fontname = Helvetica];
|
||||
"term-tty6" -> "udev" [color = magenta];
|
||||
"term-tty5" -> "udev" [color = red];
|
||||
"term-tty4" -> "udev" [color = darkgoldenrod];
|
||||
"term-tty3" -> "udev" [color = dimgrey];
|
||||
"term-tty2" -> "udev" [color = darkviolet];
|
||||
"term-tty1" -> "udev" [color = peachpuff4];
|
||||
"networking" -> "udev" [color = dimgrey];
|
||||
"host-name" [label = "host-name", shape = box, fontname = Helvetica];
|
||||
"term-tty6" -> "host-name" [color = magenta];
|
||||
"term-tty5" -> "host-name" [color = red];
|
||||
"term-tty4" -> "host-name" [color = darkgoldenrod];
|
||||
"term-tty3" -> "host-name" [color = dimgrey];
|
||||
"term-tty2" -> "host-name" [color = darkviolet];
|
||||
"term-tty1" -> "host-name" [color = peachpuff4];
|
||||
"loopback" [label = "loopback", shape = box, fontname = Helvetica];
|
||||
|
||||
}
|
||||
-156
@@ -1,156 +0,0 @@
|
||||
# GNU Guix --- Functional package management for GNU
|
||||
# Copyright © 2016 Eric Bavier <bavier@member.fsf.org>
|
||||
# Copyright © 2012, 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
|
||||
# Copyright © 2013 Andreas Enge <andreas@enge.fr>
|
||||
# Copyright © 2016 Taylan Ulrich Bayırlı/Kammer <taylanbayirli@gmail.com>
|
||||
# Copyright © 2016 Mathieu Lirzin <mthl@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/>.
|
||||
|
||||
info_TEXINFOS = %D%/guix.texi
|
||||
|
||||
DOT_FILES = \
|
||||
%D%/images/bootstrap-graph.dot \
|
||||
%D%/images/bootstrap-packages.dot \
|
||||
%D%/images/coreutils-graph.dot \
|
||||
%D%/images/coreutils-bag-graph.dot \
|
||||
%D%/images/service-graph.dot \
|
||||
%D%/images/shepherd-graph.dot
|
||||
|
||||
DOT_VECTOR_GRAPHICS = \
|
||||
$(DOT_FILES:%.dot=%.eps) \
|
||||
$(DOT_FILES:%.dot=%.pdf)
|
||||
|
||||
EXTRA_DIST += \
|
||||
%D%/htmlxref.cnf \
|
||||
%D%/contributing.texi \
|
||||
%D%/fdl-1.3.texi \
|
||||
$(DOT_FILES) \
|
||||
$(DOT_VECTOR_GRAPHICS) \
|
||||
%D%/images/coreutils-size-map.eps \
|
||||
%D%/environment-gdb.scm \
|
||||
%D%/package-hello.scm
|
||||
|
||||
OS_CONFIG_EXAMPLES_TEXI = \
|
||||
%D%/os-config-bare-bones.texi \
|
||||
%D%/os-config-desktop.texi \
|
||||
%D%/os-config-lightweight-desktop.texi
|
||||
|
||||
# Bundle this file so that makeinfo finds it in out-of-source-tree builds.
|
||||
BUILT_SOURCES += $(OS_CONFIG_EXAMPLES_TEXI)
|
||||
EXTRA_DIST += $(OS_CONFIG_EXAMPLES_TEXI)
|
||||
MAINTAINERCLEANFILES = $(OS_CONFIG_EXAMPLES_TEXI)
|
||||
|
||||
%D%/os-config-%.texi: gnu/system/examples/%.tmpl
|
||||
$(AM_V_GEN)$(MKDIR_P) "`dirname $@`"; \
|
||||
cp "$<" "$@"
|
||||
|
||||
infoimagedir = $(infodir)/images
|
||||
dist_infoimage_DATA = \
|
||||
$(DOT_FILES:%.dot=%.png) \
|
||||
%D%/images/coreutils-size-map.png
|
||||
|
||||
# Try hard to obtain an image size and aspect that's reasonable for inclusion
|
||||
# in an Info or PDF document.
|
||||
DOT_OPTIONS = \
|
||||
-Gratio=.9 -Gnodesep=.005 -Granksep=.00005 \
|
||||
-Nfontsize=9 -Nheight=.1 -Nwidth=.1
|
||||
|
||||
.dot.png:
|
||||
$(AM_V_DOT)$(DOT) -Tpng $(DOT_OPTIONS) < "$<" > "$(srcdir)/$@.tmp"; \
|
||||
mv "$(srcdir)/$@.tmp" "$(srcdir)/$@"
|
||||
|
||||
.dot.pdf:
|
||||
$(AM_V_DOT)$(DOT) -Tpdf $(DOT_OPTIONS) < "$<" > "$(srcdir)/$@.tmp"; \
|
||||
mv "$(srcdir)/$@.tmp" "$(srcdir)/$@"
|
||||
|
||||
.dot.eps:
|
||||
$(AM_V_DOT)$(DOT) -Teps $(DOT_OPTIONS) < "$<" > "$(srcdir)/$@.tmp"; \
|
||||
mv "$(srcdir)/$@.tmp" "$(srcdir)/$@"
|
||||
|
||||
.png.eps:
|
||||
$(AM_V_GEN)convert "$<" "$@-tmp.eps"; \
|
||||
mv "$@-tmp.eps" "$@"
|
||||
|
||||
# We cannot add new dependencies to `%D%/guix.pdf' & co. (info "(automake)
|
||||
# Extending"). Using the `-local' rules is imperfect, because they may be
|
||||
# triggered after the main rule. Oh, well.
|
||||
pdf-local: $(DOT_FILES=%.dot=$(top_srcdir)/%.pdf)
|
||||
info-local: $(DOT_FILES=%.dot=$(top_srcdir)/%.png)
|
||||
ps-local: $(DOT_FILES=%.dot=$(top_srcdir)/%.eps) \
|
||||
$(top_srcdir)/%D%/images/coreutils-size-map.eps
|
||||
dvi-local: ps-local
|
||||
|
||||
## ----------- ##
|
||||
## Man pages. ##
|
||||
## ----------- ##
|
||||
|
||||
# The man pages are generated using GNU Help2man. In makefiles rules they
|
||||
# depend not on the binary, but on the source files. This usage allows a
|
||||
# manual page to be generated by the maintainer and included in the
|
||||
# distribution without requiring the end-user to have 'help2man' installed.
|
||||
# They are built in $(srcdir) like info manuals.
|
||||
|
||||
sub_commands_mans = \
|
||||
$(srcdir)/%D%/guix-archive.1 \
|
||||
$(srcdir)/%D%/guix-build.1 \
|
||||
$(srcdir)/%D%/guix-challenge.1 \
|
||||
$(srcdir)/%D%/guix-download.1 \
|
||||
$(srcdir)/%D%/guix-edit.1 \
|
||||
$(srcdir)/%D%/guix-environment.1 \
|
||||
$(srcdir)/%D%/guix-gc.1 \
|
||||
$(srcdir)/%D%/guix-hash.1 \
|
||||
$(srcdir)/%D%/guix-import.1 \
|
||||
$(srcdir)/%D%/guix-lint.1 \
|
||||
$(srcdir)/%D%/guix-package.1 \
|
||||
$(srcdir)/%D%/guix-publish.1 \
|
||||
$(srcdir)/%D%/guix-pull.1 \
|
||||
$(srcdir)/%D%/guix-refresh.1 \
|
||||
$(srcdir)/%D%/guix-size.1 \
|
||||
$(srcdir)/%D%/guix-system.1
|
||||
|
||||
dist_man1_MANS = \
|
||||
$(srcdir)/%D%/guix.1 \
|
||||
$(sub_commands_mans)
|
||||
|
||||
gen_man = \
|
||||
LANGUAGE= $(top_builddir)/pre-inst-env $(HELP2MAN) \
|
||||
$(HELP2MANFLAGS)
|
||||
|
||||
HELP2MANFLAGS = --source=GNU --info-page=$(PACKAGE_TARNAME)
|
||||
|
||||
$(srcdir)/%D%/guix.1: scripts/guix.in $(sub_commands_mans)
|
||||
-$(AM_V_HELP2MAN)$(gen_man) --output="$@" `basename "$@" .1`
|
||||
|
||||
# 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.
|
||||
$(srcdir)/%D%/guix-%.1: guix/scripts/%.scm $(GOBJECTS)
|
||||
-@case '$?' in \
|
||||
*$<*) $(AM_V_P) && set -x || echo " HELP2MAN $@"; \
|
||||
$(gen_man) --output="$@" "guix $*";; \
|
||||
*) : ;; \
|
||||
esac
|
||||
|
||||
if BUILD_DAEMON
|
||||
|
||||
dist_man1_MANS += $(srcdir)/%D%/guix-daemon.1
|
||||
|
||||
$(srcdir)/%D%/guix-daemon.1: nix/nix-daemon/guix-daemon.cc
|
||||
-$(AM_V_HELP2MAN)$(gen_man) --output="$@" `basename "$@" .1`
|
||||
|
||||
endif
|
||||
@@ -0,0 +1,61 @@
|
||||
# GNU Guix --- Functional package management for GNU
|
||||
# Copyright © 2014, 2015 Alex Kost <alezost@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/>.
|
||||
|
||||
AUTOLOADS = emacs/guix-autoloads.el
|
||||
|
||||
ELFILES = \
|
||||
emacs/guix-backend.el \
|
||||
emacs/guix-base.el \
|
||||
emacs/guix-build-log.el \
|
||||
emacs/guix-command.el \
|
||||
emacs/guix-devel.el \
|
||||
emacs/guix-emacs.el \
|
||||
emacs/guix-external.el \
|
||||
emacs/guix-geiser.el \
|
||||
emacs/guix-guile.el \
|
||||
emacs/guix-help-vars.el \
|
||||
emacs/guix-history.el \
|
||||
emacs/guix-info.el \
|
||||
emacs/guix-init.el \
|
||||
emacs/guix-list.el \
|
||||
emacs/guix-messages.el \
|
||||
emacs/guix-pcomplete.el \
|
||||
emacs/guix-popup.el \
|
||||
emacs/guix-prettify.el \
|
||||
emacs/guix-profiles.el \
|
||||
emacs/guix-read.el \
|
||||
emacs/guix-utils.el \
|
||||
emacs/guix.el
|
||||
|
||||
if HAVE_EMACS
|
||||
|
||||
dist_lisp_DATA = \
|
||||
$(ELFILES) \
|
||||
$(AUTOLOADS)
|
||||
|
||||
nodist_lisp_DATA = emacs/guix-config.el
|
||||
|
||||
$(AUTOLOADS): $(ELFILES)
|
||||
$(EMACS) --batch --eval \
|
||||
"(let ((backup-inhibited t) \
|
||||
(generated-autoload-file \
|
||||
(expand-file-name \"$(AUTOLOADS)\" \"$(srcdir)\"))) \
|
||||
(update-directory-autoloads \
|
||||
(expand-file-name \"emacs\" \"$(srcdir)\")))"
|
||||
|
||||
endif HAVE_EMACS
|
||||
@@ -0,0 +1,338 @@
|
||||
;;; guix-backend.el --- Making and using Guix REPL
|
||||
|
||||
;; Copyright © 2014, 2015 Alex Kost <alezost@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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file provides the code for interacting with Guile using Guix REPL
|
||||
;; (Geiser REPL with some guix-specific additions).
|
||||
|
||||
;; By default (if `guix-use-guile-server' is non-nil) 2 Guix REPLs are
|
||||
;; started. The main one (with "guile --listen" process) is used for
|
||||
;; "interacting" with a user - for showing a progress of
|
||||
;; installing/deleting Guix packages. The second (internal) REPL is
|
||||
;; used for synchronous evaluating, e.g. when information about
|
||||
;; packages/generations should be received for a list/info buffer.
|
||||
;;
|
||||
;; This "2 REPLs concept" makes it possible to have a running process of
|
||||
;; installing/deleting packages and to continue to search/list/get info
|
||||
;; about other packages at the same time. If you prefer to use a single
|
||||
;; Guix REPL, do not try to receive any information while there is a
|
||||
;; running code in the REPL (see
|
||||
;; <https://github.com/jaor/geiser/issues/28>).
|
||||
;;
|
||||
;; If you need to use "guix.el" in another Emacs (i.e. when there is
|
||||
;; a runnig "guile --listen..." REPL somewhere), you can either change
|
||||
;; `guix-default-port' in that Emacs instance or set
|
||||
;; `guix-use-guile-server' to t.
|
||||
;;
|
||||
;; Guix REPLs (unlike the usual Geiser REPLs) are not added to
|
||||
;; `geiser-repl--repls' variable, and thus cannot be used for evaluating
|
||||
;; while editing scm-files. The only purpose of Guix REPLs is to be an
|
||||
;; intermediate between "Guix/Guile level" and "Emacs interface level".
|
||||
;; That being said you can still want to use a Guix REPL while hacking
|
||||
;; auxiliary scheme-files for "guix.el". You can just use "M-x
|
||||
;; connect-to-guile" (connect to "localhost" and `guix-default-port') to
|
||||
;; have a usual Geiser REPL with all stuff defined by "guix.el" package.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'geiser-mode)
|
||||
(require 'geiser-guile)
|
||||
(require 'guix-geiser)
|
||||
(require 'guix-config)
|
||||
(require 'guix-external)
|
||||
(require 'guix-emacs)
|
||||
|
||||
(defvar guix-load-path guix-config-emacs-interface-directory
|
||||
"Directory with scheme files for \"guix.el\" package.")
|
||||
|
||||
(defvar guix-helper-file
|
||||
(expand-file-name "guix-helper.scm" guix-load-path)
|
||||
"Auxiliary scheme file for loading.")
|
||||
|
||||
|
||||
;;; REPL
|
||||
|
||||
(defgroup guix-repl nil
|
||||
"Settings for Guix REPLs."
|
||||
:prefix "guix-repl-"
|
||||
:group 'guix)
|
||||
|
||||
(defcustom guix-repl-startup-time 30000
|
||||
"Time, in milliseconds, to wait for Guix REPL to startup.
|
||||
Same as `geiser-repl-startup-time' but is used for Guix REPL.
|
||||
If you have a slow system, try to increase this time."
|
||||
:type 'integer
|
||||
:group 'guix-repl)
|
||||
|
||||
(defcustom guix-repl-buffer-name "*Guix REPL*"
|
||||
"Default name of a Geiser REPL buffer used for Guix."
|
||||
:type 'string
|
||||
:group 'guix-repl)
|
||||
|
||||
(defcustom guix-after-start-repl-hook ()
|
||||
"Hook called after Guix REPL is started."
|
||||
:type 'hook
|
||||
:group 'guix-repl)
|
||||
|
||||
(defcustom guix-use-guile-server t
|
||||
"If non-nil, start guile with '--listen' argument.
|
||||
This allows to receive information about packages using an additional
|
||||
REPL while some packages are being installed/removed in the main REPL."
|
||||
:type 'boolean
|
||||
:group 'guix-repl)
|
||||
|
||||
(defcustom guix-default-port 37246
|
||||
"Default port used if `guix-use-guile-server' is non-nil."
|
||||
:type 'integer
|
||||
:group 'guix-repl)
|
||||
|
||||
(defvar guix-repl-buffer nil
|
||||
"Main Geiser REPL buffer used for communicating with Guix.
|
||||
This REPL is used for processing package actions and for
|
||||
receiving information if `guix-use-guile-server' is nil.")
|
||||
|
||||
(defvar guix-internal-repl-buffer nil
|
||||
"Additional Geiser REPL buffer used for communicating with Guix.
|
||||
This REPL is used for receiving information only if
|
||||
`guix-use-guile-server' is non-nil.")
|
||||
|
||||
(defvar guix-internal-repl-buffer-name "*Guix Internal REPL*"
|
||||
"Default name of an internal Guix REPL buffer.")
|
||||
|
||||
(defvar guix-before-repl-operation-hook nil
|
||||
"Hook run before executing an operation in Guix REPL.")
|
||||
|
||||
(defvar guix-after-repl-operation-hook
|
||||
'(guix-emacs-load-autoloads-maybe
|
||||
guix-repl-operation-success-message)
|
||||
"Hook run after executing successful operation in Guix REPL.")
|
||||
|
||||
(defvar guix-repl-operation-p nil
|
||||
"Non-nil, if current operation is performed by `guix-eval-in-repl'.
|
||||
This internal variable is used to distinguish Guix operations
|
||||
from operations performed in Guix REPL by a user.")
|
||||
|
||||
(defvar guix-repl-operation-type nil
|
||||
"Type of the current operation performed by `guix-eval-in-repl'.
|
||||
This internal variable is used to define what actions should be
|
||||
executed after the current operation succeeds.
|
||||
See `guix-eval-in-repl' for details.")
|
||||
|
||||
(defun guix-repl-operation-success-message ()
|
||||
"Message telling about successful Guix operation."
|
||||
(message "Guix operation has been performed."))
|
||||
|
||||
(defun guix-get-guile-program (&optional internal)
|
||||
"Return a value suitable for `geiser-guile-binary'."
|
||||
(if (or internal
|
||||
(not guix-use-guile-server))
|
||||
guix-guile-program
|
||||
(append (if (listp guix-guile-program)
|
||||
guix-guile-program
|
||||
(list guix-guile-program))
|
||||
;; Guile understands "--listen=..." but not "--listen ..."
|
||||
(list (concat "--listen="
|
||||
(number-to-string guix-default-port))))))
|
||||
|
||||
(defun guix-start-process-maybe (&optional start-msg end-msg)
|
||||
"Start Geiser REPL configured for Guix if needed.
|
||||
START-MSG and END-MSG are strings displayed in the minibuffer in
|
||||
the beginning and in the end of the starting process. If nil,
|
||||
display default messages."
|
||||
(guix-start-repl-maybe nil
|
||||
(or start-msg "Starting Guix REPL ...")
|
||||
(or end-msg "Guix REPL has been started."))
|
||||
(if guix-use-guile-server
|
||||
(guix-start-repl-maybe 'internal)
|
||||
(setq guix-internal-repl-buffer guix-repl-buffer)))
|
||||
|
||||
(defun guix-start-repl-maybe (&optional internal start-msg end-msg)
|
||||
"Start Guix REPL if needed.
|
||||
If INTERNAL is non-nil, start an internal REPL.
|
||||
|
||||
START-MSG and END-MSG are strings displayed in the minibuffer in
|
||||
the beginning and in the end of the process. If nil, do not
|
||||
display messages."
|
||||
(let* ((repl-var (guix-get-repl-buffer-variable internal))
|
||||
(repl (symbol-value repl-var)))
|
||||
(unless (and (buffer-live-p repl)
|
||||
(get-buffer-process repl))
|
||||
(and start-msg (message start-msg))
|
||||
(setq guix-repl-operation-p nil)
|
||||
(let ((geiser-guile-binary (guix-get-guile-program internal))
|
||||
(geiser-guile-init-file (or internal guix-helper-file))
|
||||
(repl (get-buffer-create
|
||||
(guix-get-repl-buffer-name internal))))
|
||||
(condition-case err
|
||||
(guix-start-repl repl
|
||||
(and internal
|
||||
(geiser-repl--read-address
|
||||
"localhost" guix-default-port)))
|
||||
(text-read-only
|
||||
(error (concat "Couldn't start Guix REPL. Perhaps the port %s is busy.\n"
|
||||
"See buffer '%s' for details")
|
||||
guix-default-port (buffer-name repl))))
|
||||
(set repl-var repl)
|
||||
(and end-msg (message end-msg))
|
||||
(unless internal
|
||||
(run-hooks 'guix-after-start-repl-hook))))))
|
||||
|
||||
(defun guix-start-repl (buffer &optional address)
|
||||
"Start Guix REPL in BUFFER.
|
||||
If ADDRESS is non-nil, connect to a remote guile process using
|
||||
this address (it should be defined by
|
||||
`geiser-repl--read-address')."
|
||||
;; A mix of the code from `geiser-repl--start-repl' and
|
||||
;; `geiser-repl--to-repl-buffer'.
|
||||
(let ((impl 'guile)
|
||||
(geiser-guile-load-path (cons guix-load-path
|
||||
geiser-guile-load-path))
|
||||
(geiser-repl-startup-time guix-repl-startup-time))
|
||||
(with-current-buffer buffer
|
||||
(geiser-repl-mode)
|
||||
(geiser-impl--set-buffer-implementation impl)
|
||||
(geiser-repl--autodoc-mode -1)
|
||||
(goto-char (point-max))
|
||||
(let ((prompt (geiser-con--combined-prompt
|
||||
geiser-guile--prompt-regexp
|
||||
geiser-guile--debugger-prompt-regexp)))
|
||||
(geiser-repl--save-remote-data address)
|
||||
(geiser-repl--start-scheme impl address prompt)
|
||||
(geiser-repl--quit-setup)
|
||||
(geiser-repl--history-setup)
|
||||
(setq-local geiser-repl--repls (list buffer))
|
||||
(geiser-repl--set-this-buffer-repl buffer)
|
||||
(setq geiser-repl--connection
|
||||
(geiser-con--make-connection
|
||||
(get-buffer-process (current-buffer))
|
||||
geiser-guile--prompt-regexp
|
||||
geiser-guile--debugger-prompt-regexp))
|
||||
(geiser-repl--startup impl address)
|
||||
(geiser-repl--autodoc-mode 1)
|
||||
(geiser-company--setup geiser-repl-company-p)
|
||||
(add-hook 'comint-output-filter-functions
|
||||
'guix-repl-output-filter
|
||||
nil t)
|
||||
(set-process-query-on-exit-flag
|
||||
(get-buffer-process (current-buffer))
|
||||
geiser-repl-query-on-kill-p)))))
|
||||
|
||||
(defun guix-repl-output-filter (str)
|
||||
"Filter function suitable for `comint-output-filter-functions'.
|
||||
This is a replacement for `geiser-repl--output-filter'."
|
||||
(cond
|
||||
((string-match-p geiser-guile--prompt-regexp str)
|
||||
(geiser-autodoc--disinhibit-autodoc)
|
||||
(when guix-repl-operation-p
|
||||
(setq guix-repl-operation-p nil)
|
||||
(run-hooks 'guix-after-repl-operation-hook)
|
||||
;; Run hooks specific to the current operation type.
|
||||
(when guix-repl-operation-type
|
||||
(let ((type-hook (intern
|
||||
(concat "guix-after-"
|
||||
(symbol-name guix-repl-operation-type)
|
||||
"-hook"))))
|
||||
(setq guix-repl-operation-type nil)
|
||||
(and (boundp type-hook)
|
||||
(run-hooks type-hook))))))
|
||||
((string-match geiser-guile--debugger-prompt-regexp str)
|
||||
(setq guix-repl-operation-p nil)
|
||||
(geiser-con--connection-set-debugging geiser-repl--connection
|
||||
(match-beginning 0))
|
||||
(geiser-autodoc--disinhibit-autodoc))))
|
||||
|
||||
(defun guix-repl-exit (&optional internal no-wait)
|
||||
"Exit the current Guix REPL.
|
||||
If INTERNAL is non-nil, exit the internal REPL.
|
||||
If NO-WAIT is non-nil, do not wait for the REPL process to exit:
|
||||
send a kill signal to it and return immediately."
|
||||
(let ((repl (symbol-value (guix-get-repl-buffer-variable internal))))
|
||||
(when (get-buffer-process repl)
|
||||
(with-current-buffer repl
|
||||
(geiser-con--connection-deactivate geiser-repl--connection t)
|
||||
(comint-kill-subjob)
|
||||
(unless no-wait
|
||||
(while (get-buffer-process repl)
|
||||
(sleep-for 0.1)))))))
|
||||
|
||||
(defun guix-get-repl-buffer (&optional internal)
|
||||
"Return Guix REPL buffer; start REPL if needed.
|
||||
If INTERNAL is non-nil, return an additional internal REPL."
|
||||
(guix-start-process-maybe)
|
||||
(let ((repl (symbol-value (guix-get-repl-buffer-variable internal))))
|
||||
;; If a new Geiser REPL is started, `geiser-repl--repl' variable may
|
||||
;; be set to the new value in a Guix REPL, so set it back to a
|
||||
;; proper value here.
|
||||
(with-current-buffer repl
|
||||
(geiser-repl--set-this-buffer-repl repl))
|
||||
repl))
|
||||
|
||||
(defun guix-get-repl-buffer-variable (&optional internal)
|
||||
"Return the name of a variable with a REPL buffer."
|
||||
(if internal
|
||||
'guix-internal-repl-buffer
|
||||
'guix-repl-buffer))
|
||||
|
||||
(defun guix-get-repl-buffer-name (&optional internal)
|
||||
"Return the name of a REPL buffer."
|
||||
(if internal
|
||||
guix-internal-repl-buffer-name
|
||||
guix-repl-buffer-name))
|
||||
|
||||
(defun guix-switch-to-repl (&optional internal)
|
||||
"Switch to Guix REPL.
|
||||
If INTERNAL is non-nil (interactively with prefix), switch to the
|
||||
additional internal REPL if it exists."
|
||||
(interactive "P")
|
||||
(geiser-repl--switch-to-buffer (guix-get-repl-buffer internal)))
|
||||
|
||||
|
||||
;;; Evaluating expressions
|
||||
|
||||
(defvar guix-operation-buffer nil
|
||||
"Buffer from which the latest Guix operation was performed.")
|
||||
|
||||
(defun guix-eval (str)
|
||||
"Evaluate STR with guile expression using Guix REPL.
|
||||
See `guix-geiser-eval' for details."
|
||||
(guix-geiser-eval str (guix-get-repl-buffer 'internal)))
|
||||
|
||||
(defun guix-eval-read (str)
|
||||
"Evaluate STR with guile expression using Guix REPL.
|
||||
See `guix-geiser-eval-read' for details."
|
||||
(guix-geiser-eval-read str (guix-get-repl-buffer 'internal)))
|
||||
|
||||
(defun guix-eval-in-repl (str &optional operation-buffer operation-type)
|
||||
"Switch to Guix REPL and evaluate STR with guile expression there.
|
||||
If OPERATION-BUFFER is non-nil, it should be a buffer from which
|
||||
the current operation was performed.
|
||||
|
||||
If OPERATION-TYPE is non-nil, it should be a symbol. After
|
||||
successful executing of the current operation,
|
||||
`guix-after-OPERATION-TYPE-hook' is called."
|
||||
(run-hooks 'guix-before-repl-operation-hook)
|
||||
(setq guix-repl-operation-p t
|
||||
guix-repl-operation-type operation-type
|
||||
guix-operation-buffer operation-buffer)
|
||||
(guix-geiser-eval-in-repl str (guix-get-repl-buffer)))
|
||||
|
||||
(provide 'guix-backend)
|
||||
|
||||
;;; guix-backend.el ends here
|
||||
+1192
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,334 @@
|
||||
;;; guix-build-log.el --- Major and minor modes for build logs -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright © 2015 Alex Kost <alezost@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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file provides a major mode (`guix-build-log-mode') and a minor mode
|
||||
;; (`guix-build-log-minor-mode') for highlighting Guix build logs.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(defgroup guix-build-log nil
|
||||
"Settings for `guix-build-log-mode'."
|
||||
:group 'guix)
|
||||
|
||||
(defgroup guix-build-log-faces nil
|
||||
"Faces for `guix-build-log-mode'."
|
||||
:group 'guix-build-log
|
||||
:group 'guix-faces)
|
||||
|
||||
(defface guix-build-log-title-head
|
||||
'((t :inherit font-lock-keyword-face))
|
||||
"Face for '@' symbol of a log title."
|
||||
:group 'guix-build-log-faces)
|
||||
|
||||
(defface guix-build-log-title-start
|
||||
'((t :inherit guix-build-log-title-head))
|
||||
"Face for a log title denoting a start of a process."
|
||||
:group 'guix-build-log-faces)
|
||||
|
||||
(defface guix-build-log-title-success
|
||||
'((t :inherit guix-build-log-title-head))
|
||||
"Face for a log title denoting a successful end of a process."
|
||||
:group 'guix-build-log-faces)
|
||||
|
||||
(defface guix-build-log-title-fail
|
||||
'((t :inherit error))
|
||||
"Face for a log title denoting a failed end of a process."
|
||||
:group 'guix-build-log-faces)
|
||||
|
||||
(defface guix-build-log-title-end
|
||||
'((t :inherit guix-build-log-title-head))
|
||||
"Face for a log title denoting an undefined end of a process."
|
||||
:group 'guix-build-log-faces)
|
||||
|
||||
(defface guix-build-log-phase-name
|
||||
'((t :inherit font-lock-function-name-face))
|
||||
"Face for a phase name."
|
||||
:group 'guix-build-log-faces)
|
||||
|
||||
(defface guix-build-log-phase-start
|
||||
'((default :weight bold)
|
||||
(((class grayscale) (background light)) :foreground "Gray90")
|
||||
(((class grayscale) (background dark)) :foreground "DimGray")
|
||||
(((class color) (min-colors 16) (background light))
|
||||
:foreground "DarkGreen")
|
||||
(((class color) (min-colors 16) (background dark))
|
||||
:foreground "LimeGreen")
|
||||
(((class color) (min-colors 8)) :foreground "green"))
|
||||
"Face for the start line of a phase."
|
||||
:group 'guix-build-log-faces)
|
||||
|
||||
(defface guix-build-log-phase-end
|
||||
'((((class grayscale) (background light)) :foreground "Gray90")
|
||||
(((class grayscale) (background dark)) :foreground "DimGray")
|
||||
(((class color) (min-colors 16) (background light))
|
||||
:foreground "ForestGreen")
|
||||
(((class color) (min-colors 16) (background dark))
|
||||
:foreground "LightGreen")
|
||||
(((class color) (min-colors 8)) :foreground "green")
|
||||
(t :weight bold))
|
||||
"Face for the end line of a phase."
|
||||
:group 'guix-build-log-faces)
|
||||
|
||||
(defface guix-build-log-phase-success
|
||||
'((t))
|
||||
"Face for the 'succeeded' word of a phase line."
|
||||
:group 'guix-build-log-faces)
|
||||
|
||||
(defface guix-build-log-phase-fail
|
||||
'((t :inherit error))
|
||||
"Face for the 'failed' word of a phase line."
|
||||
:group 'guix-build-log-faces)
|
||||
|
||||
(defface guix-build-log-phase-seconds
|
||||
'((t :inherit font-lock-constant-face))
|
||||
"Face for the number of seconds for a phase."
|
||||
:group 'guix-build-log-faces)
|
||||
|
||||
(defcustom guix-build-log-mode-hook
|
||||
;; Not using `compilation-minor-mode' because it rebinds some standard
|
||||
;; keys, including M-n/M-p.
|
||||
'(compilation-shell-minor-mode view-mode)
|
||||
"Hook run after `guix-build-log-mode' is entered."
|
||||
:type 'hook
|
||||
:group 'guix-build-log)
|
||||
|
||||
(defvar guix-build-log-phase-name-regexp "`\\([^']+\\)'"
|
||||
"Regexp for a phase name.")
|
||||
|
||||
(defvar guix-build-log-phase-start-regexp
|
||||
(concat "^starting phase " guix-build-log-phase-name-regexp)
|
||||
"Regexp for the start line of a 'build' phase.")
|
||||
|
||||
(defun guix-build-log-title-regexp (&optional state)
|
||||
"Return regexp for the log title.
|
||||
STATE is a symbol denoting a state of the title. It should be
|
||||
`start', `fail', `success' or `nil' (for a regexp matching any
|
||||
state)."
|
||||
(let* ((word-rx (rx (1+ (any word "-"))))
|
||||
(state-rx (cond ((eq state 'start) (concat word-rx "started"))
|
||||
((eq state 'success) (concat word-rx "succeeded"))
|
||||
((eq state 'fail) (concat word-rx "failed"))
|
||||
(t word-rx))))
|
||||
(rx-to-string
|
||||
`(and bol (group "@") " " (group (regexp ,state-rx)))
|
||||
t)))
|
||||
|
||||
(defun guix-build-log-phase-end-regexp (&optional state)
|
||||
"Return regexp for the end line of a 'build' phase.
|
||||
STATE is a symbol denoting how a build phase was ended. It should be
|
||||
`fail', `success' or `nil' (for a regexp matching any state)."
|
||||
(let ((state-rx (cond ((eq state 'success) "succeeded")
|
||||
((eq state 'fail) "failed")
|
||||
(t (regexp-opt '("succeeded" "failed"))))))
|
||||
(rx-to-string
|
||||
`(and bol "phase " (regexp ,guix-build-log-phase-name-regexp)
|
||||
" " (group (regexp ,state-rx)) " after "
|
||||
(group (1+ (or digit "."))) " seconds")
|
||||
t)))
|
||||
|
||||
(defvar guix-build-log-phase-end-regexp
|
||||
;; For efficiency, it is better to have a regexp for the general line
|
||||
;; of the phase end, then to call the function all the time.
|
||||
(guix-build-log-phase-end-regexp)
|
||||
"Regexp for the end line of a 'build' phase.")
|
||||
|
||||
(defvar guix-build-log-font-lock-keywords
|
||||
`((,(guix-build-log-title-regexp 'start)
|
||||
(1 'guix-build-log-title-head)
|
||||
(2 'guix-build-log-title-start))
|
||||
(,(guix-build-log-title-regexp 'success)
|
||||
(1 'guix-build-log-title-head)
|
||||
(2 'guix-build-log-title-success))
|
||||
(,(guix-build-log-title-regexp 'fail)
|
||||
(1 'guix-build-log-title-head)
|
||||
(2 'guix-build-log-title-fail))
|
||||
(,(guix-build-log-title-regexp)
|
||||
(1 'guix-build-log-title-head)
|
||||
(2 'guix-build-log-title-end))
|
||||
(,guix-build-log-phase-start-regexp
|
||||
(0 'guix-build-log-phase-start)
|
||||
(1 'guix-build-log-phase-name prepend))
|
||||
(,(guix-build-log-phase-end-regexp 'success)
|
||||
(0 'guix-build-log-phase-end)
|
||||
(1 'guix-build-log-phase-name prepend)
|
||||
(2 'guix-build-log-phase-success prepend)
|
||||
(3 'guix-build-log-phase-seconds prepend))
|
||||
(,(guix-build-log-phase-end-regexp 'fail)
|
||||
(0 'guix-build-log-phase-end)
|
||||
(1 'guix-build-log-phase-name prepend)
|
||||
(2 'guix-build-log-phase-fail prepend)
|
||||
(3 'guix-build-log-phase-seconds prepend)))
|
||||
"A list of `font-lock-keywords' for `guix-build-log-mode'.")
|
||||
|
||||
(defvar guix-build-log-mode-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(set-keymap-parent map special-mode-map)
|
||||
(define-key map (kbd "M-n") 'guix-build-log-next-phase)
|
||||
(define-key map (kbd "M-p") 'guix-build-log-previous-phase)
|
||||
(define-key map (kbd "TAB") 'guix-build-log-phase-toggle)
|
||||
(define-key map (kbd "<tab>") 'guix-build-log-phase-toggle)
|
||||
(define-key map (kbd "<backtab>") 'guix-build-log-phase-toggle-all)
|
||||
(define-key map [(shift tab)] 'guix-build-log-phase-toggle-all)
|
||||
map)
|
||||
"Keymap for `guix-build-log-mode' buffers.")
|
||||
|
||||
(defun guix-build-log-phase-start (&optional with-header?)
|
||||
"Return the start point of the current build phase.
|
||||
If WITH-HEADER? is non-nil, do not skip 'starting phase ...' header.
|
||||
Return nil, if there is no phase start before the current point."
|
||||
(save-excursion
|
||||
(end-of-line)
|
||||
(when (re-search-backward guix-build-log-phase-start-regexp nil t)
|
||||
(unless with-header? (end-of-line))
|
||||
(point))))
|
||||
|
||||
(defun guix-build-log-phase-end ()
|
||||
"Return the end point of the current build phase."
|
||||
(save-excursion
|
||||
(beginning-of-line)
|
||||
(when (re-search-forward guix-build-log-phase-end-regexp nil t)
|
||||
(point))))
|
||||
|
||||
(defun guix-build-log-phase-hide ()
|
||||
"Hide the body of the current build phase."
|
||||
(interactive)
|
||||
(let ((beg (guix-build-log-phase-start))
|
||||
(end (guix-build-log-phase-end)))
|
||||
(when (and beg end)
|
||||
;; If not on the header line, move to it.
|
||||
(when (and (> (point) beg)
|
||||
(< (point) end))
|
||||
(goto-char (guix-build-log-phase-start t)))
|
||||
(remove-overlays beg end 'invisible t)
|
||||
(let ((o (make-overlay beg end)))
|
||||
(overlay-put o 'evaporate t)
|
||||
(overlay-put o 'invisible t)))))
|
||||
|
||||
(defun guix-build-log-phase-show ()
|
||||
"Show the body of the current build phase."
|
||||
(interactive)
|
||||
(let ((beg (guix-build-log-phase-start))
|
||||
(end (guix-build-log-phase-end)))
|
||||
(when (and beg end)
|
||||
(remove-overlays beg end 'invisible t))))
|
||||
|
||||
(defun guix-build-log-phase-hidden-p ()
|
||||
"Return non-nil, if the body of the current build phase is hidden."
|
||||
(let ((beg (guix-build-log-phase-start)))
|
||||
(and beg
|
||||
(cl-some (lambda (o)
|
||||
(overlay-get o 'invisible))
|
||||
(overlays-at beg)))))
|
||||
|
||||
(defun guix-build-log-phase-toggle-function ()
|
||||
"Return a function to toggle the body of the current build phase."
|
||||
(if (guix-build-log-phase-hidden-p)
|
||||
#'guix-build-log-phase-show
|
||||
#'guix-build-log-phase-hide))
|
||||
|
||||
(defun guix-build-log-phase-toggle ()
|
||||
"Show/hide the body of the current build phase."
|
||||
(interactive)
|
||||
(funcall (guix-build-log-phase-toggle-function)))
|
||||
|
||||
(defun guix-build-log-phase-toggle-all ()
|
||||
"Show/hide the bodies of all build phases."
|
||||
(interactive)
|
||||
(save-excursion
|
||||
;; Some phases may be hidden, and some shown. Whether to hide or to
|
||||
;; show them, it is determined by the state of the first phase here.
|
||||
(goto-char (point-min))
|
||||
(let ((fun (save-excursion
|
||||
(re-search-forward guix-build-log-phase-start-regexp nil t)
|
||||
(guix-build-log-phase-toggle-function))))
|
||||
(while (re-search-forward guix-build-log-phase-start-regexp nil t)
|
||||
(funcall fun)))))
|
||||
|
||||
(defun guix-build-log-next-phase (&optional arg)
|
||||
"Move to the next build phase.
|
||||
With ARG, do it that many times. Negative ARG means move
|
||||
backward."
|
||||
(interactive "^p")
|
||||
(if arg
|
||||
(when (zerop arg) (user-error "Try again"))
|
||||
(setq arg 1))
|
||||
(let ((search-fun (if (> arg 0)
|
||||
#'re-search-forward
|
||||
#'re-search-backward))
|
||||
(n (abs arg))
|
||||
found last-found)
|
||||
(save-excursion
|
||||
(end-of-line (if (> arg 0) 1 0)) ; skip the current line
|
||||
(while (and (not (zerop n))
|
||||
(setq found
|
||||
(funcall search-fun
|
||||
guix-build-log-phase-start-regexp
|
||||
nil t)))
|
||||
(setq n (1- n)
|
||||
last-found found)))
|
||||
(when last-found
|
||||
(goto-char last-found)
|
||||
(forward-line 0))
|
||||
(or found
|
||||
(user-error (if (> arg 0)
|
||||
"No next build phase"
|
||||
"No previous build phase")))))
|
||||
|
||||
(defun guix-build-log-previous-phase (&optional arg)
|
||||
"Move to the previous build phase.
|
||||
With ARG, do it that many times. Negative ARG means move
|
||||
forward."
|
||||
(interactive "^p")
|
||||
(guix-build-log-next-phase (- (or arg 1))))
|
||||
|
||||
;;;###autoload
|
||||
(define-derived-mode guix-build-log-mode special-mode
|
||||
"Guix-Build-Log"
|
||||
"Major mode for viewing Guix build logs.
|
||||
|
||||
\\{guix-build-log-mode-map}"
|
||||
(setq font-lock-defaults '(guix-build-log-font-lock-keywords t)))
|
||||
|
||||
;;;###autoload
|
||||
(define-minor-mode guix-build-log-minor-mode
|
||||
"Toggle Guix Build Log minor mode.
|
||||
|
||||
With a prefix argument ARG, enable Guix Build Log minor mode if
|
||||
ARG is positive, and disable it otherwise. If called from Lisp,
|
||||
enable the mode if ARG is omitted or nil.
|
||||
|
||||
When Guix Build Log minor mode is enabled, it highlights build
|
||||
log in the current buffer. This mode can be enabled
|
||||
programmatically using hooks:
|
||||
|
||||
(add-hook 'shell-mode-hook 'guix-build-log-minor-mode)"
|
||||
:init-value nil
|
||||
:lighter " Guix-Build-Log"
|
||||
:group 'guix-build-log
|
||||
(if guix-build-log-minor-mode
|
||||
(font-lock-add-keywords nil guix-build-log-font-lock-keywords)
|
||||
(font-lock-remove-keywords nil guix-build-log-font-lock-keywords))
|
||||
(when font-lock-mode
|
||||
(font-lock-fontify-buffer)))
|
||||
|
||||
(provide 'guix-build-log)
|
||||
|
||||
;;; guix-build-log.el ends here
|
||||
@@ -0,0 +1,718 @@
|
||||
;;; guix-command.el --- Popup interface for guix commands -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright © 2015 Alex Kost <alezost@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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file provides a magit-like popup interface for running guix
|
||||
;; commands in Guix REPL. The entry point is "M-x guix". When it is
|
||||
;; called the first time, "guix --help" output is parsed and
|
||||
;; `guix-COMMAND-action' functions are generated for each available guix
|
||||
;; COMMAND. Then a window with these commands is popped up. When a
|
||||
;; particular COMMAND is called, "guix COMMAND --help" output is parsed,
|
||||
;; and a user get a new popup window with available options for this
|
||||
;; command and so on.
|
||||
|
||||
;; To avoid hard-coding all guix options, actions, etc., as much data is
|
||||
;; taken from "guix ... --help" outputs as possible. But this data is
|
||||
;; still incomplete: not all long options have short analogs, also
|
||||
;; special readers should be used for some options (for example, to
|
||||
;; complete package names while prompting for a package). So after
|
||||
;; parsing --help output, the arguments are "improved". All arguments
|
||||
;; (switches, options and actions) are `guix-command-argument'
|
||||
;; structures.
|
||||
|
||||
;; Only "M-x guix" command is available after this file is loaded. The
|
||||
;; rest commands/actions/popups are generated on the fly only when they
|
||||
;; are needed (that's why there is a couple of `eval'-s in this file).
|
||||
|
||||
;; COMMANDS argument is used by many functions in this file. It means a
|
||||
;; list of guix commands without "guix" itself, e.g.: ("build"),
|
||||
;; ("import" "gnu"). The empty list stands for the plain "guix" without
|
||||
;; subcommands.
|
||||
|
||||
;; All actions in popup windows are divided into 2 groups:
|
||||
;;
|
||||
;; - 'Popup' actions - used to pop up another window. For example, every
|
||||
;; action in the 'guix' or 'guix import' window is a popup action. They
|
||||
;; are defined by `guix-command-define-popup-action' macro.
|
||||
;;
|
||||
;; - 'Execute' actions - used to do something with the command line (to
|
||||
;; run a command in Guix REPL or to copy it into kill-ring) constructed
|
||||
;; with the current popup. They are defined by
|
||||
;; `guix-command-define-execute-action' macro.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'cl-lib)
|
||||
(require 'guix-popup)
|
||||
(require 'guix-utils)
|
||||
(require 'guix-help-vars)
|
||||
(require 'guix-read)
|
||||
(require 'guix-base)
|
||||
(require 'guix-guile)
|
||||
(require 'guix-external)
|
||||
|
||||
(defgroup guix-commands nil
|
||||
"Settings for guix popup windows."
|
||||
:group 'guix)
|
||||
|
||||
(defvar guix-command-complex-with-shared-arguments
|
||||
'("system")
|
||||
"List of guix commands which have subcommands with shared options.
|
||||
I.e., 'guix foo --help' is the same as 'guix foo bar --help'.")
|
||||
|
||||
(defun guix-command-action-name (&optional commands &rest name-parts)
|
||||
"Return name of action function for guix COMMANDS."
|
||||
(guix-command-symbol (append commands name-parts (list "action"))))
|
||||
|
||||
|
||||
;;; Command arguments
|
||||
|
||||
(cl-defstruct (guix-command-argument
|
||||
(:constructor guix-command-make-argument)
|
||||
(:copier guix-command-copy-argument))
|
||||
name char doc fun switch? option? action?)
|
||||
|
||||
(cl-defun guix-command-modify-argument
|
||||
(argument &key
|
||||
(name nil name-bound?)
|
||||
(char nil char-bound?)
|
||||
(doc nil doc-bound?)
|
||||
(fun nil fun-bound?)
|
||||
(switch? nil switch?-bound?)
|
||||
(option? nil option?-bound?)
|
||||
(action? nil action?-bound?))
|
||||
"Return a modified version of ARGUMENT."
|
||||
(declare (indent 1))
|
||||
(let ((copy (guix-command-copy-argument argument)))
|
||||
(and name-bound? (setf (guix-command-argument-name copy) name))
|
||||
(and char-bound? (setf (guix-command-argument-char copy) char))
|
||||
(and doc-bound? (setf (guix-command-argument-doc copy) doc))
|
||||
(and fun-bound? (setf (guix-command-argument-fun copy) fun))
|
||||
(and switch?-bound? (setf (guix-command-argument-switch? copy) switch?))
|
||||
(and option?-bound? (setf (guix-command-argument-option? copy) option?))
|
||||
(and action?-bound? (setf (guix-command-argument-action? copy) action?))
|
||||
copy))
|
||||
|
||||
(defun guix-command-modify-argument-from-alist (argument alist)
|
||||
"Return a modified version of ARGUMENT or nil if it wasn't modified.
|
||||
Each assoc from ALIST have a form (NAME . PLIST). NAME is an
|
||||
argument name. PLIST is a property list of argument parameters
|
||||
to be modified."
|
||||
(let* ((name (guix-command-argument-name argument))
|
||||
(plist (guix-assoc-value alist name)))
|
||||
(when plist
|
||||
(apply #'guix-command-modify-argument
|
||||
argument plist))))
|
||||
|
||||
(defmacro guix-command-define-argument-improver (name alist)
|
||||
"Define NAME variable and function to modify an argument from ALIST."
|
||||
(declare (indent 1))
|
||||
`(progn
|
||||
(defvar ,name ,alist)
|
||||
(defun ,name (argument)
|
||||
(guix-command-modify-argument-from-alist argument ,name))))
|
||||
|
||||
(guix-command-define-argument-improver
|
||||
guix-command-improve-action-argument
|
||||
'(("graph" :char ?G)
|
||||
("environment" :char ?E)
|
||||
("publish" :char ?u)
|
||||
("pull" :char ?P)
|
||||
("size" :char ?z)))
|
||||
|
||||
(guix-command-define-argument-improver
|
||||
guix-command-improve-common-argument
|
||||
'(("--help" :switch? nil)
|
||||
("--version" :switch? nil)))
|
||||
|
||||
(guix-command-define-argument-improver
|
||||
guix-command-improve-target-argument
|
||||
'(("--target" :char ?T)))
|
||||
|
||||
(guix-command-define-argument-improver
|
||||
guix-command-improve-system-type-argument
|
||||
'(("--system" :fun guix-read-system-type)))
|
||||
|
||||
(guix-command-define-argument-improver
|
||||
guix-command-improve-load-path-argument
|
||||
'(("--load-path" :fun read-directory-name)))
|
||||
|
||||
(guix-command-define-argument-improver
|
||||
guix-command-improve-search-paths-argument
|
||||
'(("--search-paths" :char ?P)))
|
||||
|
||||
(guix-command-define-argument-improver
|
||||
guix-command-improve-substitute-urls-argument
|
||||
'(("--substitute-urls" :char ?U)))
|
||||
|
||||
(guix-command-define-argument-improver
|
||||
guix-command-improve-hash-argument
|
||||
'(("--format" :fun guix-read-hash-format)))
|
||||
|
||||
(guix-command-define-argument-improver
|
||||
guix-command-improve-key-policy-argument
|
||||
'(("--key-download" :fun guix-read-key-policy)))
|
||||
|
||||
(defvar guix-command-improve-common-build-argument
|
||||
'(("--no-substitutes" :char ?s)
|
||||
("--no-build-hook" :char ?h)
|
||||
("--max-silent-time" :char ?x)))
|
||||
|
||||
(defun guix-command-improve-common-build-argument (argument)
|
||||
(guix-command-modify-argument-from-alist
|
||||
argument
|
||||
(append guix-command-improve-load-path-argument
|
||||
guix-command-improve-substitute-urls-argument
|
||||
guix-command-improve-common-build-argument)))
|
||||
|
||||
(guix-command-define-argument-improver
|
||||
guix-command-improve-archive-argument
|
||||
'(("--generate-key" :char ?k)))
|
||||
|
||||
(guix-command-define-argument-improver
|
||||
guix-command-improve-build-argument
|
||||
'(("--no-grafts" :char ?g)
|
||||
("--root" :fun guix-read-file-name)
|
||||
("--sources" :char ?S :fun guix-read-source-type :switch? nil)
|
||||
("--with-source" :fun guix-read-file-name)))
|
||||
|
||||
(guix-command-define-argument-improver
|
||||
guix-command-improve-environment-argument
|
||||
'(("--exec" :fun read-shell-command)
|
||||
("--load" :fun guix-read-file-name)))
|
||||
|
||||
(guix-command-define-argument-improver
|
||||
guix-command-improve-gc-argument
|
||||
'(("--list-dead" :char ?D)
|
||||
("--list-live" :char ?L)
|
||||
("--referrers" :char ?f)
|
||||
("--verify" :fun guix-read-verify-options-string)))
|
||||
|
||||
(guix-command-define-argument-improver
|
||||
guix-command-improve-graph-argument
|
||||
'(("--type" :fun guix-read-graph-type)))
|
||||
|
||||
(guix-command-define-argument-improver
|
||||
guix-command-improve-import-argument
|
||||
'(("cran" :char ?r)))
|
||||
|
||||
(guix-command-define-argument-improver
|
||||
guix-command-improve-import-elpa-argument
|
||||
'(("--archive" :fun guix-read-elpa-archive)))
|
||||
|
||||
(guix-command-define-argument-improver
|
||||
guix-command-improve-lint-argument
|
||||
'(("--checkers" :fun guix-read-lint-checker-names-string)))
|
||||
|
||||
(guix-command-define-argument-improver
|
||||
guix-command-improve-package-argument
|
||||
;; Unlike all other options, --install/--remove do not have a form
|
||||
;; '--install=foo,bar' but '--install foo bar' instead, so we need
|
||||
;; some tweaks.
|
||||
'(("--install"
|
||||
:name "--install " :fun guix-read-package-names-string
|
||||
:switch? nil :option? t)
|
||||
("--remove"
|
||||
:name "--remove " :fun guix-read-package-names-string
|
||||
:switch? nil :option? t)
|
||||
("--install-from-file" :fun guix-read-file-name)
|
||||
("--manifest" :fun guix-read-file-name)
|
||||
("--do-not-upgrade" :char ?U)
|
||||
("--roll-back" :char ?R)
|
||||
("--show" :char ?w :fun guix-read-package-name)))
|
||||
|
||||
(guix-command-define-argument-improver
|
||||
guix-command-improve-refresh-argument
|
||||
'(("--select" :fun guix-read-refresh-subset)
|
||||
("--key-server" :char ?S)))
|
||||
|
||||
(guix-command-define-argument-improver
|
||||
guix-command-improve-size-argument
|
||||
'(("--map-file" :fun guix-read-file-name)))
|
||||
|
||||
(guix-command-define-argument-improver
|
||||
guix-command-improve-system-argument
|
||||
'(("disk-image" :char ?D)
|
||||
("vm-image" :char ?V)
|
||||
("--on-error" :char ?E)
|
||||
("--no-grub" :char ?g)
|
||||
("--full-boot" :char ?b)))
|
||||
|
||||
(defvar guix-command-argument-improvers
|
||||
'((()
|
||||
guix-command-improve-action-argument)
|
||||
(("archive")
|
||||
guix-command-improve-common-build-argument
|
||||
guix-command-improve-target-argument
|
||||
guix-command-improve-system-type-argument
|
||||
guix-command-improve-archive-argument)
|
||||
(("build")
|
||||
guix-command-improve-common-build-argument
|
||||
guix-command-improve-target-argument
|
||||
guix-command-improve-system-type-argument
|
||||
guix-command-improve-build-argument)
|
||||
(("download")
|
||||
guix-command-improve-hash-argument)
|
||||
(("hash")
|
||||
guix-command-improve-hash-argument)
|
||||
(("environment")
|
||||
guix-command-improve-common-build-argument
|
||||
guix-command-improve-search-paths-argument
|
||||
guix-command-improve-system-type-argument
|
||||
guix-command-improve-environment-argument)
|
||||
(("gc")
|
||||
guix-command-improve-gc-argument)
|
||||
(("graph")
|
||||
guix-command-improve-graph-argument)
|
||||
(("import")
|
||||
guix-command-improve-import-argument)
|
||||
(("import" "gnu")
|
||||
guix-command-improve-key-policy-argument)
|
||||
(("import" "elpa")
|
||||
guix-command-improve-import-elpa-argument)
|
||||
(("lint")
|
||||
guix-command-improve-lint-argument)
|
||||
(("package")
|
||||
guix-command-improve-common-build-argument
|
||||
guix-command-improve-search-paths-argument
|
||||
guix-command-improve-package-argument)
|
||||
(("refresh")
|
||||
guix-command-improve-key-policy-argument
|
||||
guix-command-improve-refresh-argument)
|
||||
(("size")
|
||||
guix-command-improve-system-type-argument
|
||||
guix-command-improve-substitute-urls-argument
|
||||
guix-command-improve-size-argument)
|
||||
(("system")
|
||||
guix-command-improve-common-build-argument
|
||||
guix-command-improve-system-argument))
|
||||
"Alist of guix commands and argument improvers for them.")
|
||||
|
||||
(defun guix-command-improve-argument (argument improvers)
|
||||
"Return ARGUMENT modified with IMPROVERS."
|
||||
(or (cl-some (lambda (improver)
|
||||
(funcall improver argument))
|
||||
improvers)
|
||||
argument))
|
||||
|
||||
(defun guix-command-improve-arguments (arguments commands)
|
||||
"Return ARGUMENTS for 'guix COMMANDS ...' modified for popup interface."
|
||||
(let ((improvers (cons 'guix-command-improve-common-argument
|
||||
(guix-assoc-value guix-command-argument-improvers
|
||||
commands))))
|
||||
(mapcar (lambda (argument)
|
||||
(guix-command-improve-argument argument improvers))
|
||||
arguments)))
|
||||
|
||||
(defun guix-command-parse-arguments (&optional commands)
|
||||
"Return a list of parsed 'guix COMMANDS ...' arguments."
|
||||
(with-temp-buffer
|
||||
(insert (guix-help-string commands))
|
||||
(let (args)
|
||||
(guix-while-search guix-help-parse-option-regexp
|
||||
(let* ((short (match-string-no-properties 1))
|
||||
(name (match-string-no-properties 2))
|
||||
(arg (match-string-no-properties 3))
|
||||
(doc (match-string-no-properties 4))
|
||||
(char (if short
|
||||
(elt short 1) ; short option letter
|
||||
(elt name 2))) ; first letter of the long option
|
||||
;; If "--foo=bar" or "--foo[=bar]" then it is 'option'.
|
||||
(option? (not (string= "" arg)))
|
||||
;; If "--foo" or "--foo[=bar]" then it is 'switch'.
|
||||
(switch? (or (string= "" arg)
|
||||
(eq ?\[ (elt arg 0)))))
|
||||
(push (guix-command-make-argument
|
||||
:name name
|
||||
:char char
|
||||
:doc doc
|
||||
:switch? switch?
|
||||
:option? option?)
|
||||
args)))
|
||||
(guix-while-search guix-help-parse-command-regexp
|
||||
(let* ((name (match-string-no-properties 1))
|
||||
(char (elt name 0)))
|
||||
(push (guix-command-make-argument
|
||||
:name name
|
||||
:char char
|
||||
:fun (guix-command-action-name commands name)
|
||||
:action? t)
|
||||
args)))
|
||||
args)))
|
||||
|
||||
(defun guix-command-rest-argument (&optional commands)
|
||||
"Return '--' argument for COMMANDS."
|
||||
(cl-flet ((argument (&rest args)
|
||||
(apply #'guix-command-make-argument
|
||||
:name "-- " :char ?= :option? t args)))
|
||||
(let ((command (car commands)))
|
||||
(cond
|
||||
((member command '("archive" "build" "graph" "edit"
|
||||
"environment" "lint" "refresh"))
|
||||
(argument :doc "Packages" :fun 'guix-read-package-names-string))
|
||||
((string= command "download")
|
||||
(argument :doc "URL"))
|
||||
((string= command "gc")
|
||||
(argument :doc "Paths" :fun 'guix-read-file-name))
|
||||
((member command '("hash" "system"))
|
||||
(argument :doc "File" :fun 'guix-read-file-name))
|
||||
((string= command "size")
|
||||
(argument :doc "Package" :fun 'guix-read-package-name))
|
||||
((equal commands '("import" "nix"))
|
||||
(argument :doc "Nixpkgs Attribute"))
|
||||
;; Other 'guix import' subcommands, but not 'import' itself.
|
||||
((and (cdr commands)
|
||||
(string= command "import"))
|
||||
(argument :doc "Package name"))))))
|
||||
|
||||
(defun guix-command-additional-arguments (&optional commands)
|
||||
"Return additional arguments for COMMANDS."
|
||||
(let ((rest-arg (guix-command-rest-argument commands)))
|
||||
(and rest-arg (list rest-arg))))
|
||||
|
||||
;; Ideally only `guix-command-arguments' function should exist with the
|
||||
;; contents of `guix-command-all-arguments', but we need to make a
|
||||
;; special case for `guix-command-complex-with-shared-arguments' commands.
|
||||
|
||||
(defun guix-command-all-arguments (&optional commands)
|
||||
"Return list of all arguments for 'guix COMMANDS ...'."
|
||||
(let ((parsed (guix-command-parse-arguments commands)))
|
||||
(append (guix-command-improve-arguments parsed commands)
|
||||
(guix-command-additional-arguments commands))))
|
||||
|
||||
(guix-memoized-defalias guix-command-all-arguments-memoize
|
||||
guix-command-all-arguments)
|
||||
|
||||
(defun guix-command-arguments (&optional commands)
|
||||
"Return list of arguments for 'guix COMMANDS ...'."
|
||||
(let ((command (car commands)))
|
||||
(if (member command
|
||||
guix-command-complex-with-shared-arguments)
|
||||
;; Take actions only for 'guix system', and switches+options for
|
||||
;; 'guix system foo'.
|
||||
(funcall (if (null (cdr commands))
|
||||
#'cl-remove-if-not
|
||||
#'cl-remove-if)
|
||||
#'guix-command-argument-action?
|
||||
(guix-command-all-arguments-memoize (list command)))
|
||||
(guix-command-all-arguments commands))))
|
||||
|
||||
(defun guix-command-switch->popup-switch (switch)
|
||||
"Return popup switch from command SWITCH argument."
|
||||
(list (guix-command-argument-char switch)
|
||||
(or (guix-command-argument-doc switch)
|
||||
"Unknown")
|
||||
(guix-command-argument-name switch)))
|
||||
|
||||
(defun guix-command-option->popup-option (option)
|
||||
"Return popup option from command OPTION argument."
|
||||
(list (guix-command-argument-char option)
|
||||
(or (guix-command-argument-doc option)
|
||||
"Unknown")
|
||||
(let ((name (guix-command-argument-name option)))
|
||||
(if (string-match-p " \\'" name) ; ends with space
|
||||
name
|
||||
(concat name "=")))
|
||||
(or (guix-command-argument-fun option)
|
||||
'read-from-minibuffer)))
|
||||
|
||||
(defun guix-command-action->popup-action (action)
|
||||
"Return popup action from command ACTION argument."
|
||||
(list (guix-command-argument-char action)
|
||||
(or (guix-command-argument-doc action)
|
||||
(guix-command-argument-name action)
|
||||
"Unknown")
|
||||
(guix-command-argument-fun action)))
|
||||
|
||||
(defun guix-command-sort-arguments (arguments)
|
||||
"Sort ARGUMENTS by name in alphabetical order."
|
||||
(sort arguments
|
||||
(lambda (a1 a2)
|
||||
(let ((name1 (guix-command-argument-name a1))
|
||||
(name2 (guix-command-argument-name a2)))
|
||||
(cond ((null name1) nil)
|
||||
((null name2) t)
|
||||
(t (string< name1 name2)))))))
|
||||
|
||||
(defun guix-command-switches (arguments)
|
||||
"Return switches from ARGUMENTS."
|
||||
(cl-remove-if-not #'guix-command-argument-switch? arguments))
|
||||
|
||||
(defun guix-command-options (arguments)
|
||||
"Return options from ARGUMENTS."
|
||||
(cl-remove-if-not #'guix-command-argument-option? arguments))
|
||||
|
||||
(defun guix-command-actions (arguments)
|
||||
"Return actions from ARGUMENTS."
|
||||
(cl-remove-if-not #'guix-command-argument-action? arguments))
|
||||
|
||||
(defun guix-command-post-process-args (args)
|
||||
"Adjust appropriately command line ARGS returned from popup command."
|
||||
;; XXX We need to split "--install foo bar" and similar strings into
|
||||
;; lists of strings. But some commands (e.g., 'guix hash') accept a
|
||||
;; file name as the 'rest' argument, and as file names may contain
|
||||
;; spaces, splitting by spaces will break such names. For example, the
|
||||
;; following argument: "-- /tmp/file with spaces" will be transformed
|
||||
;; into the following list: ("--" "/tmp/file" "with" "spaces") instead
|
||||
;; of the wished ("--" "/tmp/file with spaces").
|
||||
(let* (rest
|
||||
(rx (rx string-start
|
||||
(or "-- " "--install " "--remove ")))
|
||||
(args (mapcar (lambda (arg)
|
||||
(if (string-match-p rx arg)
|
||||
(progn (push (split-string arg) rest)
|
||||
nil)
|
||||
arg))
|
||||
args)))
|
||||
(if rest
|
||||
(apply #'append (delq nil args) rest)
|
||||
args)))
|
||||
|
||||
|
||||
;;; 'Execute' actions
|
||||
|
||||
(defvar guix-command-default-execute-arguments
|
||||
(list
|
||||
(guix-command-make-argument
|
||||
:name "repl" :char ?r :doc "Run in Guix REPL")
|
||||
(guix-command-make-argument
|
||||
:name "shell" :char ?s :doc "Run in shell")
|
||||
(guix-command-make-argument
|
||||
:name "copy" :char ?c :doc "Copy command line"))
|
||||
"List of default 'execute' action arguments.")
|
||||
|
||||
(defvar guix-command-additional-execute-arguments
|
||||
(let ((graph-arg (guix-command-make-argument
|
||||
:name "view" :char ?v :doc "View graph")))
|
||||
`((("build")
|
||||
,(guix-command-make-argument
|
||||
:name "log" :char ?l :doc "View build log"))
|
||||
(("graph") ,graph-arg)
|
||||
(("size")
|
||||
,(guix-command-make-argument
|
||||
:name "view" :char ?v :doc "View map"))
|
||||
(("system" "dmd-graph") ,graph-arg)
|
||||
(("system" "extension-graph") ,graph-arg)))
|
||||
"Alist of guix commands and additional 'execute' action arguments.")
|
||||
|
||||
(defun guix-command-execute-arguments (commands)
|
||||
"Return a list of 'execute' action arguments for COMMANDS."
|
||||
(mapcar (lambda (arg)
|
||||
(guix-command-modify-argument arg
|
||||
:action? t
|
||||
:fun (guix-command-action-name
|
||||
commands (guix-command-argument-name arg))))
|
||||
(append guix-command-default-execute-arguments
|
||||
(guix-assoc-value
|
||||
guix-command-additional-execute-arguments commands))))
|
||||
|
||||
(defvar guix-command-special-executors
|
||||
'((("environment")
|
||||
("repl" . guix-run-environment-command-in-repl))
|
||||
(("pull")
|
||||
("repl" . guix-run-pull-command-in-repl))
|
||||
(("build")
|
||||
("log" . guix-run-view-build-log))
|
||||
(("graph")
|
||||
("view" . guix-run-view-graph))
|
||||
(("size")
|
||||
("view" . guix-run-view-size-map))
|
||||
(("system" "dmd-graph")
|
||||
("view" . guix-run-view-graph))
|
||||
(("system" "extension-graph")
|
||||
("view" . guix-run-view-graph)))
|
||||
"Alist of guix commands and alists of special executers for them.
|
||||
See also `guix-command-default-executors'.")
|
||||
|
||||
(defvar guix-command-default-executors
|
||||
'(("repl" . guix-run-command-in-repl)
|
||||
("shell" . guix-run-command-in-shell)
|
||||
("copy" . guix-copy-command-as-kill))
|
||||
"Alist of default executers for action names.")
|
||||
|
||||
(defun guix-command-executor (commands name)
|
||||
"Return function to run command line arguments for guix COMMANDS."
|
||||
(or (guix-assoc-value guix-command-special-executors commands name)
|
||||
(guix-assoc-value guix-command-default-executors name)))
|
||||
|
||||
(defun guix-run-environment-command-in-repl (args)
|
||||
"Run 'guix ARGS ...' environment command in Guix REPL."
|
||||
;; As 'guix environment' usually tries to run another process, it may
|
||||
;; be fun but not wise to run this command in Geiser REPL.
|
||||
(when (or (member "--dry-run" args)
|
||||
(member "--search-paths" args)
|
||||
(when (y-or-n-p
|
||||
(format "'%s' command will spawn an external process.
|
||||
Do you really want to execute this command in Geiser REPL? "
|
||||
(guix-command-string args)))
|
||||
(message "May \"M-x shell-mode\" be with you!")
|
||||
t))
|
||||
(guix-run-command-in-repl args)))
|
||||
|
||||
(defun guix-run-pull-command-in-repl (args)
|
||||
"Run 'guix ARGS ...' pull command in Guix REPL.
|
||||
Perform pull-specific actions after operation, see
|
||||
`guix-after-pull-hook' and `guix-update-after-pull'."
|
||||
(guix-eval-in-repl
|
||||
(apply #'guix-make-guile-expression 'guix-command args)
|
||||
nil 'pull))
|
||||
|
||||
(defun guix-run-view-build-log (args)
|
||||
"Add --log-file to ARGS, run 'guix ARGS ...' build command, and
|
||||
open the log file(s)."
|
||||
(let* ((args (if (member "--log-file" args)
|
||||
args
|
||||
(apply #'list (car args) "--log-file" (cdr args))))
|
||||
(output (guix-command-output args))
|
||||
(files (split-string output "\n" t)))
|
||||
(dolist (file files)
|
||||
(guix-find-file-or-url file)
|
||||
(guix-build-log-mode))))
|
||||
|
||||
(defun guix-run-view-graph (args)
|
||||
"Run 'guix ARGS ...' graph command, make the image and open it."
|
||||
(let* ((graph-file (guix-dot-file-name))
|
||||
(dot-args (guix-dot-arguments graph-file)))
|
||||
(if (guix-eval-read (guix-make-guile-expression
|
||||
'pipe-guix-output args dot-args))
|
||||
(guix-find-file graph-file)
|
||||
(error "Couldn't create a graph"))))
|
||||
|
||||
(defun guix-run-view-size-map (args)
|
||||
"Run 'guix ARGS ...' size command, and open the map file."
|
||||
(let* ((wished-map-file
|
||||
(cl-some (lambda (arg)
|
||||
(and (string-match "--map-file=\\(.+\\)" arg)
|
||||
(match-string 1 arg)))
|
||||
args))
|
||||
(map-file (or wished-map-file (guix-png-file-name)))
|
||||
(args (if wished-map-file
|
||||
args
|
||||
(apply #'list
|
||||
(car args)
|
||||
(concat "--map-file=" map-file)
|
||||
(cdr args)))))
|
||||
(guix-command-output args)
|
||||
(guix-find-file map-file)))
|
||||
|
||||
|
||||
;;; Generating popups, actions, etc.
|
||||
|
||||
(defmacro guix-command-define-popup-action (name &optional commands)
|
||||
"Define NAME function to generate (if needed) and run popup for COMMANDS."
|
||||
(declare (indent 1) (debug t))
|
||||
(let* ((popup-fun (guix-command-symbol `(,@commands "popup")))
|
||||
(doc (format "Call `%s' (generate it if needed)."
|
||||
popup-fun)))
|
||||
`(defun ,name (&optional arg)
|
||||
,doc
|
||||
(interactive "P")
|
||||
(unless (fboundp ',popup-fun)
|
||||
(guix-command-generate-popup ',popup-fun ',commands))
|
||||
(,popup-fun arg))))
|
||||
|
||||
(defmacro guix-command-define-execute-action (name executor
|
||||
&optional commands)
|
||||
"Define NAME function to execute the current action for guix COMMANDS.
|
||||
EXECUTOR function is called with the current command line arguments."
|
||||
(declare (indent 1) (debug t))
|
||||
(let* ((arguments-fun (guix-command-symbol `(,@commands "arguments")))
|
||||
(doc (format "Call `%s' with the current popup arguments."
|
||||
executor)))
|
||||
`(defun ,name (&rest args)
|
||||
,doc
|
||||
(interactive (,arguments-fun))
|
||||
(,executor (append ',commands
|
||||
(guix-command-post-process-args args))))))
|
||||
|
||||
(defun guix-command-generate-popup-actions (actions &optional commands)
|
||||
"Generate 'popup' commands from ACTIONS arguments for guix COMMANDS."
|
||||
(dolist (action actions)
|
||||
(let ((fun (guix-command-argument-fun action)))
|
||||
(unless (fboundp fun)
|
||||
(eval `(guix-command-define-popup-action ,fun
|
||||
,(append commands
|
||||
(list (guix-command-argument-name action)))))))))
|
||||
|
||||
(defun guix-command-generate-execute-actions (actions &optional commands)
|
||||
"Generate 'execute' commands from ACTIONS arguments for guix COMMANDS."
|
||||
(dolist (action actions)
|
||||
(let ((fun (guix-command-argument-fun action)))
|
||||
(unless (fboundp fun)
|
||||
(eval `(guix-command-define-execute-action ,fun
|
||||
,(guix-command-executor
|
||||
commands (guix-command-argument-name action))
|
||||
,commands))))))
|
||||
|
||||
(defun guix-command-generate-popup (name &optional commands)
|
||||
"Define NAME popup with 'guix COMMANDS ...' interface."
|
||||
(let* ((command (car commands))
|
||||
(man-page (concat "guix" (and command (concat "-" command))))
|
||||
(doc (format "Popup window for '%s' command."
|
||||
(guix-concat-strings (cons "guix" commands)
|
||||
" ")))
|
||||
(args (guix-command-arguments commands))
|
||||
(switches (guix-command-sort-arguments
|
||||
(guix-command-switches args)))
|
||||
(options (guix-command-sort-arguments
|
||||
(guix-command-options args)))
|
||||
(popup-actions (guix-command-sort-arguments
|
||||
(guix-command-actions args)))
|
||||
(execute-actions (unless popup-actions
|
||||
(guix-command-execute-arguments commands)))
|
||||
(actions (or popup-actions execute-actions)))
|
||||
(if popup-actions
|
||||
(guix-command-generate-popup-actions popup-actions commands)
|
||||
(guix-command-generate-execute-actions execute-actions commands))
|
||||
(eval
|
||||
`(guix-define-popup ,name
|
||||
,doc
|
||||
'guix-commands
|
||||
:man-page ,man-page
|
||||
:switches ',(mapcar #'guix-command-switch->popup-switch switches)
|
||||
:options ',(mapcar #'guix-command-option->popup-option options)
|
||||
:actions ',(mapcar #'guix-command-action->popup-action actions)
|
||||
:max-action-columns 4))))
|
||||
|
||||
;;;###autoload (autoload 'guix "guix-command" "Popup window for 'guix'." t)
|
||||
(guix-command-define-popup-action guix)
|
||||
|
||||
(defalias 'guix-edit-action #'guix-edit)
|
||||
|
||||
|
||||
(defvar guix-command-font-lock-keywords
|
||||
(eval-when-compile
|
||||
`((,(rx "("
|
||||
(group "guix-command-define-"
|
||||
(or "popup-action"
|
||||
"execute-action"
|
||||
"argument-improver"))
|
||||
symbol-end
|
||||
(zero-or-more blank)
|
||||
(zero-or-one
|
||||
(group (one-or-more (or (syntax word) (syntax symbol))))))
|
||||
(1 font-lock-keyword-face)
|
||||
(2 font-lock-function-name-face nil t)))))
|
||||
|
||||
(font-lock-add-keywords 'emacs-lisp-mode guix-command-font-lock-keywords)
|
||||
|
||||
(provide 'guix-command)
|
||||
|
||||
;;; guix-command.el ends here
|
||||
@@ -0,0 +1,38 @@
|
||||
;;; guix-config.el --- Compile-time configuration of Guix.
|
||||
|
||||
;; Copyright © 2015 Mathieu Lirzin <mthl@openmailbox.org>
|
||||
;; Copyright © 2015 Alex Kost <alezost@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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(defconst guix-config-emacs-interface-directory
|
||||
(replace-regexp-in-string "${prefix}" "@prefix@" "@emacsuidir@"))
|
||||
|
||||
(defconst guix-config-state-directory
|
||||
;; This must match `NIX_STATE_DIR' as defined in `daemon.am'.
|
||||
(or (getenv "NIX_STATE_DIR") "@guix_localstatedir@/guix"))
|
||||
|
||||
(defconst guix-config-guile-program "@GUILE@"
|
||||
"Name of the 'guile' executable defined at configure time.")
|
||||
|
||||
(defconst guix-config-dot-program "@DOT_USER_PROGRAM@"
|
||||
"Name of the 'dot' executable defined at configure time.")
|
||||
|
||||
(provide 'guix-config)
|
||||
|
||||
;;; guix-config.el ends here
|
||||
@@ -0,0 +1,375 @@
|
||||
;;; guix-devel.el --- Development tools -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright © 2015 Alex Kost <alezost@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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file provides commands useful for developing Guix (or even
|
||||
;; arbitrary Guile code) with Geiser.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'lisp-mode)
|
||||
(require 'guix-guile)
|
||||
(require 'guix-geiser)
|
||||
(require 'guix-utils)
|
||||
(require 'guix-base)
|
||||
|
||||
(defgroup guix-devel nil
|
||||
"Settings for Guix development utils."
|
||||
:group 'guix)
|
||||
|
||||
(defgroup guix-devel-faces nil
|
||||
"Faces for `guix-devel-mode'."
|
||||
:group 'guix-devel
|
||||
:group 'guix-faces)
|
||||
|
||||
(defface guix-devel-modify-phases-keyword
|
||||
'((t :inherit font-lock-preprocessor-face))
|
||||
"Face for a `modify-phases' keyword ('delete', 'replace', etc.)."
|
||||
:group 'guix-devel-faces)
|
||||
|
||||
(defface guix-devel-gexp-symbol
|
||||
'((t :inherit font-lock-keyword-face))
|
||||
"Face for gexp symbols ('#~', '#$', etc.).
|
||||
See Info node `(guix) G-Expressions'."
|
||||
:group 'guix-devel-faces)
|
||||
|
||||
(defcustom guix-devel-activate-mode t
|
||||
"If non-nil, then `guix-devel-mode' is automatically activated
|
||||
in Scheme buffers."
|
||||
:type 'boolean
|
||||
:group 'guix-devel)
|
||||
|
||||
(defun guix-devel-use-modules (&rest modules)
|
||||
"Use guile MODULES."
|
||||
(apply #'guix-geiser-call "use-modules" modules))
|
||||
|
||||
(defun guix-devel-use-module (&optional module)
|
||||
"Use guile MODULE in the current Geiser REPL.
|
||||
MODULE is a string with the module name - e.g., \"(ice-9 match)\".
|
||||
Interactively, use the module defined by the current scheme file."
|
||||
(interactive (list (guix-guile-current-module)))
|
||||
(guix-devel-use-modules module)
|
||||
(message "Using %s module." module))
|
||||
|
||||
(defun guix-devel-copy-module-as-kill ()
|
||||
"Put the name of the current guile module into `kill-ring'."
|
||||
(interactive)
|
||||
(guix-copy-as-kill (guix-guile-current-module)))
|
||||
|
||||
(defun guix-devel-setup-repl (&optional repl)
|
||||
"Setup REPL for using `guix-devel-...' commands."
|
||||
(guix-devel-use-modules "(guix monad-repl)"
|
||||
"(guix scripts)"
|
||||
"(guix store)"
|
||||
"(guix ui)")
|
||||
;; Without this workaround, the warning/build output disappears. See
|
||||
;; <https://github.com/jaor/geiser/issues/83> for details.
|
||||
(guix-geiser-eval-in-repl-synchronously
|
||||
"(begin
|
||||
(guix-warning-port (current-warning-port))
|
||||
(current-build-output-port (current-error-port)))"
|
||||
repl 'no-history 'no-display))
|
||||
|
||||
(defvar guix-devel-repl-processes nil
|
||||
"List of REPL processes configured by `guix-devel-setup-repl'.")
|
||||
|
||||
(defun guix-devel-setup-repl-maybe (&optional repl)
|
||||
"Setup (if needed) REPL for using `guix-devel-...' commands."
|
||||
(let ((process (get-buffer-process (or repl (guix-geiser-repl)))))
|
||||
(when (and process
|
||||
(not (memq process guix-devel-repl-processes)))
|
||||
(guix-devel-setup-repl repl)
|
||||
(push process guix-devel-repl-processes))))
|
||||
|
||||
(defmacro guix-devel-with-definition (def-var &rest body)
|
||||
"Run BODY with the current guile definition bound to DEF-VAR.
|
||||
Bind DEF-VAR variable to the name of the current top-level
|
||||
definition, setup the current REPL, use the current module, and
|
||||
run BODY."
|
||||
(declare (indent 1) (debug (symbolp body)))
|
||||
`(let ((,def-var (guix-guile-current-definition)))
|
||||
(guix-devel-setup-repl-maybe)
|
||||
(guix-devel-use-modules (guix-guile-current-module))
|
||||
,@body))
|
||||
|
||||
(defun guix-devel-build-package-definition ()
|
||||
"Build a package defined by the current top-level variable definition."
|
||||
(interactive)
|
||||
(guix-devel-with-definition def
|
||||
(when (or (not guix-operation-confirm)
|
||||
(guix-operation-prompt (format "Build '%s'?" def)))
|
||||
(guix-geiser-eval-in-repl
|
||||
(concat ",run-in-store "
|
||||
(guix-guile-make-call-expression
|
||||
"build-package" def
|
||||
"#:use-substitutes?" (guix-guile-boolean
|
||||
guix-use-substitutes)
|
||||
"#:dry-run?" (guix-guile-boolean guix-dry-run)))))))
|
||||
|
||||
(defun guix-devel-build-package-source ()
|
||||
"Build the source of the current package definition."
|
||||
(interactive)
|
||||
(guix-devel-with-definition def
|
||||
(when (or (not guix-operation-confirm)
|
||||
(guix-operation-prompt
|
||||
(format "Build '%s' package source?" def)))
|
||||
(guix-geiser-eval-in-repl
|
||||
(concat ",run-in-store "
|
||||
(guix-guile-make-call-expression
|
||||
"build-package-source" def
|
||||
"#:use-substitutes?" (guix-guile-boolean
|
||||
guix-use-substitutes)
|
||||
"#:dry-run?" (guix-guile-boolean guix-dry-run)))))))
|
||||
|
||||
(defun guix-devel-lint-package ()
|
||||
"Check the current package.
|
||||
See Info node `(guix) Invoking guix lint' for details."
|
||||
(interactive)
|
||||
(guix-devel-with-definition def
|
||||
(guix-devel-use-modules "(guix scripts lint)")
|
||||
(when (or (not guix-operation-confirm)
|
||||
(y-or-n-p (format "Lint '%s' package?" def)))
|
||||
(guix-geiser-eval-in-repl
|
||||
(format "(run-checkers %s)" def)))))
|
||||
|
||||
|
||||
;;; Font-lock
|
||||
|
||||
(defvar guix-devel-modify-phases-keyword-regexp
|
||||
(rx (+ word))
|
||||
"Regexp for a 'modify-phases' keyword ('delete', 'replace', etc.).")
|
||||
|
||||
(defun guix-devel-modify-phases-font-lock-matcher (limit)
|
||||
"Find a 'modify-phases' keyword.
|
||||
This function is used as a MATCHER for `font-lock-keywords'."
|
||||
(ignore-errors
|
||||
(down-list)
|
||||
(or (re-search-forward guix-devel-modify-phases-keyword-regexp
|
||||
limit t)
|
||||
(set-match-data nil))
|
||||
(up-list)
|
||||
t))
|
||||
|
||||
(defun guix-devel-modify-phases-font-lock-pre ()
|
||||
"Skip the next sexp, and return the end point of the current list.
|
||||
This function is used as a PRE-MATCH-FORM for `font-lock-keywords'
|
||||
to find 'modify-phases' keywords."
|
||||
(let ((in-comment? (nth 4 (syntax-ppss))))
|
||||
;; If 'modify-phases' is commented, do not try to search for its
|
||||
;; keywords.
|
||||
(unless in-comment?
|
||||
(ignore-errors (forward-sexp))
|
||||
(save-excursion (up-list) (point)))))
|
||||
|
||||
(defconst guix-devel-keywords
|
||||
'("call-with-compressed-output-port"
|
||||
"call-with-container"
|
||||
"call-with-decompressed-port"
|
||||
"call-with-derivation-narinfo"
|
||||
"call-with-derivation-substitute"
|
||||
"call-with-error-handling"
|
||||
"call-with-temporary-directory"
|
||||
"call-with-temporary-output-file"
|
||||
"define-enumerate-type"
|
||||
"define-gexp-compiler"
|
||||
"define-lift"
|
||||
"define-monad"
|
||||
"define-operation"
|
||||
"define-record-type*"
|
||||
"emacs-substitute-sexps"
|
||||
"emacs-substitute-variables"
|
||||
"mbegin"
|
||||
"mlet"
|
||||
"mlet*"
|
||||
"munless"
|
||||
"mwhen"
|
||||
"run-with-state"
|
||||
"run-with-store"
|
||||
"signature-case"
|
||||
"substitute*"
|
||||
"substitute-keyword-arguments"
|
||||
"test-assertm"
|
||||
"use-package-modules"
|
||||
"use-service-modules"
|
||||
"use-system-modules"
|
||||
"with-atomic-file-output"
|
||||
"with-atomic-file-replacement"
|
||||
"with-derivation-narinfo"
|
||||
"with-derivation-substitute"
|
||||
"with-directory-excursion"
|
||||
"with-error-handling"
|
||||
"with-monad"
|
||||
"with-mutex"
|
||||
"with-store"))
|
||||
|
||||
(defvar guix-devel-font-lock-keywords
|
||||
`((,(rx (or "#~" "#$" "#$@" "#+" "#+@")) .
|
||||
'guix-devel-gexp-symbol)
|
||||
(,(guix-guile-keyword-regexp (regexp-opt guix-devel-keywords))
|
||||
(1 'font-lock-keyword-face))
|
||||
(,(guix-guile-keyword-regexp "modify-phases")
|
||||
(1 'font-lock-keyword-face)
|
||||
(guix-devel-modify-phases-font-lock-matcher
|
||||
(guix-devel-modify-phases-font-lock-pre)
|
||||
nil
|
||||
(0 'guix-devel-modify-phases-keyword nil t))))
|
||||
"A list of `font-lock-keywords' for `guix-devel-mode'.")
|
||||
|
||||
|
||||
;;; Indentation
|
||||
|
||||
(defmacro guix-devel-scheme-indent (&rest rules)
|
||||
"Set `scheme-indent-function' according to RULES.
|
||||
Each rule should have a form (SYMBOL VALUE). See `put' for details."
|
||||
(declare (indent 0))
|
||||
`(progn
|
||||
,@(mapcar (lambda (rule)
|
||||
`(put ',(car rule) 'scheme-indent-function ,(cadr rule)))
|
||||
rules)))
|
||||
|
||||
(defun guix-devel-indent-package (state indent-point normal-indent)
|
||||
"Indentation rule for 'package' form."
|
||||
(let* ((package-eol (line-end-position))
|
||||
(count (if (and (ignore-errors (down-list) t)
|
||||
(< (point) package-eol)
|
||||
(looking-at "inherit\\>"))
|
||||
1
|
||||
0)))
|
||||
(lisp-indent-specform count state indent-point normal-indent)))
|
||||
|
||||
(defun guix-devel-indent-modify-phases-keyword (count)
|
||||
"Return indentation function for 'modify-phases' keywords."
|
||||
(lambda (state indent-point normal-indent)
|
||||
(when (ignore-errors
|
||||
(goto-char (nth 1 state)) ; start of keyword sexp
|
||||
(backward-up-list)
|
||||
(looking-at "(modify-phases\\>"))
|
||||
(lisp-indent-specform count state indent-point normal-indent))))
|
||||
|
||||
(defalias 'guix-devel-indent-modify-phases-keyword-1
|
||||
(guix-devel-indent-modify-phases-keyword 1))
|
||||
(defalias 'guix-devel-indent-modify-phases-keyword-2
|
||||
(guix-devel-indent-modify-phases-keyword 2))
|
||||
|
||||
(guix-devel-scheme-indent
|
||||
(bag 0)
|
||||
(build-system 0)
|
||||
(call-with-compressed-output-port 2)
|
||||
(call-with-container 1)
|
||||
(call-with-decompressed-port 2)
|
||||
(call-with-error-handling 0)
|
||||
(container-excursion 1)
|
||||
(emacs-batch-edit-file 1)
|
||||
(emacs-batch-eval 0)
|
||||
(emacs-substitute-sexps 1)
|
||||
(emacs-substitute-variables 1)
|
||||
(file-system 0)
|
||||
(graft 0)
|
||||
(manifest-entry 0)
|
||||
(manifest-pattern 0)
|
||||
(mbegin 1)
|
||||
(mlet 2)
|
||||
(mlet* 2)
|
||||
(modify-phases 1)
|
||||
(munless 1)
|
||||
(mwhen 1)
|
||||
(operating-system 0)
|
||||
(origin 0)
|
||||
(package 'guix-devel-indent-package)
|
||||
(run-with-state 1)
|
||||
(run-with-store 1)
|
||||
(signature-case 1)
|
||||
(substitute* 1)
|
||||
(substitute-keyword-arguments 1)
|
||||
(test-assertm 1)
|
||||
(with-atomic-file-output 1)
|
||||
(with-derivation-narinfo 1)
|
||||
(with-derivation-substitute 2)
|
||||
(with-directory-excursion 1)
|
||||
(with-error-handling 0)
|
||||
(with-monad 1)
|
||||
(with-mutex 1)
|
||||
(with-store 1)
|
||||
(wrap-program 1)
|
||||
|
||||
;; 'modify-phases' keywords:
|
||||
(replace 'guix-devel-indent-modify-phases-keyword-1)
|
||||
(add-after 'guix-devel-indent-modify-phases-keyword-2)
|
||||
(add-before 'guix-devel-indent-modify-phases-keyword-2))
|
||||
|
||||
|
||||
(defvar guix-devel-keys-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(define-key map (kbd "b") 'guix-devel-build-package-definition)
|
||||
(define-key map (kbd "s") 'guix-devel-build-package-source)
|
||||
(define-key map (kbd "l") 'guix-devel-lint-package)
|
||||
(define-key map (kbd "k") 'guix-devel-copy-module-as-kill)
|
||||
(define-key map (kbd "u") 'guix-devel-use-module)
|
||||
map)
|
||||
"Keymap with subkeys for `guix-devel-mode-map'.")
|
||||
|
||||
(defvar guix-devel-mode-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(define-key map (kbd "C-c .") guix-devel-keys-map)
|
||||
map)
|
||||
"Keymap for `guix-devel-mode'.")
|
||||
|
||||
;;;###autoload
|
||||
(define-minor-mode guix-devel-mode
|
||||
"Minor mode for `scheme-mode' buffers.
|
||||
|
||||
With a prefix argument ARG, enable the mode if ARG is positive,
|
||||
and disable it otherwise. If called from Lisp, enable the mode
|
||||
if ARG is omitted or nil.
|
||||
|
||||
When Guix Devel mode is enabled, it provides the following key
|
||||
bindings:
|
||||
|
||||
\\{guix-devel-mode-map}"
|
||||
:init-value nil
|
||||
:lighter " Guix"
|
||||
:keymap guix-devel-mode-map
|
||||
(if guix-devel-mode
|
||||
(progn
|
||||
(setq-local font-lock-multiline t)
|
||||
(font-lock-add-keywords nil guix-devel-font-lock-keywords))
|
||||
(setq-local font-lock-multiline nil)
|
||||
(font-lock-remove-keywords nil guix-devel-font-lock-keywords))
|
||||
(when font-lock-mode
|
||||
(font-lock-fontify-buffer)))
|
||||
|
||||
;;;###autoload
|
||||
(defun guix-devel-activate-mode-maybe ()
|
||||
"Activate `guix-devel-mode' depending on
|
||||
`guix-devel-activate-mode' variable."
|
||||
(when guix-devel-activate-mode
|
||||
(guix-devel-mode)))
|
||||
|
||||
|
||||
(defvar guix-devel-emacs-font-lock-keywords
|
||||
(eval-when-compile
|
||||
`((,(rx "(" (group "guix-devel-with-definition") symbol-end) . 1))))
|
||||
|
||||
(font-lock-add-keywords 'emacs-lisp-mode
|
||||
guix-devel-emacs-font-lock-keywords)
|
||||
|
||||
(provide 'guix-devel)
|
||||
|
||||
;;; guix-devel.el ends here
|
||||
@@ -0,0 +1,103 @@
|
||||
;;; guix-emacs.el --- Emacs packages installed with Guix
|
||||
|
||||
;; Copyright © 2014 Alex Kost <alezost@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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file provides auxiliary code for working with Emacs packages
|
||||
;; installed with Guix.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'guix-profiles)
|
||||
(require 'cl-lib)
|
||||
|
||||
(defcustom guix-emacs-activate-after-operation t
|
||||
"Activate Emacs packages after installing.
|
||||
If nil, do not load autoloads of the Emacs packages after
|
||||
they are successfully installed."
|
||||
:type 'boolean
|
||||
:group 'guix)
|
||||
|
||||
(defvar guix-emacs-autoloads nil
|
||||
"List of the last loaded Emacs autoloads.")
|
||||
|
||||
(defun guix-emacs-directory (&optional profile)
|
||||
"Return directory with Emacs packages installed in PROFILE.
|
||||
If PROFILE is nil, use `guix-user-profile'."
|
||||
(expand-file-name "share/emacs/site-lisp"
|
||||
(or profile guix-user-profile)))
|
||||
|
||||
(defun guix-emacs-find-autoloads-in-directory (directory)
|
||||
"Return list of Emacs 'autoloads' files in DIRECTORY."
|
||||
(directory-files directory 'full-name "-autoloads\\.el\\'" 'no-sort))
|
||||
|
||||
(defun guix-emacs-subdirs (directory)
|
||||
"Return list of DIRECTORY subdirectories."
|
||||
(cl-remove-if (lambda (file)
|
||||
(or (string-match-p (rx "/." string-end) file)
|
||||
(string-match-p (rx "/.." string-end) file)
|
||||
(not (file-directory-p file))))
|
||||
(directory-files directory 'full-name nil 'no-sort)))
|
||||
|
||||
(defun guix-emacs-find-autoloads (&optional profile)
|
||||
"Return list of autoloads of Emacs packages installed in PROFILE.
|
||||
If PROFILE is nil, use `guix-user-profile'.
|
||||
Return nil if there are no emacs packages installed in PROFILE."
|
||||
(let ((elisp-root-dir (guix-emacs-directory profile)))
|
||||
(if (file-directory-p elisp-root-dir)
|
||||
(let ((elisp-pkgs-dir (expand-file-name "guix.d" elisp-root-dir))
|
||||
(root-autoloads (guix-emacs-find-autoloads-in-directory
|
||||
elisp-root-dir)))
|
||||
(if (file-directory-p elisp-pkgs-dir)
|
||||
(let ((pkgs-autoloads
|
||||
(cl-mapcan #'guix-emacs-find-autoloads-in-directory
|
||||
(guix-emacs-subdirs elisp-pkgs-dir))))
|
||||
(append root-autoloads pkgs-autoloads))
|
||||
root-autoloads))
|
||||
(message "Directory '%s' does not exist." elisp-root-dir)
|
||||
nil)))
|
||||
|
||||
;;;###autoload
|
||||
(defun guix-emacs-load-autoloads (&optional all)
|
||||
"Load autoloads for Emacs packages installed in a user profile.
|
||||
Add autoloads directories to `load-path'.
|
||||
If ALL is nil, activate only those packages that were installed
|
||||
after the last activation, otherwise activate all Emacs packages
|
||||
installed in `guix-user-profile'."
|
||||
(interactive "P")
|
||||
(let* ((autoloads (guix-emacs-find-autoloads))
|
||||
(files (if all
|
||||
autoloads
|
||||
(cl-nset-difference autoloads guix-emacs-autoloads
|
||||
:test #'string=))))
|
||||
(dolist (file files)
|
||||
(cl-pushnew (file-name-directory file) load-path
|
||||
:test #'string=)
|
||||
(load file 'noerror))
|
||||
(setq guix-emacs-autoloads autoloads)))
|
||||
|
||||
(defun guix-emacs-load-autoloads-maybe ()
|
||||
"Load autoloads for Emacs packages if needed.
|
||||
See `guix-emacs-activate-after-operation' for details."
|
||||
(and guix-emacs-activate-after-operation
|
||||
(guix-emacs-load-autoloads)))
|
||||
|
||||
(provide 'guix-emacs)
|
||||
|
||||
;;; guix-emacs.el ends here
|
||||
@@ -0,0 +1,88 @@
|
||||
;;; guix-external.el --- External programs -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright © 2015 Alex Kost <alezost@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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file provides auxiliary code for running external programs.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'guix-config)
|
||||
|
||||
(defgroup guix-external nil
|
||||
"Settings for external programs."
|
||||
:group 'guix)
|
||||
|
||||
(defcustom guix-guile-program guix-config-guile-program
|
||||
"Name of the 'guile' executable used for Guix REPL.
|
||||
May be either a string (the name of the executable) or a list of
|
||||
strings of the form:
|
||||
|
||||
(NAME . ARGS)
|
||||
|
||||
Where ARGS is a list of arguments to the guile program."
|
||||
:type 'string
|
||||
:group 'guix-external)
|
||||
|
||||
(defcustom guix-dot-program
|
||||
(if (file-name-absolute-p guix-config-dot-program)
|
||||
guix-config-dot-program
|
||||
(executable-find "dot"))
|
||||
"Name of the 'dot' executable."
|
||||
:type 'string
|
||||
:group 'guix-external)
|
||||
|
||||
(defcustom guix-dot-default-arguments
|
||||
'("-Tpng")
|
||||
"Default arguments for 'dot' program."
|
||||
:type '(repeat string)
|
||||
:group 'guix-external)
|
||||
|
||||
(defcustom guix-dot-file-name-function #'guix-png-file-name
|
||||
"Function used to define a file name of a temporary 'dot' file.
|
||||
The function is called without arguments."
|
||||
:type '(choice (function-item guix-png-file-name)
|
||||
(function :tag "Other function"))
|
||||
:group 'guix-external)
|
||||
|
||||
(defun guix-dot-arguments (output-file &rest args)
|
||||
"Return a list of dot arguments for writing a graph into OUTPUT-FILE.
|
||||
If ARGS is nil, use `guix-dot-default-arguments'."
|
||||
(or guix-dot-program
|
||||
(error (concat "Couldn't find 'dot'.\n"
|
||||
"Set guix-dot-program to a proper value")))
|
||||
(apply #'list
|
||||
guix-dot-program
|
||||
(concat "-o" output-file)
|
||||
(or args guix-dot-default-arguments)))
|
||||
|
||||
(defun guix-dot-file-name ()
|
||||
"Call `guix-dot-file-name-function'."
|
||||
(funcall guix-dot-file-name-function))
|
||||
|
||||
(defun guix-png-file-name ()
|
||||
"Return '.png' file name in the `temporary-file-directory'."
|
||||
(concat (make-temp-name
|
||||
(concat (file-name-as-directory temporary-file-directory)
|
||||
"guix-emacs-graph-"))
|
||||
".png"))
|
||||
|
||||
(provide 'guix-external)
|
||||
|
||||
;;; guix-external.el ends here
|
||||
@@ -0,0 +1,114 @@
|
||||
;;; guix-geiser.el --- Interacting with Geiser -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright © 2015 Alex Kost <alezost@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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file provides functions to evaluate guile code using Geiser.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'geiser-mode)
|
||||
(require 'guix-guile)
|
||||
|
||||
(defun guix-geiser-repl ()
|
||||
"Return the current Geiser REPL."
|
||||
(or geiser-repl--repl
|
||||
(geiser-repl--repl/impl 'guile)
|
||||
(error "Geiser REPL not found")))
|
||||
|
||||
(defun guix-geiser-eval (str &optional repl)
|
||||
"Evaluate STR with guile expression using Geiser REPL.
|
||||
If REPL is nil, use the current Geiser REPL.
|
||||
Return a list of strings with result values of evaluation."
|
||||
(with-current-buffer (or repl (guix-geiser-repl))
|
||||
(let ((res (geiser-eval--send/wait `(:eval (:scm ,str)))))
|
||||
(if (geiser-eval--retort-error res)
|
||||
(error "Error in evaluating guile expression: %s"
|
||||
(geiser-eval--retort-output res))
|
||||
(cdr (assq 'result res))))))
|
||||
|
||||
(defun guix-geiser-eval-read (str &optional repl)
|
||||
"Evaluate STR with guile expression using Geiser REPL.
|
||||
Return elisp expression of the first result value of evaluation."
|
||||
;; Parsing scheme code with elisp `read' is probably not the best idea.
|
||||
(read (replace-regexp-in-string
|
||||
"#f\\|#<unspecified>" "nil"
|
||||
(replace-regexp-in-string
|
||||
"#t" "t" (car (guix-geiser-eval str repl))))))
|
||||
|
||||
(defun guix-repl-send (cmd &optional save-history)
|
||||
"Send CMD input string to the current REPL buffer.
|
||||
This is the same as `geiser-repl--send', but with SAVE-HISTORY
|
||||
argument. If SAVE-HISTORY is non-nil, save CMD in the REPL
|
||||
history."
|
||||
(when (and cmd (eq major-mode 'geiser-repl-mode))
|
||||
(geiser-repl--prepare-send)
|
||||
(goto-char (point-max))
|
||||
(comint-kill-input)
|
||||
(insert cmd)
|
||||
(let ((comint-input-filter (if save-history
|
||||
comint-input-filter
|
||||
'ignore)))
|
||||
(comint-send-input nil t))))
|
||||
|
||||
(defun guix-geiser-eval-in-repl (str &optional repl no-history no-display)
|
||||
"Switch to Geiser REPL and evaluate STR with guile expression there.
|
||||
If NO-HISTORY is non-nil, do not save STR in the REPL history.
|
||||
If NO-DISPLAY is non-nil, do not switch to the REPL buffer."
|
||||
(let ((repl (or repl (guix-geiser-repl))))
|
||||
(with-current-buffer repl
|
||||
;; XXX Since Geiser 0.8, `geiser-repl--send' has SAVE-HISTORY
|
||||
;; argument, so use this function eventually and remove
|
||||
;; `guix-repl-send'.
|
||||
(guix-repl-send str (not no-history)))
|
||||
(unless no-display
|
||||
(geiser-repl--switch-to-buffer repl))))
|
||||
|
||||
(defun guix-geiser-eval-in-repl-synchronously (str &optional repl
|
||||
no-history no-display)
|
||||
"Evaluate STR in Geiser REPL synchronously, i.e. wait until the
|
||||
REPL operation will be finished.
|
||||
See `guix-geiser-eval-in-repl' for the meaning of arguments."
|
||||
(let* ((repl (if repl (get-buffer repl) (guix-geiser-repl)))
|
||||
(running? nil)
|
||||
(filter (lambda (output)
|
||||
(setq running?
|
||||
(and (get-buffer-process repl)
|
||||
(not (guix-guile-prompt? output))))))
|
||||
(comint-output-filter-functions
|
||||
(cons filter comint-output-filter-functions)))
|
||||
(guix-geiser-eval-in-repl str repl no-history no-display)
|
||||
(while running?
|
||||
(sleep-for 0.1))))
|
||||
|
||||
(defun guix-geiser-call (proc &rest args)
|
||||
"Call (PROC ARGS ...) synchronously using the current Geiser REPL.
|
||||
PROC and ARGS should be strings."
|
||||
(guix-geiser-eval
|
||||
(apply #'guix-guile-make-call-expression proc args)))
|
||||
|
||||
(defun guix-geiser-call-in-repl (proc &rest args)
|
||||
"Call (PROC ARGS ...) in the current Geiser REPL.
|
||||
PROC and ARGS should be strings."
|
||||
(guix-geiser-eval-in-repl
|
||||
(apply #'guix-guile-make-call-expression proc args)))
|
||||
|
||||
(provide 'guix-geiser)
|
||||
|
||||
;;; guix-geiser.el ends here
|
||||
@@ -0,0 +1,98 @@
|
||||
;;; guix-guile.el --- Auxiliary tools for working with guile code -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright © 2015 Alex Kost <alezost@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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file provides functions for parsing guile code, making guile
|
||||
;; expressions, etc.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'geiser-guile)
|
||||
|
||||
(defvar guix-guile-definition-regexp
|
||||
(rx bol "(define"
|
||||
(zero-or-one "*")
|
||||
(zero-or-one "-public")
|
||||
(one-or-more space)
|
||||
(zero-or-one "(")
|
||||
(group (one-or-more (or word (syntax symbol)))))
|
||||
"Regexp used to find the guile definition.")
|
||||
|
||||
(defun guix-guile-current-definition ()
|
||||
"Return string with name of the current top-level guile definition."
|
||||
(save-excursion
|
||||
(beginning-of-defun)
|
||||
(if (looking-at guix-guile-definition-regexp)
|
||||
(match-string-no-properties 1)
|
||||
(error "Couldn't find the current definition"))))
|
||||
|
||||
(defun guix-guile-current-module ()
|
||||
"Return a string with the current guile module.
|
||||
Return nil, if current buffer does not define a module."
|
||||
;; Modified version of `geiser-guile--get-module'.
|
||||
(save-excursion
|
||||
(geiser-syntax--pop-to-top)
|
||||
(when (or (re-search-backward geiser-guile--module-re nil t)
|
||||
(looking-at geiser-guile--library-re)
|
||||
(re-search-forward geiser-guile--module-re nil t))
|
||||
(match-string-no-properties 1))))
|
||||
|
||||
(defun guix-guile-boolean (arg)
|
||||
"Return a string with guile boolean value.
|
||||
Transform elisp ARG (nil or non-nil) to the guile boolean (#f or #t)."
|
||||
(concat "#" (prin1-to-string (if arg 't 'f))))
|
||||
|
||||
(defun guix-guile-keyword-regexp (keyword)
|
||||
"Return regexp to find guile KEYWORD."
|
||||
(format "(\\(%s\\)\\_>" keyword))
|
||||
|
||||
(defun guix-guile-make-call-expression (proc &rest args)
|
||||
"Return \"(PROC ARGS ...)\" string.
|
||||
PROC and ARGS should be strings."
|
||||
(format "(%s %s)"
|
||||
proc
|
||||
(mapconcat #'identity args " ")))
|
||||
|
||||
(defun guix-make-guile-expression (fun &rest args)
|
||||
"Return string containing a guile expression for calling FUN with ARGS."
|
||||
(format "(%S %s)" fun
|
||||
(mapconcat
|
||||
(lambda (arg)
|
||||
(cond
|
||||
((null arg) "'()")
|
||||
((or (eq arg t)
|
||||
;; An ugly hack to separate 'false' from nil.
|
||||
(equal arg 'f)
|
||||
(keywordp arg))
|
||||
(concat "#" (prin1-to-string arg t)))
|
||||
((or (symbolp arg) (listp arg))
|
||||
(concat "'" (prin1-to-string arg)))
|
||||
(t (prin1-to-string arg))))
|
||||
args
|
||||
" ")))
|
||||
|
||||
(defun guix-guile-prompt? (string)
|
||||
"Return non-nil, if STRING contains a Guile prompt."
|
||||
(or (string-match-p geiser-guile--prompt-regexp string)
|
||||
(string-match-p geiser-guile--debugger-prompt-regexp string)))
|
||||
|
||||
(provide 'guix-guile)
|
||||
|
||||
;;; guix-guile.el ends here
|
||||
@@ -0,0 +1,108 @@
|
||||
;;; guix-help-vars.el --- Variables related to --help output
|
||||
|
||||
;; Copyright © 2015 Alex Kost <alezost@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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file provides regular expressions to parse various "guix
|
||||
;; ... --help" outputs and lists of non-receivable items (system types,
|
||||
;; hash formats, etc.).
|
||||
|
||||
;;; Code:
|
||||
|
||||
|
||||
;;; Regexps for parsing "guix ..." outputs
|
||||
|
||||
(defvar guix-help-parse-option-regexp
|
||||
(rx bol " "
|
||||
(zero-or-one (group "-" (not (any "- ")))
|
||||
",")
|
||||
(one-or-more " ")
|
||||
(group "--" (one-or-more (or wordchar "-")))
|
||||
(group (zero-or-one "[")
|
||||
(zero-or-one "="))
|
||||
(zero-or-more (not space))
|
||||
(one-or-more space)
|
||||
(group (one-or-more any)))
|
||||
"Common regexp used to find command options.")
|
||||
|
||||
(defvar guix-help-parse-command-regexp
|
||||
(rx bol " "
|
||||
(group wordchar (one-or-more (or wordchar "-"))))
|
||||
"Regexp used to find guix commands.
|
||||
'Command' means any option not prefixed with '-'. For example,
|
||||
guix subcommand, system action, importer, etc.")
|
||||
|
||||
(defvar guix-help-parse-long-option-regexp
|
||||
(rx (or " " ", ")
|
||||
(group "--" (one-or-more (or wordchar "-"))
|
||||
(zero-or-one "=")))
|
||||
"Regexp used to find long options.")
|
||||
|
||||
(defvar guix-help-parse-short-option-regexp
|
||||
(rx bol (one-or-more blank)
|
||||
"-" (group (not (any "- "))))
|
||||
"Regexp used to find short options.")
|
||||
|
||||
(defvar guix-help-parse-package-regexp
|
||||
(rx bol (group (one-or-more (not blank))))
|
||||
"Regexp used to find names of the packages.")
|
||||
|
||||
(defvar guix-help-parse-list-regexp
|
||||
(rx bol (zero-or-more blank) "- "
|
||||
(group (one-or-more (or wordchar "-"))))
|
||||
"Regexp used to find various lists (lint checkers, graph types).")
|
||||
|
||||
(defvar guix-help-parse-regexp-group 1
|
||||
"Parenthesized expression of regexps used to find commands and
|
||||
options.")
|
||||
|
||||
|
||||
;;; Non-receivable lists of system types, hash formats, etc.
|
||||
|
||||
(defvar guix-help-system-types
|
||||
'("x86_64-linux" "i686-linux" "armhf-linux" "mips64el-linux")
|
||||
"List of supported systems.")
|
||||
|
||||
(defvar guix-help-source-types
|
||||
'("package" "all" "transitive")
|
||||
"List of supported sources types.")
|
||||
|
||||
(defvar guix-help-hash-formats
|
||||
'("nix-base32" "base32" "base16" "hex" "hexadecimal")
|
||||
"List of supported hash formats.")
|
||||
|
||||
(defvar guix-help-refresh-subsets
|
||||
'("core" "non-core")
|
||||
"List of supported 'refresh' subsets.")
|
||||
|
||||
(defvar guix-help-key-policies
|
||||
'("interactive" "always" "never")
|
||||
"List of supported key download policies.")
|
||||
|
||||
(defvar guix-help-verify-options
|
||||
'("repair" "contents")
|
||||
"List of supported 'verify' options")
|
||||
|
||||
(defvar guix-help-elpa-archives
|
||||
'("gnu" "melpa" "melpa-stable")
|
||||
"List of supported ELPA archives.")
|
||||
|
||||
(provide 'guix-help-vars)
|
||||
|
||||
;;; guix-help-vars.el ends here
|
||||
@@ -0,0 +1,65 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2014 Alex Kost <alezost@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 is an auxiliary file for the Emacs UI. It is used to add Guix
|
||||
;; directories to path variables and to load the main code.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(use-modules (ice-9 regex)
|
||||
(srfi srfi-26))
|
||||
|
||||
(define %guix-dir)
|
||||
|
||||
;; The code is taken from ‘guix’ executable script
|
||||
(define (set-paths!)
|
||||
(define-syntax-rule (push! elt v) (set! v (cons elt v)))
|
||||
|
||||
(define config-lookup
|
||||
(let ((config '(("prefix" . "@prefix@")
|
||||
("guilemoduledir" . "@guilemoduledir@")))
|
||||
(var-ref-regexp (make-regexp "\\$\\{([a-z]+)\\}")))
|
||||
(define (expand-var-ref match)
|
||||
(lookup (match:substring match 1)))
|
||||
(define (expand str)
|
||||
(regexp-substitute/global #f var-ref-regexp str
|
||||
'pre expand-var-ref 'post))
|
||||
(define (lookup name)
|
||||
(expand (assoc-ref config name)))
|
||||
lookup))
|
||||
|
||||
(let ((module-dir (config-lookup "guilemoduledir"))
|
||||
(updates-dir (and=> (or (getenv "XDG_CONFIG_HOME")
|
||||
(and=> (getenv "HOME")
|
||||
(cut string-append <> "/.config")))
|
||||
(cut string-append <> "/guix/latest"))))
|
||||
(push! module-dir %load-path)
|
||||
(push! module-dir %load-compiled-path)
|
||||
(if (and updates-dir (file-exists? updates-dir))
|
||||
(begin
|
||||
(set! %guix-dir updates-dir)
|
||||
(push! updates-dir %load-path)
|
||||
(push! updates-dir %load-compiled-path))
|
||||
(set! %guix-dir module-dir))))
|
||||
|
||||
(set-paths!)
|
||||
|
||||
(load-from-path "guix-main")
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
;;; guix-history.el --- History of buffer information
|
||||
|
||||
;; Copyright © 2014 Alex Kost <alezost@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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file provides support for history of buffers similar to the
|
||||
;; history of a `help-mode' buffer.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'cl-macs)
|
||||
|
||||
(defvar-local guix-history-stack-item nil
|
||||
"Current item of the history.
|
||||
A list of the form (FUNCTION [ARGS ...]).
|
||||
The item is used by calling (apply FUNCTION ARGS).")
|
||||
(put 'guix-history-stack-item 'permanent-local t)
|
||||
|
||||
(defvar-local guix-history-back-stack nil
|
||||
"Stack (list) of visited items.
|
||||
Each element of the list has a form of `guix-history-stack-item'.")
|
||||
(put 'guix-history-back-stack 'permanent-local t)
|
||||
|
||||
(defvar-local guix-history-forward-stack nil
|
||||
"Stack (list) of items visited with `guix-history-back'.
|
||||
Each element of the list has a form of `guix-history-stack-item'.")
|
||||
(put 'guix-history-forward-stack 'permanent-local t)
|
||||
|
||||
(defvar guix-history-size 0
|
||||
"Maximum number of items saved in history.
|
||||
If 0, the history is disabled.")
|
||||
|
||||
(defun guix-history-add (item)
|
||||
"Add ITEM to history."
|
||||
(and guix-history-stack-item
|
||||
(push guix-history-stack-item guix-history-back-stack))
|
||||
(setq guix-history-forward-stack nil
|
||||
guix-history-stack-item item)
|
||||
(when (>= (length guix-history-back-stack)
|
||||
guix-history-size)
|
||||
(setq guix-history-back-stack
|
||||
(cl-loop for elt in guix-history-back-stack
|
||||
for i from 1 to guix-history-size
|
||||
collect elt))))
|
||||
|
||||
(defun guix-history-replace (item)
|
||||
"Replace current item in history with ITEM."
|
||||
(setq guix-history-stack-item item))
|
||||
|
||||
(defun guix-history-goto (item)
|
||||
"Go to the ITEM of history.
|
||||
ITEM should have the form of `guix-history-stack-item'."
|
||||
(or (listp item)
|
||||
(error "Wrong value of history element"))
|
||||
(setq guix-history-stack-item item)
|
||||
(apply (car item) (cdr item)))
|
||||
|
||||
(defun guix-history-back ()
|
||||
"Go back to the previous element of history in the current buffer."
|
||||
(interactive)
|
||||
(or guix-history-back-stack
|
||||
(user-error "No previous element in history"))
|
||||
(push guix-history-stack-item guix-history-forward-stack)
|
||||
(guix-history-goto (pop guix-history-back-stack)))
|
||||
|
||||
(defun guix-history-forward ()
|
||||
"Go forward to the next element of history in the current buffer."
|
||||
(interactive)
|
||||
(or guix-history-forward-stack
|
||||
(user-error "No next element in history"))
|
||||
(push guix-history-stack-item guix-history-back-stack)
|
||||
(guix-history-goto (pop guix-history-forward-stack)))
|
||||
|
||||
(provide 'guix-history)
|
||||
|
||||
;;; guix-history.el ends here
|
||||
@@ -0,0 +1,886 @@
|
||||
;;; guix-info.el --- Info buffers for displaying entries -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright © 2014, 2015 Alex Kost <alezost@gmail.com>
|
||||
;; Copyright © 2015 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file provides a help-like buffer for displaying information
|
||||
;; about Guix packages and generations.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'guix-base)
|
||||
(require 'guix-utils)
|
||||
|
||||
(defgroup guix-info nil
|
||||
"General settings for info buffers."
|
||||
:prefix "guix-info-"
|
||||
:group 'guix)
|
||||
|
||||
(defgroup guix-info-faces nil
|
||||
"Faces for info buffers."
|
||||
:group 'guix-info
|
||||
:group 'guix-faces)
|
||||
|
||||
(defface guix-info-param-title
|
||||
'((t :inherit font-lock-type-face))
|
||||
"Face used for titles of parameters."
|
||||
:group 'guix-info-faces)
|
||||
|
||||
(defface guix-info-file-path
|
||||
'((t :inherit link))
|
||||
"Face used for file paths."
|
||||
:group 'guix-info-faces)
|
||||
|
||||
(defface guix-info-url
|
||||
'((t :inherit link))
|
||||
"Face used for URLs."
|
||||
:group 'guix-info-faces)
|
||||
|
||||
(defface guix-info-time
|
||||
'((t :inherit font-lock-constant-face))
|
||||
"Face used for timestamps."
|
||||
:group 'guix-info-faces)
|
||||
|
||||
(defface guix-info-action-button
|
||||
'((((type x w32 ns) (class color))
|
||||
:box (:line-width 2 :style released-button)
|
||||
:background "lightgrey" :foreground "black")
|
||||
(t :inherit button))
|
||||
"Face used for action buttons."
|
||||
:group 'guix-info-faces)
|
||||
|
||||
(defface guix-info-action-button-mouse
|
||||
'((((type x w32 ns) (class color))
|
||||
:box (:line-width 2 :style released-button)
|
||||
:background "grey90" :foreground "black")
|
||||
(t :inherit highlight))
|
||||
"Mouse face used for action buttons."
|
||||
:group 'guix-info-faces)
|
||||
|
||||
(defcustom guix-info-ignore-empty-vals nil
|
||||
"If non-nil, do not display parameters with nil values."
|
||||
:type 'boolean
|
||||
:group 'guix-info)
|
||||
|
||||
(defvar guix-info-param-title-format "%-18s: "
|
||||
"String used to format a title of a parameter.
|
||||
It should be a '%s'-sequence. After inserting a title formatted
|
||||
with this string, a value of the parameter is inserted.
|
||||
This string is used by `guix-info-insert-title-default'.")
|
||||
|
||||
(defvar guix-info-multiline-prefix (make-string 20 ?\s)
|
||||
"String used to format multi-line parameter values.
|
||||
If a value occupies more than one line, this string is inserted
|
||||
in the beginning of each line after the first one.
|
||||
This string is used by `guix-info-insert-val-default'.")
|
||||
|
||||
(defvar guix-info-indent 2
|
||||
"Number of spaces used to indent various parts of inserted text.")
|
||||
|
||||
(defvar guix-info-fill-column 60
|
||||
"Column used for filling (word wrapping) parameters with long lines.
|
||||
If a value is not multi-line and it occupies more than this
|
||||
number of characters, it will be split into several lines.")
|
||||
|
||||
(defvar guix-info-delimiter "\n\f\n"
|
||||
"String used to separate entries.")
|
||||
|
||||
(defvar guix-info-insert-methods
|
||||
'((package
|
||||
(name guix-package-info-name)
|
||||
(version guix-package-info-version)
|
||||
(license guix-package-info-license)
|
||||
(synopsis guix-package-info-synopsis)
|
||||
(description guix-package-info-insert-description
|
||||
guix-info-insert-title-simple)
|
||||
(outputs guix-package-info-insert-outputs
|
||||
guix-info-insert-title-simple)
|
||||
(source guix-package-info-insert-source
|
||||
guix-info-insert-title-simple)
|
||||
(home-url guix-info-insert-url)
|
||||
(inputs guix-package-info-insert-inputs)
|
||||
(native-inputs guix-package-info-insert-native-inputs)
|
||||
(propagated-inputs guix-package-info-insert-propagated-inputs)
|
||||
(location guix-package-info-insert-location))
|
||||
(installed
|
||||
(path guix-package-info-insert-output-path
|
||||
guix-info-insert-title-simple)
|
||||
(dependencies guix-package-info-insert-output-dependencies
|
||||
guix-info-insert-title-simple))
|
||||
(output
|
||||
(name guix-package-info-name)
|
||||
(version guix-output-info-insert-version)
|
||||
(output guix-output-info-insert-output)
|
||||
(source guix-package-info-insert-source
|
||||
guix-info-insert-title-simple)
|
||||
(path guix-package-info-insert-output-path
|
||||
guix-info-insert-title-simple)
|
||||
(dependencies guix-package-info-insert-output-dependencies
|
||||
guix-info-insert-title-simple)
|
||||
(license guix-package-info-license)
|
||||
(synopsis guix-package-info-synopsis)
|
||||
(description guix-package-info-insert-description
|
||||
guix-info-insert-title-simple)
|
||||
(home-url guix-info-insert-url)
|
||||
(inputs guix-package-info-insert-inputs)
|
||||
(native-inputs guix-package-info-insert-native-inputs)
|
||||
(propagated-inputs guix-package-info-insert-propagated-inputs)
|
||||
(location guix-package-info-insert-location))
|
||||
(generation
|
||||
(number guix-generation-info-insert-number)
|
||||
(current guix-generation-info-insert-current)
|
||||
(path guix-info-insert-file-path)
|
||||
(time guix-info-insert-time)))
|
||||
"Methods for inserting parameter values.
|
||||
Each element of the list should have a form:
|
||||
|
||||
(ENTRY-TYPE . ((PARAM INSERT-VALUE [INSERT-TITLE]) ...))
|
||||
|
||||
INSERT-VALUE may be either nil, a face name or a function. If it
|
||||
is nil or a face, `guix-info-insert-val-default' function is
|
||||
called with parameter value and INSERT-VALUE as arguments. If it
|
||||
is a function, this function is called with parameter value and
|
||||
entry info (alist of parameters and their values) as arguments.
|
||||
|
||||
INSERT-TITLE may be either nil, a face name or a function. If it
|
||||
is nil or a face, `guix-info-insert-title-default' function is
|
||||
called with parameter title and INSERT-TITLE as arguments. If it
|
||||
is a function, this function is called with parameter title as
|
||||
argument.")
|
||||
|
||||
(defvar guix-info-displayed-params
|
||||
'((package name version synopsis outputs source location home-url
|
||||
license inputs native-inputs propagated-inputs description)
|
||||
(output name version output synopsis source path dependencies location
|
||||
home-url license inputs native-inputs propagated-inputs
|
||||
description)
|
||||
(installed path dependencies)
|
||||
(generation number prev-number current time path))
|
||||
"List of displayed entry parameters.
|
||||
Each element of the list should have a form:
|
||||
|
||||
(ENTRY-TYPE . (PARAM ...))
|
||||
|
||||
The order of displayed parameters is the same as in this list.")
|
||||
|
||||
(defun guix-info-get-insert-methods (entry-type param)
|
||||
"Return list of insert methods for parameter PARAM of ENTRY-TYPE.
|
||||
See `guix-info-insert-methods' for details."
|
||||
(guix-assq-value guix-info-insert-methods
|
||||
entry-type param))
|
||||
|
||||
(defun guix-info-get-displayed-params (entry-type)
|
||||
"Return parameters of ENTRY-TYPE that should be displayed."
|
||||
(guix-assq-value guix-info-displayed-params
|
||||
entry-type))
|
||||
|
||||
(defun guix-info-get-indent (&optional level)
|
||||
"Return `guix-info-indent' \"multiplied\" by LEVEL spaces.
|
||||
LEVEL is 1 by default."
|
||||
(make-string (* guix-info-indent (or level 1)) ?\s))
|
||||
|
||||
(defun guix-info-insert-indent (&optional level)
|
||||
"Insert `guix-info-indent' spaces LEVEL times (1 by default)."
|
||||
(insert (guix-info-get-indent level)))
|
||||
|
||||
(defun guix-info-insert-entries (entries entry-type)
|
||||
"Display ENTRIES of ENTRY-TYPE in the current info buffer.
|
||||
ENTRIES should have a form of `guix-entries'."
|
||||
(guix-mapinsert (lambda (entry)
|
||||
(guix-info-insert-entry entry entry-type))
|
||||
entries
|
||||
guix-info-delimiter))
|
||||
|
||||
(defun guix-info-insert-entry-default (entry entry-type
|
||||
&optional indent-level)
|
||||
"Insert ENTRY of ENTRY-TYPE into the current info buffer.
|
||||
If INDENT-LEVEL is non-nil, indent displayed information by this
|
||||
number of `guix-info-indent' spaces."
|
||||
(let ((region-beg (point)))
|
||||
(mapc (lambda (param)
|
||||
(guix-info-insert-param param entry entry-type))
|
||||
(guix-info-get-displayed-params entry-type))
|
||||
(when indent-level
|
||||
(indent-rigidly region-beg (point)
|
||||
(* indent-level guix-info-indent)))))
|
||||
|
||||
(defun guix-info-insert-entry (entry entry-type &optional indent-level)
|
||||
"Insert ENTRY of ENTRY-TYPE into the current info buffer.
|
||||
Use `guix-info-insert-ENTRY-TYPE-function' or
|
||||
`guix-info-insert-entry-default' if it is nil."
|
||||
(let* ((var (intern (concat "guix-info-insert-"
|
||||
(symbol-name entry-type)
|
||||
"-function")))
|
||||
(fun (symbol-value var)))
|
||||
(if (functionp fun)
|
||||
(funcall fun entry)
|
||||
(guix-info-insert-entry-default entry entry-type indent-level))))
|
||||
|
||||
(defun guix-info-insert-param (param entry entry-type)
|
||||
"Insert title and value of a PARAM at point.
|
||||
ENTRY is alist with parameters and their values.
|
||||
ENTRY-TYPE is a type of ENTRY."
|
||||
(let ((val (guix-assq-value entry param)))
|
||||
(unless (and guix-info-ignore-empty-vals (null val))
|
||||
(let* ((title (guix-get-param-title entry-type param))
|
||||
(insert-methods (guix-info-get-insert-methods entry-type param))
|
||||
(val-method (car insert-methods))
|
||||
(title-method (cadr insert-methods)))
|
||||
(guix-info-method-funcall title title-method
|
||||
#'guix-info-insert-title-default)
|
||||
(guix-info-method-funcall val val-method
|
||||
#'guix-info-insert-val-default
|
||||
entry)
|
||||
(insert "\n")))))
|
||||
|
||||
(defun guix-info-method-funcall (val method default-fun &rest args)
|
||||
"Call METHOD or DEFAULT-FUN.
|
||||
|
||||
If METHOD is a function and VAL is non-nil, call this
|
||||
function by applying it to VAL and ARGS.
|
||||
|
||||
If METHOD is a face, propertize inserted VAL with this face."
|
||||
(cond ((or (null method)
|
||||
(facep method))
|
||||
(funcall default-fun val method))
|
||||
((functionp method)
|
||||
(apply method val args))
|
||||
(t (error "Unknown method '%S'" method))))
|
||||
|
||||
(defun guix-info-insert-title-default (title &optional face format)
|
||||
"Insert TITLE formatted with `guix-info-param-title-format' at point."
|
||||
(guix-format-insert title
|
||||
(or face 'guix-info-param-title)
|
||||
(or format guix-info-param-title-format)))
|
||||
|
||||
(defun guix-info-insert-title-simple (title &optional face)
|
||||
"Insert TITLE at point."
|
||||
(guix-info-insert-title-default title face "%s:"))
|
||||
|
||||
(defun guix-info-insert-val-default (val &optional face)
|
||||
"Format and insert parameter value VAL at point.
|
||||
|
||||
This function is intended to be called after
|
||||
`guix-info-insert-title-default'.
|
||||
|
||||
If VAL is a one-line string longer than `guix-info-fill-column',
|
||||
split it into several short lines. See also
|
||||
`guix-info-multiline-prefix'.
|
||||
|
||||
If FACE is non-nil, propertize inserted line(s) with this FACE."
|
||||
(guix-split-insert val face
|
||||
guix-info-fill-column
|
||||
(concat "\n" guix-info-multiline-prefix)))
|
||||
|
||||
(defun guix-info-insert-val-simple (val &optional face-or-fun)
|
||||
"Format and insert parameter value VAL at point.
|
||||
|
||||
This function is intended to be called after
|
||||
`guix-info-insert-title-simple'.
|
||||
|
||||
If VAL is a one-line string longer than `guix-info-fill-column',
|
||||
split it into several short lines and indent each line with
|
||||
`guix-info-indent' spaces.
|
||||
|
||||
If FACE-OR-FUN is a face, propertize inserted line(s) with this FACE.
|
||||
|
||||
If FACE-OR-FUN is a function, call it with VAL as argument. If
|
||||
VAL is a list, call the function on each element of this list."
|
||||
(if (null val)
|
||||
(progn (guix-info-insert-indent)
|
||||
(guix-format-insert nil))
|
||||
(let ((prefix (concat "\n" (guix-info-get-indent))))
|
||||
(insert prefix)
|
||||
(if (functionp face-or-fun)
|
||||
(guix-mapinsert face-or-fun
|
||||
(if (listp val) val (list val))
|
||||
prefix)
|
||||
(guix-split-insert val face-or-fun
|
||||
guix-info-fill-column prefix)))))
|
||||
|
||||
(defun guix-info-insert-time (seconds &optional _)
|
||||
"Insert formatted time string using SECONDS at point."
|
||||
(guix-info-insert-val-default (guix-get-time-string seconds)
|
||||
'guix-info-time))
|
||||
|
||||
|
||||
;;; Buttons
|
||||
|
||||
(defvar guix-info-button-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(set-keymap-parent map button-map)
|
||||
(define-key map (kbd "c") 'guix-info-button-copy-label)
|
||||
map)
|
||||
"Keymap for buttons in info buffers.")
|
||||
|
||||
(define-button-type 'guix
|
||||
'keymap guix-info-button-map
|
||||
'follow-link t)
|
||||
|
||||
(define-button-type 'guix-action
|
||||
:supertype 'guix
|
||||
'face 'guix-info-action-button
|
||||
'mouse-face 'guix-info-action-button-mouse)
|
||||
|
||||
(define-button-type 'guix-file
|
||||
:supertype 'guix
|
||||
'face 'guix-info-file-path
|
||||
'help-echo "Find file"
|
||||
'action (lambda (btn)
|
||||
(guix-find-file (button-label btn))))
|
||||
|
||||
(define-button-type 'guix-url
|
||||
:supertype 'guix
|
||||
'face 'guix-info-url
|
||||
'help-echo "Browse URL"
|
||||
'action (lambda (btn)
|
||||
(browse-url (button-label btn))))
|
||||
|
||||
(define-button-type 'guix-package-location
|
||||
:supertype 'guix
|
||||
'face 'guix-package-info-location
|
||||
'help-echo "Find location of this package"
|
||||
'action (lambda (btn)
|
||||
(guix-find-location (button-label btn))))
|
||||
|
||||
(define-button-type 'guix-package-name
|
||||
:supertype 'guix
|
||||
'face 'guix-package-info-name-button
|
||||
'help-echo "Describe this package"
|
||||
'action (lambda (btn)
|
||||
(guix-get-show-entries guix-profile 'info guix-package-info-type
|
||||
'name (button-label btn))))
|
||||
|
||||
(defun guix-info-button-copy-label (&optional pos)
|
||||
"Copy a label of the button at POS into kill ring.
|
||||
If POS is nil, use the current point position."
|
||||
(interactive)
|
||||
(let ((button (button-at (or pos (point)))))
|
||||
(when button
|
||||
(kill-new (button-label button)))))
|
||||
|
||||
(defun guix-info-insert-action-button (label action &optional message
|
||||
&rest properties)
|
||||
"Make action button with LABEL and insert it at point.
|
||||
ACTION is a function called when the button is pressed. It
|
||||
should accept button as the argument.
|
||||
MESSAGE is a button message.
|
||||
See `insert-text-button' for the meaning of PROPERTIES."
|
||||
(apply #'guix-insert-button
|
||||
label 'guix-action
|
||||
'action action
|
||||
'help-echo message
|
||||
properties))
|
||||
|
||||
(defun guix-info-insert-file-path (path &optional _)
|
||||
"Make button from file PATH and insert it at point."
|
||||
(guix-insert-button path 'guix-file))
|
||||
|
||||
(defun guix-info-insert-url (url &optional _)
|
||||
"Make button from URL and insert it at point."
|
||||
(guix-insert-button url 'guix-url))
|
||||
|
||||
|
||||
(defvar guix-info-mode-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(set-keymap-parent
|
||||
map (make-composed-keymap (list guix-root-map button-buffer-map)
|
||||
special-mode-map))
|
||||
map)
|
||||
"Parent keymap for info buffers.")
|
||||
|
||||
(define-derived-mode guix-info-mode special-mode "Guix-Info"
|
||||
"Parent mode for displaying information in info buffers.")
|
||||
|
||||
|
||||
;;; Displaying packages
|
||||
|
||||
(guix-define-buffer-type info package
|
||||
:required (id installed non-unique))
|
||||
|
||||
(defface guix-package-info-heading
|
||||
'((((type tty pc) (class color)) :weight bold)
|
||||
(t :height 1.6 :weight bold :inherit variable-pitch))
|
||||
"Face for package name and version headings."
|
||||
:group 'guix-package-info-faces)
|
||||
|
||||
(defface guix-package-info-name
|
||||
'((t :inherit font-lock-keyword-face))
|
||||
"Face used for a name of a package."
|
||||
:group 'guix-package-info-faces)
|
||||
|
||||
(defface guix-package-info-name-button
|
||||
'((t :inherit button))
|
||||
"Face used for a full name that can be used to describe a package."
|
||||
:group 'guix-package-info-faces)
|
||||
|
||||
(defface guix-package-info-version
|
||||
'((t :inherit font-lock-builtin-face))
|
||||
"Face used for a version of a package."
|
||||
:group 'guix-package-info-faces)
|
||||
|
||||
(defface guix-package-info-synopsis
|
||||
'((((type tty pc) (class color)) :weight bold)
|
||||
(t :height 1.1 :weight bold :inherit variable-pitch))
|
||||
"Face used for a synopsis of a package."
|
||||
:group 'guix-package-info-faces)
|
||||
|
||||
(defface guix-package-info-description
|
||||
'((t))
|
||||
"Face used for a description of a package."
|
||||
:group 'guix-package-info-faces)
|
||||
|
||||
(defface guix-package-info-license
|
||||
'((t :inherit font-lock-string-face))
|
||||
"Face used for a license of a package."
|
||||
:group 'guix-package-info-faces)
|
||||
|
||||
(defface guix-package-info-location
|
||||
'((t :inherit link))
|
||||
"Face used for a location of a package."
|
||||
:group 'guix-package-info-faces)
|
||||
|
||||
(defface guix-package-info-installed-outputs
|
||||
'((default :weight bold)
|
||||
(((class color) (min-colors 88) (background light))
|
||||
:foreground "ForestGreen")
|
||||
(((class color) (min-colors 88) (background dark))
|
||||
:foreground "PaleGreen")
|
||||
(((class color) (min-colors 8))
|
||||
:foreground "green")
|
||||
(t :underline t))
|
||||
"Face used for installed outputs of a package."
|
||||
:group 'guix-package-info-faces)
|
||||
|
||||
(defface guix-package-info-uninstalled-outputs
|
||||
'((t :weight bold))
|
||||
"Face used for uninstalled outputs of a package."
|
||||
:group 'guix-package-info-faces)
|
||||
|
||||
(defface guix-package-info-obsolete
|
||||
'((t :inherit error))
|
||||
"Face used if a package is obsolete."
|
||||
:group 'guix-package-info-faces)
|
||||
|
||||
(defvar guix-info-insert-package-function
|
||||
#'guix-package-info-insert-with-heading
|
||||
"Function used to insert a package information.
|
||||
It is called with a single argument - alist of package parameters.
|
||||
If nil, insert package in a default way.")
|
||||
|
||||
(defvar guix-package-info-heading-params '(synopsis description)
|
||||
"List of parameters displayed in a heading along with name and version.")
|
||||
|
||||
(defcustom guix-package-info-fill-heading t
|
||||
"If nil, insert heading parameters in a raw form, without
|
||||
filling them to fit the window."
|
||||
:type 'boolean
|
||||
:group 'guix-package-info)
|
||||
|
||||
(defun guix-package-info-insert-heading (entry)
|
||||
"Insert the heading for package ENTRY.
|
||||
Show package name, version, and `guix-package-info-heading-params'."
|
||||
(guix-format-insert (concat (guix-assq-value entry 'name) " "
|
||||
(guix-assq-value entry 'version))
|
||||
'guix-package-info-heading)
|
||||
(insert "\n\n")
|
||||
(mapc (lambda (param)
|
||||
(let ((val (guix-assq-value entry param))
|
||||
(face (guix-get-symbol (symbol-name param)
|
||||
'info 'package)))
|
||||
(when val
|
||||
(let* ((col (min (window-width) fill-column))
|
||||
(val (if guix-package-info-fill-heading
|
||||
(guix-get-filled-string val col)
|
||||
val)))
|
||||
(guix-format-insert val (and (facep face) face))
|
||||
(insert "\n\n")))))
|
||||
guix-package-info-heading-params))
|
||||
|
||||
(defun guix-package-info-insert-with-heading (entry)
|
||||
"Insert package ENTRY with its heading at point."
|
||||
(guix-package-info-insert-heading entry)
|
||||
(mapc (lambda (param)
|
||||
(unless (or (memq param '(name version))
|
||||
(memq param guix-package-info-heading-params))
|
||||
(guix-info-insert-param param entry 'package)))
|
||||
(guix-info-get-displayed-params 'package)))
|
||||
|
||||
(defun guix-package-info-insert-description (desc &optional _)
|
||||
"Insert description DESC at point."
|
||||
(guix-info-insert-val-simple desc 'guix-package-info-description))
|
||||
|
||||
(defun guix-package-info-insert-location (location &optional _)
|
||||
"Make button from file LOCATION and insert it at point."
|
||||
(guix-insert-button location 'guix-package-location))
|
||||
|
||||
(defmacro guix-package-info-define-insert-inputs (&optional type)
|
||||
"Define a face and a function for inserting package inputs.
|
||||
TYPE is a type of inputs.
|
||||
Function name is `guix-package-info-insert-TYPE-inputs'.
|
||||
Face name is `guix-package-info-TYPE-inputs'."
|
||||
(let* ((type-str (symbol-name type))
|
||||
(type-name (and type (concat type-str "-")))
|
||||
(type-desc (and type (concat type-str " ")))
|
||||
(face (intern (concat "guix-package-info-" type-name "inputs")))
|
||||
(btn (intern (concat "guix-package-" type-name "input")))
|
||||
(fun (intern (concat "guix-package-info-insert-" type-name "inputs"))))
|
||||
`(progn
|
||||
(defface ,face
|
||||
'((t :inherit guix-package-info-name-button))
|
||||
,(concat "Face used for " type-desc "inputs of a package.")
|
||||
:group 'guix-package-info-faces)
|
||||
|
||||
(define-button-type ',btn
|
||||
:supertype 'guix-package-name
|
||||
'face ',face)
|
||||
|
||||
(defun ,fun (inputs &optional _)
|
||||
,(concat "Make buttons from " type-desc "INPUTS and insert them at point.")
|
||||
(guix-package-info-insert-full-names inputs ',btn)))))
|
||||
|
||||
(guix-package-info-define-insert-inputs)
|
||||
(guix-package-info-define-insert-inputs native)
|
||||
(guix-package-info-define-insert-inputs propagated)
|
||||
|
||||
(defun guix-package-info-insert-full-names (names button-type)
|
||||
"Make BUTTON-TYPE buttons from package NAMES and insert them at point.
|
||||
NAMES is a list of strings."
|
||||
(if names
|
||||
(guix-info-insert-val-default
|
||||
(with-temp-buffer
|
||||
(guix-mapinsert (lambda (name)
|
||||
(guix-insert-button name button-type))
|
||||
names
|
||||
guix-list-separator)
|
||||
(buffer-substring (point-min) (point-max))))
|
||||
(guix-format-insert nil)))
|
||||
|
||||
|
||||
;;; Inserting outputs and installed parameters
|
||||
|
||||
(defvar guix-package-info-output-format "%-10s"
|
||||
"String used to format output names of the packages.
|
||||
It should be a '%s'-sequence. After inserting an output name
|
||||
formatted with this string, an action button is inserted.")
|
||||
|
||||
(defvar guix-package-info-obsolete-string "(This package is obsolete)"
|
||||
"String used if a package is obsolete.")
|
||||
|
||||
(defvar guix-info-insert-installed-function nil
|
||||
"Function used to insert an installed information.
|
||||
It is called with a single argument - alist of installed
|
||||
parameters (`output', `path', `dependencies').
|
||||
If nil, insert installed info in a default way.")
|
||||
|
||||
(defun guix-package-info-insert-outputs (outputs entry)
|
||||
"Insert OUTPUTS from package ENTRY at point."
|
||||
(and (guix-assq-value entry 'obsolete)
|
||||
(guix-package-info-insert-obsolete-text))
|
||||
(and (guix-assq-value entry 'non-unique)
|
||||
(guix-assq-value entry 'installed)
|
||||
(guix-package-info-insert-non-unique-text
|
||||
(guix-get-full-name entry)))
|
||||
(insert "\n")
|
||||
(mapc (lambda (output)
|
||||
(guix-package-info-insert-output output entry))
|
||||
outputs))
|
||||
|
||||
(defun guix-package-info-insert-obsolete-text ()
|
||||
"Insert a message about obsolete package at point."
|
||||
(guix-info-insert-indent)
|
||||
(guix-format-insert guix-package-info-obsolete-string
|
||||
'guix-package-info-obsolete))
|
||||
|
||||
(defun guix-package-info-insert-non-unique-text (full-name)
|
||||
"Insert a message about non-unique package with FULL-NAME at point."
|
||||
(insert "\n")
|
||||
(guix-info-insert-indent)
|
||||
(insert "Installed outputs are displayed for a non-unique ")
|
||||
(guix-insert-button full-name 'guix-package-name)
|
||||
(insert " package."))
|
||||
|
||||
(defun guix-package-info-insert-output (output entry)
|
||||
"Insert OUTPUT at point.
|
||||
Make some fancy text with buttons and additional stuff if the
|
||||
current OUTPUT is installed (if there is such output in
|
||||
`installed' parameter of a package ENTRY)."
|
||||
(let* ((installed (guix-assq-value entry 'installed))
|
||||
(obsolete (guix-assq-value entry 'obsolete))
|
||||
(installed-entry (cl-find-if
|
||||
(lambda (entry)
|
||||
(string= (guix-assq-value entry 'output)
|
||||
output))
|
||||
installed))
|
||||
(action-type (if installed-entry 'delete 'install)))
|
||||
(guix-info-insert-indent)
|
||||
(guix-format-insert output
|
||||
(if installed-entry
|
||||
'guix-package-info-installed-outputs
|
||||
'guix-package-info-uninstalled-outputs)
|
||||
guix-package-info-output-format)
|
||||
(guix-package-info-insert-action-button action-type entry output)
|
||||
(when obsolete
|
||||
(guix-info-insert-indent)
|
||||
(guix-package-info-insert-action-button 'upgrade entry output))
|
||||
(insert "\n")
|
||||
(when installed-entry
|
||||
(guix-info-insert-entry installed-entry 'installed 2))))
|
||||
|
||||
(defun guix-package-info-insert-action-button (type entry output)
|
||||
"Insert button to process an action on a package OUTPUT at point.
|
||||
TYPE is one of the following symbols: `install', `delete', `upgrade'.
|
||||
ENTRY is an alist with package info."
|
||||
(let ((type-str (capitalize (symbol-name type)))
|
||||
(full-name (guix-get-full-name entry output)))
|
||||
(guix-info-insert-action-button
|
||||
type-str
|
||||
(lambda (btn)
|
||||
(guix-process-package-actions
|
||||
guix-profile
|
||||
`((,(button-get btn 'action-type) (,(button-get btn 'id)
|
||||
,(button-get btn 'output))))
|
||||
(current-buffer)))
|
||||
(concat type-str " '" full-name "'")
|
||||
'action-type type
|
||||
'id (or (guix-assq-value entry 'package-id)
|
||||
(guix-assq-value entry 'id))
|
||||
'output output)))
|
||||
|
||||
(defun guix-package-info-insert-output-path (path &optional _)
|
||||
"Insert PATH of the installed output."
|
||||
(guix-info-insert-val-simple path #'guix-info-insert-file-path))
|
||||
|
||||
(defalias 'guix-package-info-insert-output-dependencies
|
||||
'guix-package-info-insert-output-path)
|
||||
|
||||
|
||||
;;; Inserting a source
|
||||
|
||||
(defface guix-package-info-source
|
||||
'((t :inherit link :underline nil))
|
||||
"Face used for a source URL of a package."
|
||||
:group 'guix-package-info-faces)
|
||||
|
||||
(defcustom guix-package-info-auto-find-source nil
|
||||
"If non-nil, find a source file after pressing a \"Show\" button.
|
||||
If nil, just display the source file path without finding."
|
||||
:type 'boolean
|
||||
:group 'guix-package-info)
|
||||
|
||||
(defcustom guix-package-info-auto-download-source t
|
||||
"If nil, do not automatically download a source file if it doesn't exist.
|
||||
After pressing a \"Show\" button, a derivation of the package
|
||||
source is calculated and a store file path is displayed. If this
|
||||
variable is non-nil and the source file does not exist in the
|
||||
store, it will be automatically downloaded (with a possible
|
||||
prompt depending on `guix-operation-confirm' variable)."
|
||||
:type 'boolean
|
||||
:group 'guix-package-info)
|
||||
|
||||
(defvar guix-package-info-download-buffer nil
|
||||
"Buffer from which a current download operation was performed.")
|
||||
|
||||
(define-button-type 'guix-package-source
|
||||
:supertype 'guix
|
||||
'face 'guix-package-info-source
|
||||
'help-echo ""
|
||||
'action (lambda (_)
|
||||
;; As a source may not be a real URL (e.g., "mirror://..."),
|
||||
;; no action is bound to a source button.
|
||||
(message "Yes, this is the source URL. What did you expect?")))
|
||||
|
||||
(defun guix-package-info-insert-source-url (url &optional _)
|
||||
"Make button from source URL and insert it at point."
|
||||
(guix-insert-button url 'guix-package-source))
|
||||
|
||||
(defun guix-package-info-show-source (entry-id package-id)
|
||||
"Show file name of a package source in the current info buffer.
|
||||
Find the file if needed (see `guix-package-info-auto-find-source').
|
||||
ENTRY-ID is an ID of the current entry (package or output).
|
||||
PACKAGE-ID is an ID of the package which source to show."
|
||||
(let* ((entry (guix-get-entry-by-id entry-id guix-entries))
|
||||
(file (guix-package-source-path package-id)))
|
||||
(or file
|
||||
(error "Couldn't define file path of the package source"))
|
||||
(let* ((new-entry (cons (cons 'source-file file)
|
||||
entry))
|
||||
(entries (cl-substitute-if
|
||||
new-entry
|
||||
(lambda (entry)
|
||||
(equal (guix-assq-value entry 'id)
|
||||
entry-id))
|
||||
guix-entries
|
||||
:count 1)))
|
||||
(guix-redisplay-buffer :entries entries)
|
||||
(if (file-exists-p file)
|
||||
(if guix-package-info-auto-find-source
|
||||
(guix-find-file file)
|
||||
(message "The source store path is displayed."))
|
||||
(if guix-package-info-auto-download-source
|
||||
(guix-package-info-download-source package-id)
|
||||
(message "The source does not exist in the store."))))))
|
||||
|
||||
(defun guix-package-info-download-source (package-id)
|
||||
"Download a source of the package PACKAGE-ID."
|
||||
(setq guix-package-info-download-buffer (current-buffer))
|
||||
(guix-package-source-build-derivation
|
||||
package-id
|
||||
"The source does not exist in the store. Download it?"))
|
||||
|
||||
(defun guix-package-info-insert-source (source entry)
|
||||
"Insert SOURCE from package ENTRY at point.
|
||||
SOURCE is a list of URLs."
|
||||
(guix-info-insert-indent)
|
||||
(if (null source)
|
||||
(guix-format-insert nil)
|
||||
(let* ((source-file (guix-assq-value entry 'source-file))
|
||||
(entry-id (guix-assq-value entry 'id))
|
||||
(package-id (or (guix-assq-value entry 'package-id)
|
||||
entry-id)))
|
||||
(if (null source-file)
|
||||
(guix-info-insert-action-button
|
||||
"Show"
|
||||
(lambda (btn)
|
||||
(guix-package-info-show-source (button-get btn 'entry-id)
|
||||
(button-get btn 'package-id)))
|
||||
"Show the source store path of the current package"
|
||||
'entry-id entry-id
|
||||
'package-id package-id)
|
||||
(unless (file-exists-p source-file)
|
||||
(guix-info-insert-action-button
|
||||
"Download"
|
||||
(lambda (btn)
|
||||
(guix-package-info-download-source
|
||||
(button-get btn 'package-id)))
|
||||
"Download the source into the store"
|
||||
'package-id package-id))
|
||||
(guix-info-insert-val-simple source-file
|
||||
#'guix-info-insert-file-path))
|
||||
(guix-info-insert-val-simple source
|
||||
#'guix-package-info-insert-source-url))))
|
||||
|
||||
(defun guix-package-info-redisplay-after-download ()
|
||||
"Redisplay an 'info' buffer after downloading the package source.
|
||||
This function is used to hide a \"Download\" button if needed."
|
||||
(when (buffer-live-p guix-package-info-download-buffer)
|
||||
(guix-redisplay-buffer :buffer guix-package-info-download-buffer)
|
||||
(setq guix-package-info-download-buffer nil)))
|
||||
|
||||
(add-hook 'guix-after-source-download-hook
|
||||
'guix-package-info-redisplay-after-download)
|
||||
|
||||
|
||||
;;; Displaying outputs
|
||||
|
||||
(guix-define-buffer-type info output
|
||||
:buffer-name "*Guix Package Info*"
|
||||
:required (id package-id installed non-unique))
|
||||
|
||||
(defvar guix-info-insert-output-function nil
|
||||
"Function used to insert an output information.
|
||||
It is called with a single argument - alist of output parameters.
|
||||
If nil, insert output in a default way.")
|
||||
|
||||
(defun guix-output-info-insert-version (version entry)
|
||||
"Insert output VERSION and obsolete text if needed at point."
|
||||
(guix-info-insert-val-default version
|
||||
'guix-package-info-version)
|
||||
(and (guix-assq-value entry 'obsolete)
|
||||
(guix-package-info-insert-obsolete-text)))
|
||||
|
||||
(defun guix-output-info-insert-output (output entry)
|
||||
"Insert OUTPUT and action buttons at point."
|
||||
(let* ((installed (guix-assq-value entry 'installed))
|
||||
(obsolete (guix-assq-value entry 'obsolete))
|
||||
(action-type (if installed 'delete 'install)))
|
||||
(guix-info-insert-val-default
|
||||
output
|
||||
(if installed
|
||||
'guix-package-info-installed-outputs
|
||||
'guix-package-info-uninstalled-outputs))
|
||||
(guix-info-insert-indent)
|
||||
(guix-package-info-insert-action-button action-type entry output)
|
||||
(when obsolete
|
||||
(guix-info-insert-indent)
|
||||
(guix-package-info-insert-action-button 'upgrade entry output))))
|
||||
|
||||
|
||||
;;; Displaying generations
|
||||
|
||||
(guix-define-buffer-type info generation)
|
||||
|
||||
(defface guix-generation-info-number
|
||||
'((t :inherit font-lock-keyword-face))
|
||||
"Face used for a number of a generation."
|
||||
:group 'guix-generation-info-faces)
|
||||
|
||||
(defface guix-generation-info-current
|
||||
'((t :inherit guix-package-info-installed-outputs))
|
||||
"Face used if a generation is the current one."
|
||||
:group 'guix-generation-info-faces)
|
||||
|
||||
(defface guix-generation-info-not-current
|
||||
'((t nil))
|
||||
"Face used if a generation is not the current one."
|
||||
:group 'guix-generation-info-faces)
|
||||
|
||||
(defvar guix-info-insert-generation-function nil
|
||||
"Function used to insert a generation information.
|
||||
It is called with a single argument - alist of generation parameters.
|
||||
If nil, insert generation in a default way.")
|
||||
|
||||
(defun guix-generation-info-insert-number (number &optional _)
|
||||
"Insert generation NUMBER and action buttons."
|
||||
(guix-info-insert-val-default number 'guix-generation-info-number)
|
||||
(guix-info-insert-indent)
|
||||
(guix-info-insert-action-button
|
||||
"Packages"
|
||||
(lambda (btn)
|
||||
(guix-get-show-entries guix-profile 'list guix-package-list-type
|
||||
'generation (button-get btn 'number)))
|
||||
"Show installed packages for this generation"
|
||||
'number number)
|
||||
(guix-info-insert-indent)
|
||||
(guix-info-insert-action-button
|
||||
"Delete"
|
||||
(lambda (btn)
|
||||
(guix-delete-generations guix-profile (list (button-get btn 'number))
|
||||
(current-buffer)))
|
||||
"Delete this generation"
|
||||
'number number))
|
||||
|
||||
(defun guix-generation-info-insert-current (val entry)
|
||||
"Insert boolean value VAL showing whether this generation is current."
|
||||
(if val
|
||||
(guix-info-insert-val-default "Yes" 'guix-generation-info-current)
|
||||
(guix-info-insert-val-default "No" 'guix-generation-info-not-current)
|
||||
(guix-info-insert-indent)
|
||||
(guix-info-insert-action-button
|
||||
"Switch"
|
||||
(lambda (btn)
|
||||
(guix-switch-to-generation guix-profile (button-get btn 'number)
|
||||
(current-buffer)))
|
||||
"Switch to this generation (make it the current one)"
|
||||
'number (guix-assq-value entry 'number))))
|
||||
|
||||
(provide 'guix-info)
|
||||
|
||||
;;; guix-info.el ends here
|
||||
@@ -0,0 +1,19 @@
|
||||
(require 'guix-autoloads)
|
||||
(require 'guix-emacs)
|
||||
|
||||
(defcustom guix-package-enable-at-startup t
|
||||
"If non-nil, activate Emacs packages installed in a user profile.
|
||||
Set this variable to nil before requiring `guix-init' file to
|
||||
avoid loading autoloads of Emacs packages installed in
|
||||
`guix-user-profile'."
|
||||
:type 'boolean
|
||||
:group 'guix)
|
||||
|
||||
(add-to-list 'load-path (guix-emacs-directory))
|
||||
|
||||
(when guix-package-enable-at-startup
|
||||
(guix-emacs-load-autoloads 'all))
|
||||
|
||||
(add-hook 'scheme-mode-hook 'guix-devel-activate-mode-maybe)
|
||||
|
||||
(provide 'guix-init)
|
||||
@@ -0,0 +1,894 @@
|
||||
;;; guix-list.el --- List buffers for displaying entries -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright © 2014, 2015 Alex Kost <alezost@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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file provides a list-like buffer for displaying information
|
||||
;; about Guix packages and generations.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'cl-lib)
|
||||
(require 'tabulated-list)
|
||||
(require 'guix-info)
|
||||
(require 'guix-base)
|
||||
(require 'guix-utils)
|
||||
|
||||
(defgroup guix-list nil
|
||||
"General settings for list buffers."
|
||||
:prefix "guix-list-"
|
||||
:group 'guix)
|
||||
|
||||
(defgroup guix-list-faces nil
|
||||
"Faces for list buffers."
|
||||
:group 'guix-list
|
||||
:group 'guix-faces)
|
||||
|
||||
(defface guix-list-file-path
|
||||
'((t :inherit guix-info-file-path))
|
||||
"Face used for file paths."
|
||||
:group 'guix-list-faces)
|
||||
|
||||
(defcustom guix-list-describe-warning-count 10
|
||||
"The maximum number of entries for describing without a warning.
|
||||
If a user wants to describe more than this number of marked
|
||||
entries, he will be prompted for confirmation."
|
||||
:type 'integer
|
||||
:group 'guix-list)
|
||||
|
||||
(defvar guix-list-column-format
|
||||
`((package
|
||||
(name 20 t)
|
||||
(version 10 nil)
|
||||
(outputs 13 t)
|
||||
(installed 13 t)
|
||||
(synopsis 30 nil))
|
||||
(output
|
||||
(name 20 t)
|
||||
(version 10 nil)
|
||||
(output 9 t)
|
||||
(installed 12 t)
|
||||
(synopsis 30 nil))
|
||||
(generation
|
||||
(number 5
|
||||
,(lambda (a b) (guix-list-sort-numerically 0 a b))
|
||||
:right-align t)
|
||||
(current 10 t)
|
||||
(time 20 t)
|
||||
(path 30 t)))
|
||||
"Columns displayed in list buffers.
|
||||
Each element of the list has a form:
|
||||
|
||||
(ENTRY-TYPE . ((PARAM WIDTH SORT . PROPS) ...))
|
||||
|
||||
PARAM is the name of an entry parameter of ENTRY-TYPE. For the
|
||||
meaning of WIDTH, SORT and PROPS, see `tabulated-list-format'.")
|
||||
|
||||
(defvar guix-list-column-titles
|
||||
'((generation
|
||||
(number . "N.")))
|
||||
"Column titles for list buffers.
|
||||
Has the same structure as `guix-param-titles', but titles from
|
||||
this list have a priority.")
|
||||
|
||||
(defvar guix-list-column-value-methods
|
||||
'((package
|
||||
(name . guix-package-list-get-name)
|
||||
(synopsis . guix-list-get-one-line)
|
||||
(description . guix-list-get-one-line)
|
||||
(installed . guix-package-list-get-installed-outputs))
|
||||
(output
|
||||
(name . guix-package-list-get-name)
|
||||
(synopsis . guix-list-get-one-line)
|
||||
(description . guix-list-get-one-line))
|
||||
(generation
|
||||
(current . guix-generation-list-get-current)
|
||||
(time . guix-list-get-time)
|
||||
(path . guix-list-get-file-path)))
|
||||
"Methods for inserting parameter values in columns.
|
||||
Each element of the list has a form:
|
||||
|
||||
(ENTRY-TYPE . ((PARAM . FUN) ...))
|
||||
|
||||
PARAM is the name of an entry parameter of ENTRY-TYPE.
|
||||
|
||||
FUN is a function returning a value that will be inserted. The
|
||||
function is called with 2 arguments: the first one is the value
|
||||
of the parameter; the second argument is an entry info (alist of
|
||||
parameters and their values).")
|
||||
|
||||
(defun guix-list-get-param-title (entry-type param)
|
||||
"Return title of an ENTRY-TYPE entry parameter PARAM."
|
||||
(or (guix-assq-value guix-list-column-titles
|
||||
entry-type param)
|
||||
(guix-get-param-title entry-type param)))
|
||||
|
||||
(defun guix-list-get-column-format (entry-type)
|
||||
"Return column format for ENTRY-TYPE."
|
||||
(guix-assq-value guix-list-column-format entry-type))
|
||||
|
||||
(defun guix-list-get-displayed-params (entry-type)
|
||||
"Return list of parameters of ENTRY-TYPE that should be displayed."
|
||||
(mapcar #'car
|
||||
(guix-list-get-column-format entry-type)))
|
||||
|
||||
(defun guix-list-get-sort-key (entry-type param &optional invert)
|
||||
"Return suitable sort key for `tabulated-list-sort-key'.
|
||||
Define column title by ENTRY-TYPE and PARAM. If INVERT is
|
||||
non-nil, invert the sort."
|
||||
(when (memq param (guix-list-get-displayed-params entry-type))
|
||||
(cons (guix-list-get-param-title entry-type param) invert)))
|
||||
|
||||
(defun guix-list-sort-numerically (column a b)
|
||||
"Compare COLUMN of tabulated entries A and B numerically.
|
||||
It is a sort predicate for `tabulated-list-format'.
|
||||
Return non-nil, if B is bigger than A."
|
||||
(cl-flet ((num (entry)
|
||||
(string-to-number (aref (cadr entry) column))))
|
||||
(> (num b) (num a))))
|
||||
|
||||
(defun guix-list-make-tabulated-vector (entry-type fun)
|
||||
"Call FUN on each column specification for ENTRY-TYPE.
|
||||
|
||||
FUN is called with 2 argument: parameter name and column
|
||||
specification (see `guix-list-column-format').
|
||||
|
||||
Return a vector made of values of FUN calls."
|
||||
(apply #'vector
|
||||
(mapcar (lambda (col-spec)
|
||||
(funcall fun (car col-spec) (cdr col-spec)))
|
||||
(guix-list-get-column-format entry-type))))
|
||||
|
||||
(defun guix-list-get-list-format (entry-type)
|
||||
"Return ENTRY-TYPE list specification for `tabulated-list-format'."
|
||||
(guix-list-make-tabulated-vector
|
||||
entry-type
|
||||
(lambda (param spec)
|
||||
(cons (guix-list-get-param-title entry-type param)
|
||||
spec))))
|
||||
|
||||
(defun guix-list-insert-entries (entries entry-type)
|
||||
"Display ENTRIES of ENTRY-TYPE in the current list buffer.
|
||||
ENTRIES should have a form of `guix-entries'."
|
||||
(setq tabulated-list-entries
|
||||
(guix-list-get-tabulated-entries entries entry-type))
|
||||
(tabulated-list-print))
|
||||
|
||||
(defun guix-list-get-tabulated-entries (entries entry-type)
|
||||
"Return list of values of ENTRY-TYPE for `tabulated-list-entries'.
|
||||
Values are taken from ENTRIES which should have the form of
|
||||
`guix-entries'."
|
||||
(mapcar (lambda (entry)
|
||||
(list (guix-assq-value entry 'id)
|
||||
(guix-list-get-tabulated-entry entry entry-type)))
|
||||
entries))
|
||||
|
||||
(defun guix-list-get-tabulated-entry (entry entry-type)
|
||||
"Return array of values for `tabulated-list-entries'.
|
||||
Parameters are taken from ENTRY of ENTRY-TYPE."
|
||||
(guix-list-make-tabulated-vector
|
||||
entry-type
|
||||
(lambda (param _)
|
||||
(let ((val (guix-assq-value entry param))
|
||||
(fun (guix-assq-value guix-list-column-value-methods
|
||||
entry-type param)))
|
||||
(if fun
|
||||
(funcall fun val entry)
|
||||
(guix-get-string val))))))
|
||||
|
||||
(defun guix-list-get-one-line (val &optional _)
|
||||
"Return one-line string from a multi-line string VAL.
|
||||
VAL may be nil."
|
||||
(if val
|
||||
(guix-get-one-line val)
|
||||
(guix-get-string nil)))
|
||||
|
||||
(defun guix-list-get-time (seconds &optional _)
|
||||
"Return formatted time string from SECONDS."
|
||||
(guix-get-time-string seconds))
|
||||
|
||||
(defun guix-list-get-file-path (path &optional _)
|
||||
"Return PATH button specification for `tabulated-list-entries'."
|
||||
(list path
|
||||
'face 'guix-list-file-path
|
||||
'action (lambda (btn) (find-file (button-label btn)))
|
||||
'follow-link t
|
||||
'help-echo "Find file"))
|
||||
|
||||
(defun guix-list-current-id ()
|
||||
"Return ID of the current entry."
|
||||
(or (tabulated-list-get-id)
|
||||
(user-error "No entry here")))
|
||||
|
||||
(defun guix-list-current-entry ()
|
||||
"Return alist of the current entry info."
|
||||
(guix-get-entry-by-id (guix-list-current-id) guix-entries))
|
||||
|
||||
(defun guix-list-current-package-id ()
|
||||
"Return ID of the current package."
|
||||
(cl-ecase major-mode
|
||||
(guix-package-list-mode
|
||||
(guix-list-current-id))
|
||||
(guix-output-list-mode
|
||||
(guix-assq-value (guix-list-current-entry) 'package-id))))
|
||||
|
||||
(defun guix-list-for-each-line (fun &rest args)
|
||||
"Call FUN with ARGS for each entry line."
|
||||
(or (derived-mode-p 'guix-list-mode)
|
||||
(error "The current buffer is not in Guix List mode"))
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(while (not (eobp))
|
||||
(apply fun args)
|
||||
(forward-line))))
|
||||
|
||||
(defun guix-list-fold-lines (fun init)
|
||||
"Fold over entry lines in the current list buffer.
|
||||
Call FUN with RESULT as argument for each line, using INIT as
|
||||
the initial value of RESULT. Return the final result."
|
||||
(let ((res init))
|
||||
(guix-list-for-each-line
|
||||
(lambda () (setq res (funcall fun res))))
|
||||
res))
|
||||
|
||||
|
||||
;;; Marking and sorting
|
||||
|
||||
(defvar-local guix-list-marked nil
|
||||
"List of the marked entries.
|
||||
Each element of the list has a form:
|
||||
|
||||
(ID MARK-NAME . ARGS)
|
||||
|
||||
ID is an entry ID.
|
||||
MARK-NAME is a symbol from `guix-list-mark-alist'.
|
||||
ARGS is a list of additional values.")
|
||||
|
||||
(defvar guix-list-mark-alist
|
||||
'((empty . ?\s)
|
||||
(general . ?*))
|
||||
"Alist of available mark names and mark characters.")
|
||||
|
||||
(defsubst guix-list-get-mark (name)
|
||||
"Return mark character by its NAME."
|
||||
(or (guix-assq-value guix-list-mark-alist name)
|
||||
(error "Mark '%S' not found" name)))
|
||||
|
||||
(defsubst guix-list-get-mark-string (name)
|
||||
"Return mark string by its NAME."
|
||||
(string (guix-list-get-mark name)))
|
||||
|
||||
(defun guix-list-current-mark ()
|
||||
"Return mark character of the current line."
|
||||
(char-after (line-beginning-position)))
|
||||
|
||||
(defun guix-list-get-marked (&rest mark-names)
|
||||
"Return list of specs of entries marked with any mark from MARK-NAMES.
|
||||
Entry specs are elements from `guix-list-marked' list.
|
||||
If MARK-NAMES are not specified, use all marks from
|
||||
`guix-list-mark-alist' except the `empty' one."
|
||||
(or mark-names
|
||||
(setq mark-names
|
||||
(delq 'empty
|
||||
(mapcar #'car guix-list-mark-alist))))
|
||||
(cl-remove-if-not (lambda (assoc)
|
||||
(memq (cadr assoc) mark-names))
|
||||
guix-list-marked))
|
||||
|
||||
(defun guix-list-get-marked-args (mark-name)
|
||||
"Return list of (ID . ARGS) elements from lines marked with MARK-NAME.
|
||||
See `guix-list-marked' for the meaning of ARGS."
|
||||
(mapcar (lambda (spec)
|
||||
(let ((id (car spec))
|
||||
(args (cddr spec)))
|
||||
(cons id args)))
|
||||
(guix-list-get-marked mark-name)))
|
||||
|
||||
(defun guix-list-get-marked-id-list (&rest mark-names)
|
||||
"Return list of IDs of entries marked with any mark from MARK-NAMES.
|
||||
See `guix-list-get-marked' for details."
|
||||
(mapcar #'car (apply #'guix-list-get-marked mark-names)))
|
||||
|
||||
(defun guix-list--mark (mark-name &optional advance &rest args)
|
||||
"Put a mark on the current line.
|
||||
Also add the current entry to `guix-list-marked' using its ID and ARGS.
|
||||
MARK-NAME is a symbol from `guix-list-mark-alist'.
|
||||
If ADVANCE is non-nil, move forward by one line after marking."
|
||||
(let ((id (guix-list-current-id)))
|
||||
(if (eq mark-name 'empty)
|
||||
(setq guix-list-marked (assq-delete-all id guix-list-marked))
|
||||
(let ((assoc (assq id guix-list-marked))
|
||||
(val (cons mark-name args)))
|
||||
(if assoc
|
||||
(setcdr assoc val)
|
||||
(push (cons id val) guix-list-marked)))))
|
||||
(tabulated-list-put-tag (guix-list-get-mark-string mark-name)
|
||||
advance))
|
||||
|
||||
(defun guix-list-mark (&optional arg)
|
||||
"Mark the current line and move to the next line.
|
||||
With ARG, mark all lines."
|
||||
(interactive "P")
|
||||
(if arg
|
||||
(guix-list-mark-all)
|
||||
(guix-list--mark 'general t)))
|
||||
|
||||
(defun guix-list-mark-all (&optional mark-name)
|
||||
"Mark all lines with MARK-NAME mark.
|
||||
MARK-NAME is a symbol from `guix-list-mark-alist'.
|
||||
Interactively, put a general mark on all lines."
|
||||
(interactive)
|
||||
(or mark-name (setq mark-name 'general))
|
||||
(guix-list-for-each-line #'guix-list--mark mark-name))
|
||||
|
||||
(defun guix-list-unmark (&optional arg)
|
||||
"Unmark the current line and move to the next line.
|
||||
With ARG, unmark all lines."
|
||||
(interactive "P")
|
||||
(if arg
|
||||
(guix-list-unmark-all)
|
||||
(guix-list--mark 'empty t)))
|
||||
|
||||
(defun guix-list-unmark-backward ()
|
||||
"Move up one line and unmark it."
|
||||
(interactive)
|
||||
(forward-line -1)
|
||||
(guix-list--mark 'empty))
|
||||
|
||||
(defun guix-list-unmark-all ()
|
||||
"Unmark all lines."
|
||||
(interactive)
|
||||
(guix-list-mark-all 'empty))
|
||||
|
||||
(defun guix-list-restore-marks ()
|
||||
"Put marks according to `guix-list-mark-alist'."
|
||||
(guix-list-for-each-line
|
||||
(lambda ()
|
||||
(let ((mark-name (car (guix-assq-value guix-list-marked
|
||||
(guix-list-current-id)))))
|
||||
(tabulated-list-put-tag
|
||||
(guix-list-get-mark-string (or mark-name 'empty)))))))
|
||||
|
||||
(defun guix-list-sort (&optional n)
|
||||
"Sort guix list entries by the column at point.
|
||||
With a numeric prefix argument N, sort the Nth column.
|
||||
Same as `tabulated-list-sort', but also restore marks after sorting."
|
||||
(interactive "P")
|
||||
(tabulated-list-sort n)
|
||||
(guix-list-restore-marks))
|
||||
|
||||
|
||||
(defvar guix-list-mode-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(set-keymap-parent
|
||||
map (make-composed-keymap guix-root-map
|
||||
tabulated-list-mode-map))
|
||||
(define-key map (kbd "RET") 'guix-list-describe)
|
||||
(define-key map (kbd "m") 'guix-list-mark)
|
||||
(define-key map (kbd "*") 'guix-list-mark)
|
||||
(define-key map (kbd "u") 'guix-list-unmark)
|
||||
(define-key map (kbd "DEL") 'guix-list-unmark-backward)
|
||||
(define-key map [remap tabulated-list-sort] 'guix-list-sort)
|
||||
map)
|
||||
"Parent keymap for list buffers.")
|
||||
|
||||
(define-derived-mode guix-list-mode tabulated-list-mode "Guix-List"
|
||||
"Parent mode for displaying information in list buffers."
|
||||
(setq tabulated-list-padding 2))
|
||||
|
||||
(defmacro guix-list-define-entry-type (entry-type &rest args)
|
||||
"Define common stuff for displaying ENTRY-TYPE entries in list buffers.
|
||||
|
||||
Remaining argument (ARGS) should have a form [KEYWORD VALUE] ... The
|
||||
following keywords are available:
|
||||
|
||||
- `:sort-key' - default sort key for the tabulated list buffer.
|
||||
|
||||
- `:invert-sort' - if non-nil, invert initial sort.
|
||||
|
||||
- `:marks' - default value for the defined
|
||||
`guix-ENTRY-TYPE-mark-alist' variable.
|
||||
|
||||
This macro defines the following functions:
|
||||
|
||||
- `guix-ENTRY-TYPE-mark-MARK-NAME' functions for each mark
|
||||
specified in `:marks' argument."
|
||||
(let* ((entry-type-str (symbol-name entry-type))
|
||||
(prefix (concat "guix-" entry-type-str "-list"))
|
||||
(mode-str (concat prefix "-mode"))
|
||||
(init-fun (intern (concat prefix "-mode-initialize")))
|
||||
(marks-var (intern (concat prefix "-mark-alist")))
|
||||
(marks-val nil)
|
||||
(sort-key nil)
|
||||
(invert-sort nil))
|
||||
|
||||
;; Process the keyword args.
|
||||
(while (keywordp (car args))
|
||||
(pcase (pop args)
|
||||
(`:sort-key (setq sort-key (pop args)))
|
||||
(`:invert-sort (setq invert-sort (pop args)))
|
||||
(`:marks (setq marks-val (pop args)))
|
||||
(_ (pop args))))
|
||||
|
||||
`(progn
|
||||
(defvar ,marks-var ',marks-val
|
||||
,(concat "Alist of additional marks for `" mode-str "'.\n"
|
||||
"Marks from this list are added to `guix-list-mark-alist'."))
|
||||
|
||||
,@(mapcar (lambda (mark-spec)
|
||||
(let* ((mark-name (car mark-spec))
|
||||
(mark-name-str (symbol-name mark-name)))
|
||||
`(defun ,(intern (concat prefix "-mark-" mark-name-str "-simple")) ()
|
||||
,(concat "Put '" mark-name-str "' mark and move to the next line.\n"
|
||||
"Also add the current entry to `guix-list-marked'.")
|
||||
(interactive)
|
||||
(guix-list--mark ',mark-name t))))
|
||||
marks-val)
|
||||
|
||||
(defun ,init-fun ()
|
||||
,(concat "Initial settings for `" mode-str "'.")
|
||||
,(when sort-key
|
||||
`(setq tabulated-list-sort-key
|
||||
(guix-list-get-sort-key
|
||||
',entry-type ',sort-key ,invert-sort)))
|
||||
(setq tabulated-list-format
|
||||
(guix-list-get-list-format ',entry-type))
|
||||
(setq-local guix-list-mark-alist
|
||||
(append guix-list-mark-alist ,marks-var))
|
||||
(tabulated-list-init-header)))))
|
||||
|
||||
(put 'guix-list-define-entry-type 'lisp-indent-function 'defun)
|
||||
|
||||
(defun guix-list-describe-maybe (entry-type ids)
|
||||
"Describe ENTRY-TYPE entries in info buffer using list of IDS."
|
||||
(let ((count (length ids)))
|
||||
(when (or (<= count guix-list-describe-warning-count)
|
||||
(y-or-n-p (format "Do you really want to describe %d entries? "
|
||||
count)))
|
||||
(apply #'guix-get-show-entries
|
||||
guix-profile 'info entry-type 'id ids))))
|
||||
|
||||
(defun guix-list-describe (&optional arg)
|
||||
"Describe entries marked with a general mark.
|
||||
If no entries are marked, describe the current entry.
|
||||
With prefix (if ARG is non-nil), describe entries marked with any mark."
|
||||
(interactive "P")
|
||||
(let ((ids (or (apply #'guix-list-get-marked-id-list
|
||||
(unless arg '(general)))
|
||||
(list (guix-list-current-id)))))
|
||||
(guix-list-describe-maybe guix-entry-type ids)))
|
||||
|
||||
(defun guix-list-edit-package ()
|
||||
"Go to the location of the current package."
|
||||
(interactive)
|
||||
(guix-edit (guix-list-current-package-id)))
|
||||
|
||||
|
||||
;;; Displaying packages
|
||||
|
||||
(guix-define-buffer-type list package)
|
||||
|
||||
(guix-list-define-entry-type package
|
||||
:sort-key name
|
||||
:marks ((install . ?I)
|
||||
(upgrade . ?U)
|
||||
(delete . ?D)))
|
||||
|
||||
(defface guix-package-list-installed
|
||||
'((t :inherit guix-package-info-installed-outputs))
|
||||
"Face used if there are installed outputs for the current package."
|
||||
:group 'guix-package-list-faces)
|
||||
|
||||
(defface guix-package-list-obsolete
|
||||
'((t :inherit guix-package-info-obsolete))
|
||||
"Face used if a package is obsolete."
|
||||
:group 'guix-package-list-faces)
|
||||
|
||||
(defcustom guix-package-list-generation-marking-enabled nil
|
||||
"If non-nil, allow putting marks in a list with 'generation packages'.
|
||||
|
||||
By default this is disabled, because it may be confusing. For
|
||||
example a package is installed in some generation, so a user can
|
||||
mark it for deletion in the list of packages from this
|
||||
generation, but the package may not be installed in the latest
|
||||
generation, so actually it cannot be deleted.
|
||||
|
||||
If you managed to understand the explanation above or if you
|
||||
really know what you do or if you just don't care, you can set
|
||||
this variable to t. It should not do much harm anyway (most
|
||||
likely)."
|
||||
:type 'boolean
|
||||
:group 'guix-package-list)
|
||||
|
||||
(let ((map guix-package-list-mode-map))
|
||||
(define-key map (kbd "e") 'guix-list-edit-package)
|
||||
(define-key map (kbd "x") 'guix-package-list-execute)
|
||||
(define-key map (kbd "i") 'guix-package-list-mark-install)
|
||||
(define-key map (kbd "d") 'guix-package-list-mark-delete)
|
||||
(define-key map (kbd "U") 'guix-package-list-mark-upgrade)
|
||||
(define-key map (kbd "^") 'guix-package-list-mark-upgrades))
|
||||
|
||||
(defun guix-package-list-get-name (name entry)
|
||||
"Return NAME of the package ENTRY.
|
||||
Colorize it with `guix-package-list-installed' or
|
||||
`guix-package-list-obsolete' if needed."
|
||||
(guix-get-string name
|
||||
(cond ((guix-assq-value entry 'obsolete)
|
||||
'guix-package-list-obsolete)
|
||||
((guix-assq-value entry 'installed)
|
||||
'guix-package-list-installed))))
|
||||
|
||||
(defun guix-package-list-get-installed-outputs (installed &optional _)
|
||||
"Return string with outputs from INSTALLED entries."
|
||||
(guix-get-string
|
||||
(mapcar (lambda (entry)
|
||||
(guix-assq-value entry 'output))
|
||||
installed)))
|
||||
|
||||
(defun guix-package-list-marking-check ()
|
||||
"Signal an error if marking is disabled for the current buffer."
|
||||
(when (and (not guix-package-list-generation-marking-enabled)
|
||||
(or (derived-mode-p 'guix-package-list-mode)
|
||||
(derived-mode-p 'guix-output-list-mode))
|
||||
(eq guix-search-type 'generation))
|
||||
(error "Action marks are disabled for lists of 'generation packages'")))
|
||||
|
||||
(defun guix-package-list-mark-outputs (mark default
|
||||
&optional prompt available)
|
||||
"Mark the current package with MARK and move to the next line.
|
||||
If PROMPT is non-nil, use it to ask a user for outputs from
|
||||
AVAILABLE list, otherwise mark all DEFAULT outputs."
|
||||
(let ((outputs (if prompt
|
||||
(guix-completing-read-multiple
|
||||
prompt available nil t)
|
||||
default)))
|
||||
(apply #'guix-list--mark mark t outputs)))
|
||||
|
||||
(defun guix-package-list-mark-install (&optional arg)
|
||||
"Mark the current package for installation and move to the next line.
|
||||
With ARG, prompt for the outputs to install (several outputs may
|
||||
be separated with \",\")."
|
||||
(interactive "P")
|
||||
(guix-package-list-marking-check)
|
||||
(let* ((entry (guix-list-current-entry))
|
||||
(all (guix-assq-value entry 'outputs))
|
||||
(installed (guix-get-installed-outputs entry))
|
||||
(available (cl-set-difference all installed :test #'string=)))
|
||||
(or available
|
||||
(user-error "This package is already installed"))
|
||||
(guix-package-list-mark-outputs
|
||||
'install '("out")
|
||||
(and arg "Output(s) to install: ")
|
||||
available)))
|
||||
|
||||
(defun guix-package-list-mark-delete (&optional arg)
|
||||
"Mark the current package for deletion and move to the next line.
|
||||
With ARG, prompt for the outputs to delete (several outputs may
|
||||
be separated with \",\")."
|
||||
(interactive "P")
|
||||
(guix-package-list-marking-check)
|
||||
(let* ((entry (guix-list-current-entry))
|
||||
(installed (guix-get-installed-outputs entry)))
|
||||
(or installed
|
||||
(user-error "This package is not installed"))
|
||||
(guix-package-list-mark-outputs
|
||||
'delete installed
|
||||
(and arg "Output(s) to delete: ")
|
||||
installed)))
|
||||
|
||||
(defun guix-package-list-mark-upgrade (&optional arg)
|
||||
"Mark the current package for upgrading and move to the next line.
|
||||
With ARG, prompt for the outputs to upgrade (several outputs may
|
||||
be separated with \",\")."
|
||||
(interactive "P")
|
||||
(guix-package-list-marking-check)
|
||||
(let* ((entry (guix-list-current-entry))
|
||||
(installed (guix-get-installed-outputs entry)))
|
||||
(or installed
|
||||
(user-error "This package is not installed"))
|
||||
(when (or (guix-assq-value entry 'obsolete)
|
||||
(y-or-n-p "This package is not obsolete. Try to upgrade it anyway? "))
|
||||
(guix-package-list-mark-outputs
|
||||
'upgrade installed
|
||||
(and arg "Output(s) to upgrade: ")
|
||||
installed))))
|
||||
|
||||
(defun guix-list-mark-package-upgrades (fun)
|
||||
"Mark all obsolete packages for upgrading.
|
||||
Use FUN to perform marking of the current line. FUN should
|
||||
accept an entry as argument."
|
||||
(guix-package-list-marking-check)
|
||||
(let ((obsolete (cl-remove-if-not
|
||||
(lambda (entry)
|
||||
(guix-assq-value entry 'obsolete))
|
||||
guix-entries)))
|
||||
(guix-list-for-each-line
|
||||
(lambda ()
|
||||
(let* ((id (guix-list-current-id))
|
||||
(entry (cl-find-if
|
||||
(lambda (entry)
|
||||
(equal id (guix-assq-value entry 'id)))
|
||||
obsolete)))
|
||||
(when entry
|
||||
(funcall fun entry)))))))
|
||||
|
||||
(defun guix-package-list-mark-upgrades ()
|
||||
"Mark all obsolete packages for upgrading."
|
||||
(interactive)
|
||||
(guix-list-mark-package-upgrades
|
||||
(lambda (entry)
|
||||
(apply #'guix-list--mark
|
||||
'upgrade nil
|
||||
(guix-get-installed-outputs entry)))))
|
||||
|
||||
(defun guix-list-execute-package-actions (fun)
|
||||
"Perform actions on the marked packages.
|
||||
Use FUN to define actions suitable for `guix-process-package-actions'.
|
||||
FUN should accept action-type as argument."
|
||||
(let ((actions (delq nil
|
||||
(mapcar fun '(install delete upgrade)))))
|
||||
(if actions
|
||||
(guix-process-package-actions
|
||||
guix-profile actions (current-buffer))
|
||||
(user-error "No operations specified"))))
|
||||
|
||||
(defun guix-package-list-execute ()
|
||||
"Perform actions on the marked packages."
|
||||
(interactive)
|
||||
(guix-list-execute-package-actions #'guix-package-list-make-action))
|
||||
|
||||
(defun guix-package-list-make-action (action-type)
|
||||
"Return action specification for the packages marked with ACTION-TYPE.
|
||||
Return nil, if there are no packages marked with ACTION-TYPE.
|
||||
The specification is suitable for `guix-process-package-actions'."
|
||||
(let ((specs (guix-list-get-marked-args action-type)))
|
||||
(and specs (cons action-type specs))))
|
||||
|
||||
|
||||
;;; Displaying outputs
|
||||
|
||||
(guix-define-buffer-type list output
|
||||
:buffer-name "*Guix Package List*"
|
||||
:required (package-id))
|
||||
|
||||
(guix-list-define-entry-type output
|
||||
:sort-key name
|
||||
:marks ((install . ?I)
|
||||
(upgrade . ?U)
|
||||
(delete . ?D)))
|
||||
|
||||
(let ((map guix-output-list-mode-map))
|
||||
(define-key map (kbd "RET") 'guix-output-list-describe)
|
||||
(define-key map (kbd "e") 'guix-list-edit-package)
|
||||
(define-key map (kbd "x") 'guix-output-list-execute)
|
||||
(define-key map (kbd "i") 'guix-output-list-mark-install)
|
||||
(define-key map (kbd "d") 'guix-output-list-mark-delete)
|
||||
(define-key map (kbd "U") 'guix-output-list-mark-upgrade)
|
||||
(define-key map (kbd "^") 'guix-output-list-mark-upgrades))
|
||||
|
||||
(defun guix-output-list-mark-install ()
|
||||
"Mark the current output for installation and move to the next line."
|
||||
(interactive)
|
||||
(guix-package-list-marking-check)
|
||||
(let* ((entry (guix-list-current-entry))
|
||||
(installed (guix-assq-value entry 'installed)))
|
||||
(if installed
|
||||
(user-error "This output is already installed")
|
||||
(guix-list--mark 'install t))))
|
||||
|
||||
(defun guix-output-list-mark-delete ()
|
||||
"Mark the current output for deletion and move to the next line."
|
||||
(interactive)
|
||||
(guix-package-list-marking-check)
|
||||
(let* ((entry (guix-list-current-entry))
|
||||
(installed (guix-assq-value entry 'installed)))
|
||||
(if installed
|
||||
(guix-list--mark 'delete t)
|
||||
(user-error "This output is not installed"))))
|
||||
|
||||
(defun guix-output-list-mark-upgrade ()
|
||||
"Mark the current output for deletion and move to the next line."
|
||||
(interactive)
|
||||
(guix-package-list-marking-check)
|
||||
(let* ((entry (guix-list-current-entry))
|
||||
(installed (guix-assq-value entry 'installed)))
|
||||
(or installed
|
||||
(user-error "This output is not installed"))
|
||||
(when (or (guix-assq-value entry 'obsolete)
|
||||
(y-or-n-p "This output is not obsolete. Try to upgrade it anyway? "))
|
||||
(guix-list--mark 'upgrade t))))
|
||||
|
||||
(defun guix-output-list-mark-upgrades ()
|
||||
"Mark all obsolete package outputs for upgrading."
|
||||
(interactive)
|
||||
(guix-list-mark-package-upgrades
|
||||
(lambda (_) (guix-list--mark 'upgrade))))
|
||||
|
||||
(defun guix-output-list-execute ()
|
||||
"Perform actions on the marked outputs."
|
||||
(interactive)
|
||||
(guix-list-execute-package-actions #'guix-output-list-make-action))
|
||||
|
||||
(defun guix-output-list-make-action (action-type)
|
||||
"Return action specification for the outputs marked with ACTION-TYPE.
|
||||
Return nil, if there are no outputs marked with ACTION-TYPE.
|
||||
The specification is suitable for `guix-process-output-actions'."
|
||||
(let ((ids (guix-list-get-marked-id-list action-type)))
|
||||
(and ids (cons action-type
|
||||
(mapcar #'guix-get-package-id-and-output-by-output-id
|
||||
ids)))))
|
||||
|
||||
(defun guix-output-list-describe (&optional arg)
|
||||
"Describe outputs or packages marked with a general mark.
|
||||
If no entries are marked, describe the current output or package.
|
||||
With prefix (if ARG is non-nil), describe entries marked with any mark.
|
||||
Also see `guix-package-info-type'."
|
||||
(interactive "P")
|
||||
(if (eq guix-package-info-type 'output)
|
||||
(guix-list-describe arg)
|
||||
(let* ((oids (or (apply #'guix-list-get-marked-id-list
|
||||
(unless arg '(general)))
|
||||
(list (guix-list-current-id))))
|
||||
(pids (mapcar (lambda (oid)
|
||||
(car (guix-get-package-id-and-output-by-output-id
|
||||
oid)))
|
||||
oids)))
|
||||
(guix-list-describe-maybe 'package (cl-remove-duplicates pids)))))
|
||||
|
||||
|
||||
;;; Displaying generations
|
||||
|
||||
(guix-define-buffer-type list generation)
|
||||
|
||||
(guix-list-define-entry-type generation
|
||||
:sort-key number
|
||||
:invert-sort t
|
||||
:marks ((delete . ?D)))
|
||||
|
||||
(let ((map guix-generation-list-mode-map))
|
||||
(define-key map (kbd "RET") 'guix-generation-list-show-packages)
|
||||
(define-key map (kbd "+") 'guix-generation-list-show-added-packages)
|
||||
(define-key map (kbd "-") 'guix-generation-list-show-removed-packages)
|
||||
(define-key map (kbd "=") 'guix-generation-list-diff)
|
||||
(define-key map (kbd "D") 'guix-generation-list-diff)
|
||||
(define-key map (kbd "e") 'guix-generation-list-ediff)
|
||||
(define-key map (kbd "x") 'guix-generation-list-execute)
|
||||
(define-key map (kbd "i") 'guix-list-describe)
|
||||
(define-key map (kbd "s") 'guix-generation-list-switch)
|
||||
(define-key map (kbd "d") 'guix-generation-list-mark-delete))
|
||||
|
||||
(defun guix-generation-list-get-current (val &optional _)
|
||||
"Return string from VAL showing whether this generation is current.
|
||||
VAL is a boolean value."
|
||||
(if val "(current)" ""))
|
||||
|
||||
(defun guix-generation-list-switch ()
|
||||
"Switch current profile to the generation at point."
|
||||
(interactive)
|
||||
(let* ((entry (guix-list-current-entry))
|
||||
(current (guix-assq-value entry 'current))
|
||||
(number (guix-assq-value entry 'number)))
|
||||
(if current
|
||||
(user-error "This generation is already the current one")
|
||||
(guix-switch-to-generation guix-profile number (current-buffer)))))
|
||||
|
||||
(defun guix-generation-list-show-packages ()
|
||||
"List installed packages for the generation at point."
|
||||
(interactive)
|
||||
(guix-get-show-entries guix-profile 'list guix-package-list-type
|
||||
'generation (guix-list-current-id)))
|
||||
|
||||
(defun guix-generation-list-generations-to-compare ()
|
||||
"Return a sorted list of 2 marked generations for comparing."
|
||||
(let ((numbers (guix-list-get-marked-id-list 'general)))
|
||||
(if (/= (length numbers) 2)
|
||||
(user-error "2 generations should be marked for comparing")
|
||||
(sort numbers #'<))))
|
||||
|
||||
(defun guix-generation-list-show-added-packages ()
|
||||
"List package outputs added to the latest marked generation.
|
||||
If 2 generations are marked with \\[guix-list-mark], display
|
||||
outputs installed in the latest marked generation that were not
|
||||
installed in the other one."
|
||||
(interactive)
|
||||
(apply #'guix-get-show-entries
|
||||
guix-profile 'list 'output 'generation-diff
|
||||
(reverse (guix-generation-list-generations-to-compare))))
|
||||
|
||||
(defun guix-generation-list-show-removed-packages ()
|
||||
"List package outputs removed from the latest marked generation.
|
||||
If 2 generations are marked with \\[guix-list-mark], display
|
||||
outputs not installed in the latest marked generation that were
|
||||
installed in the other one."
|
||||
(interactive)
|
||||
(apply #'guix-get-show-entries
|
||||
guix-profile 'list 'output 'generation-diff
|
||||
(guix-generation-list-generations-to-compare)))
|
||||
|
||||
(defun guix-generation-list-compare (diff-fun gen-fun)
|
||||
"Run GEN-FUN on the 2 marked generations and run DIFF-FUN on the results."
|
||||
(cl-multiple-value-bind (gen1 gen2)
|
||||
(guix-generation-list-generations-to-compare)
|
||||
(funcall diff-fun
|
||||
(funcall gen-fun gen1)
|
||||
(funcall gen-fun gen2))))
|
||||
|
||||
(defun guix-generation-list-ediff-manifests ()
|
||||
"Run Ediff on manifests of the 2 marked generations."
|
||||
(interactive)
|
||||
(guix-generation-list-compare
|
||||
#'ediff-files
|
||||
#'guix-profile-generation-manifest-file))
|
||||
|
||||
(defun guix-generation-list-diff-manifests ()
|
||||
"Run Diff on manifests of the 2 marked generations."
|
||||
(interactive)
|
||||
(guix-generation-list-compare
|
||||
#'guix-diff
|
||||
#'guix-profile-generation-manifest-file))
|
||||
|
||||
(defun guix-generation-list-ediff-packages ()
|
||||
"Run Ediff on package outputs installed in the 2 marked generations."
|
||||
(interactive)
|
||||
(guix-generation-list-compare
|
||||
#'ediff-buffers
|
||||
#'guix-profile-generation-packages-buffer))
|
||||
|
||||
(defun guix-generation-list-diff-packages ()
|
||||
"Run Diff on package outputs installed in the 2 marked generations."
|
||||
(interactive)
|
||||
(guix-generation-list-compare
|
||||
#'guix-diff
|
||||
#'guix-profile-generation-packages-buffer))
|
||||
|
||||
(defun guix-generation-list-ediff (arg)
|
||||
"Run Ediff on package outputs installed in the 2 marked generations.
|
||||
With ARG, run Ediff on manifests of the marked generations."
|
||||
(interactive "P")
|
||||
(if arg
|
||||
(guix-generation-list-ediff-manifests)
|
||||
(guix-generation-list-ediff-packages)))
|
||||
|
||||
(defun guix-generation-list-diff (arg)
|
||||
"Run Diff on package outputs installed in the 2 marked generations.
|
||||
With ARG, run Diff on manifests of the marked generations."
|
||||
(interactive "P")
|
||||
(if arg
|
||||
(guix-generation-list-diff-manifests)
|
||||
(guix-generation-list-diff-packages)))
|
||||
|
||||
(defun guix-generation-list-mark-delete (&optional arg)
|
||||
"Mark the current generation for deletion and move to the next line.
|
||||
With ARG, mark all generations for deletion."
|
||||
(interactive "P")
|
||||
(if arg
|
||||
(guix-list-mark-all 'delete)
|
||||
(guix-list--mark 'delete t)))
|
||||
|
||||
(defun guix-generation-list-execute ()
|
||||
"Delete marked generations."
|
||||
(interactive)
|
||||
(let ((marked (guix-list-get-marked-id-list 'delete)))
|
||||
(or marked
|
||||
(user-error "No generations marked for deletion"))
|
||||
(guix-delete-generations guix-profile marked (current-buffer))))
|
||||
|
||||
(provide 'guix-list)
|
||||
|
||||
;;; guix-list.el ends here
|
||||
+1009
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,208 @@
|
||||
;;; guix-messages.el --- Minibuffer messages
|
||||
|
||||
;; Copyright © 2014, 2015 Alex Kost <alezost@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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file provides `guix-result-message' function used to show a
|
||||
;; minibuffer message after displaying packages/generations in a
|
||||
;; list/info buffer.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'cl-lib)
|
||||
(require 'guix-utils)
|
||||
|
||||
(defvar guix-messages
|
||||
`((package
|
||||
(id
|
||||
(0 "Packages not found.")
|
||||
(1 "")
|
||||
(many "%d packages." count))
|
||||
(name
|
||||
,(lambda (_ entries names)
|
||||
(guix-message-packages-by-name entries 'package names)))
|
||||
(regexp
|
||||
(0 "No packages matching '%s'." val)
|
||||
(1 "A single package matching '%s'." val)
|
||||
(many "%d packages matching '%s'." count val))
|
||||
(all-available
|
||||
(0 "No packages are available for some reason.")
|
||||
(1 "A single available package (that's strange).")
|
||||
(many "%d available packages." count))
|
||||
(newest-available
|
||||
(0 "No packages are available for some reason.")
|
||||
(1 "A single newest available package (that's strange).")
|
||||
(many "%d newest available packages." count))
|
||||
(installed
|
||||
(0 "No packages installed in profile '%s'." profile)
|
||||
(1 "A single package installed in profile '%s'." profile)
|
||||
(many "%d packages installed in profile '%s'." count profile))
|
||||
(obsolete
|
||||
(0 "No obsolete packages in profile '%s'." profile)
|
||||
(1 "A single obsolete package in profile '%s'." profile)
|
||||
(many "%d obsolete packages in profile '%s'." count profile))
|
||||
(generation
|
||||
(0 "No packages installed in generation %d of profile '%s'."
|
||||
val profile)
|
||||
(1 "A single package installed in generation %d of profile '%s'."
|
||||
val profile)
|
||||
(many "%d packages installed in generation %d of profile '%s'."
|
||||
count val profile)))
|
||||
|
||||
(output
|
||||
(id
|
||||
(0 "Package outputs not found.")
|
||||
(1 "")
|
||||
(many "%d package outputs." count))
|
||||
(name
|
||||
,(lambda (_ entries names)
|
||||
(guix-message-packages-by-name entries 'output names)))
|
||||
(regexp
|
||||
(0 "No package outputs matching '%s'." val)
|
||||
(1 "A single package output matching '%s'." val)
|
||||
(many "%d package outputs matching '%s'." count val))
|
||||
(all-available
|
||||
(0 "No package outputs are available for some reason.")
|
||||
(1 "A single available package output (that's strange).")
|
||||
(many "%d available package outputs." count))
|
||||
(newest-available
|
||||
(0 "No package outputs are available for some reason.")
|
||||
(1 "A single newest available package output (that's strange).")
|
||||
(many "%d newest available package outputs." count))
|
||||
(installed
|
||||
(0 "No package outputs installed in profile '%s'." profile)
|
||||
(1 "A single package output installed in profile '%s'." profile)
|
||||
(many "%d package outputs installed in profile '%s'." count profile))
|
||||
(obsolete
|
||||
(0 "No obsolete package outputs in profile '%s'." profile)
|
||||
(1 "A single obsolete package output in profile '%s'." profile)
|
||||
(many "%d obsolete package outputs in profile '%s'." count profile))
|
||||
(generation
|
||||
(0 "No package outputs installed in generation %d of profile '%s'."
|
||||
val profile)
|
||||
(1 "A single package output installed in generation %d of profile '%s'."
|
||||
val profile)
|
||||
(many "%d package outputs installed in generation %d of profile '%s'."
|
||||
count val profile))
|
||||
(generation-diff
|
||||
guix-message-outputs-by-diff))
|
||||
|
||||
(generation
|
||||
(id
|
||||
(0 "Generations not found.")
|
||||
(1 "")
|
||||
(many "%d generations." count))
|
||||
(last
|
||||
(0 "No generations in profile '%s'." profile)
|
||||
(1 "The last generation of profile '%s'." profile)
|
||||
(many "%d last generations of profile '%s'." count profile))
|
||||
(all
|
||||
(0 "No generations in profile '%s'." profile)
|
||||
(1 "A single generation available in profile '%s'." profile)
|
||||
(many "%d generations available in profile '%s'." count profile))
|
||||
(time
|
||||
guix-message-generations-by-time))))
|
||||
|
||||
(defun guix-message-string-name (name)
|
||||
"Return a quoted name string."
|
||||
(concat "'" name "'"))
|
||||
|
||||
(defun guix-message-string-entry-type (entry-type &optional plural)
|
||||
"Return a string denoting an ENTRY-TYPE."
|
||||
(cl-ecase entry-type
|
||||
(package
|
||||
(if plural "packages" "package"))
|
||||
(output
|
||||
(if plural "package outputs" "package output"))
|
||||
(generation
|
||||
(if plural "generations" "generation"))))
|
||||
|
||||
(defun guix-message-string-entries (count entry-type)
|
||||
"Return a string denoting the COUNT of ENTRY-TYPE entries."
|
||||
(cl-case count
|
||||
(0 (concat "No "
|
||||
(guix-message-string-entry-type
|
||||
entry-type 'plural)))
|
||||
(1 (concat "A single "
|
||||
(guix-message-string-entry-type
|
||||
entry-type)))
|
||||
(t (format "%d %s"
|
||||
count
|
||||
(guix-message-string-entry-type
|
||||
entry-type 'plural)))))
|
||||
|
||||
(defun guix-message-packages-by-name (entries entry-type names)
|
||||
"Display a message for packages or outputs searched by NAMES."
|
||||
(let* ((count (length entries))
|
||||
(str-beg (guix-message-string-entries count entry-type))
|
||||
(str-end (if (cdr names)
|
||||
(concat "matching the following names: "
|
||||
(mapconcat #'guix-message-string-name
|
||||
names ", "))
|
||||
(concat "with name "
|
||||
(guix-message-string-name (car names))))))
|
||||
(message "%s %s." str-beg str-end)))
|
||||
|
||||
(defun guix-message-generations-by-time (profile entries times)
|
||||
"Display a message for generations searched by TIMES."
|
||||
(let* ((count (length entries))
|
||||
(str-beg (guix-message-string-entries count 'generation))
|
||||
(time-beg (guix-get-time-string (car times)))
|
||||
(time-end (guix-get-time-string (cadr times))))
|
||||
(message (concat "%s of profile '%s'\n"
|
||||
"matching time period '%s' - '%s'.")
|
||||
str-beg profile time-beg time-end)))
|
||||
|
||||
(defun guix-message-outputs-by-diff (profile entries generations)
|
||||
"Display a message for outputs searched by GENERATIONS difference."
|
||||
(let* ((count (length entries))
|
||||
(str-beg (guix-message-string-entries count 'output))
|
||||
(gen1 (car generations))
|
||||
(gen2 (cadr generations)))
|
||||
(cl-multiple-value-bind (new old str-action)
|
||||
(if (> gen1 gen2)
|
||||
(list gen1 gen2 "added to")
|
||||
(list gen2 gen1 "removed from"))
|
||||
(message (concat "%s %s generation %d comparing with "
|
||||
"generation %d of profile '%s'.")
|
||||
str-beg str-action new old profile))))
|
||||
|
||||
(defun guix-result-message (profile entries entry-type
|
||||
search-type search-vals)
|
||||
"Display an appropriate message after displaying ENTRIES."
|
||||
(let* ((type-spec (guix-assq-value guix-messages
|
||||
entry-type search-type))
|
||||
(fun-or-count-spec (car type-spec)))
|
||||
(if (functionp fun-or-count-spec)
|
||||
(funcall fun-or-count-spec profile entries search-vals)
|
||||
(let* ((count (length entries))
|
||||
(count-key (if (> count 1) 'many count))
|
||||
(msg-spec (guix-assq-value type-spec count-key))
|
||||
(msg (car msg-spec))
|
||||
(args (cdr msg-spec)))
|
||||
(mapc (lambda (subst)
|
||||
(setq args (cl-substitute (cdr subst) (car subst) args)))
|
||||
`((count . ,count)
|
||||
(val . ,(car search-vals))
|
||||
(profile . ,profile)))
|
||||
(apply #'message msg args)))))
|
||||
|
||||
(provide 'guix-messages)
|
||||
|
||||
;;; guix-messages.el ends here
|
||||
@@ -0,0 +1,356 @@
|
||||
;;; guix-pcomplete.el --- Functions for completing guix commands -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright © 2015 Alex Kost <alezost@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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file provides completions for "guix" command that may be used in
|
||||
;; `shell', `eshell' and wherever `pcomplete' works.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'pcomplete)
|
||||
(require 'pcmpl-unix)
|
||||
(require 'cl-lib)
|
||||
(require 'guix-utils)
|
||||
(require 'guix-help-vars)
|
||||
|
||||
|
||||
;;; Interacting with guix
|
||||
|
||||
(defcustom guix-pcomplete-guix-program (executable-find "guix")
|
||||
"Name of the 'guix' program.
|
||||
It is used to find guix commands, options, packages, etc."
|
||||
:type 'file
|
||||
:group 'pcomplete
|
||||
:group 'guix)
|
||||
|
||||
(defun guix-pcomplete-run-guix (&rest args)
|
||||
"Run `guix-pcomplete-guix-program' with ARGS.
|
||||
Insert the output to the current buffer."
|
||||
(apply #'call-process
|
||||
guix-pcomplete-guix-program nil t nil args))
|
||||
|
||||
(defun guix-pcomplete-run-guix-and-search (regexp &optional group
|
||||
&rest args)
|
||||
"Run `guix-pcomplete-guix-program' with ARGS and search for matches.
|
||||
Return a list of strings matching REGEXP.
|
||||
GROUP specifies a parenthesized expression used in REGEXP."
|
||||
(with-temp-buffer
|
||||
(apply #'guix-pcomplete-run-guix args)
|
||||
(let (result)
|
||||
(guix-while-search regexp
|
||||
(push (match-string-no-properties group) result))
|
||||
(nreverse result))))
|
||||
|
||||
(defmacro guix-pcomplete-define-options-finder (name docstring regexp
|
||||
&optional filter)
|
||||
"Define function NAME to receive guix options and commands.
|
||||
|
||||
The defined function takes an optional COMMAND argument. This
|
||||
function will run 'guix COMMAND --help' (or 'guix --help' if
|
||||
COMMAND is nil) using `guix-pcomplete-run-guix-and-search' and
|
||||
return its result.
|
||||
|
||||
If FILTER is specified, it should be a function. The result is
|
||||
passed to this FILTER as argument and the result value of this
|
||||
function call is returned."
|
||||
(declare (doc-string 2) (indent 1))
|
||||
`(guix-memoized-defun ,name (&optional command)
|
||||
,docstring
|
||||
(let* ((args '("--help"))
|
||||
(args (if command (cons command args) args))
|
||||
(res (apply #'guix-pcomplete-run-guix-and-search
|
||||
,regexp guix-help-parse-regexp-group args)))
|
||||
,(if filter
|
||||
`(funcall ,filter res)
|
||||
'res))))
|
||||
|
||||
(guix-pcomplete-define-options-finder guix-pcomplete-commands
|
||||
"If COMMAND is nil, return a list of available guix commands.
|
||||
If COMMAND is non-nil (it should be a string), return available
|
||||
subcommands, actions, etc. for this guix COMMAND."
|
||||
guix-help-parse-command-regexp)
|
||||
|
||||
(guix-pcomplete-define-options-finder guix-pcomplete-long-options
|
||||
"Return a list of available long options for guix COMMAND."
|
||||
guix-help-parse-long-option-regexp)
|
||||
|
||||
(guix-pcomplete-define-options-finder guix-pcomplete-short-options
|
||||
"Return a string with available short options for guix COMMAND."
|
||||
guix-help-parse-short-option-regexp
|
||||
(lambda (list)
|
||||
(guix-concat-strings list "")))
|
||||
|
||||
(guix-memoized-defun guix-pcomplete-all-packages ()
|
||||
"Return a list of all available Guix packages."
|
||||
(guix-pcomplete-run-guix-and-search
|
||||
guix-help-parse-package-regexp
|
||||
guix-help-parse-regexp-group
|
||||
"package" "--list-available"))
|
||||
|
||||
(guix-memoized-defun guix-pcomplete-installed-packages (&optional profile)
|
||||
"Return a list of Guix packages installed in PROFILE."
|
||||
(let* ((args (and profile
|
||||
(list (concat "--profile=" profile))))
|
||||
(args (append '("package" "--list-installed") args)))
|
||||
(apply #'guix-pcomplete-run-guix-and-search
|
||||
guix-help-parse-package-regexp
|
||||
guix-help-parse-regexp-group
|
||||
args)))
|
||||
|
||||
(guix-memoized-defun guix-pcomplete-lint-checkers ()
|
||||
"Return a list of all available lint checkers."
|
||||
(guix-pcomplete-run-guix-and-search
|
||||
guix-help-parse-list-regexp
|
||||
guix-help-parse-regexp-group
|
||||
"lint" "--list-checkers"))
|
||||
|
||||
(guix-memoized-defun guix-pcomplete-graph-types ()
|
||||
"Return a list of all available graph types."
|
||||
(guix-pcomplete-run-guix-and-search
|
||||
guix-help-parse-list-regexp
|
||||
guix-help-parse-regexp-group
|
||||
"graph" "--list-types"))
|
||||
|
||||
|
||||
;;; Completing
|
||||
|
||||
(defvar guix-pcomplete-option-regexp (rx string-start "-")
|
||||
"Regexp to match an option.")
|
||||
|
||||
(defvar guix-pcomplete-long-option-regexp (rx string-start "--")
|
||||
"Regexp to match a long option.")
|
||||
|
||||
(defvar guix-pcomplete-long-option-with-arg-regexp
|
||||
(rx string-start
|
||||
(group "--" (one-or-more any)) "="
|
||||
(group (zero-or-more any)))
|
||||
"Regexp to match a long option with its argument.
|
||||
The first parenthesized group defines the option and the second
|
||||
group - the argument.")
|
||||
|
||||
(defvar guix-pcomplete-short-option-with-arg-regexp
|
||||
(rx string-start
|
||||
(group "-" (not (any "-")))
|
||||
(group (zero-or-more any)))
|
||||
"Regexp to match a short option with its argument.
|
||||
The first parenthesized group defines the option and the second
|
||||
group - the argument.")
|
||||
|
||||
(defun guix-pcomplete-match-option ()
|
||||
"Return non-nil, if the current argument is an option."
|
||||
(pcomplete-match guix-pcomplete-option-regexp 0))
|
||||
|
||||
(defun guix-pcomplete-match-long-option ()
|
||||
"Return non-nil, if the current argument is a long option."
|
||||
(pcomplete-match guix-pcomplete-long-option-regexp 0))
|
||||
|
||||
(defun guix-pcomplete-match-long-option-with-arg ()
|
||||
"Return non-nil, if the current argument is a long option with value."
|
||||
(pcomplete-match guix-pcomplete-long-option-with-arg-regexp 0))
|
||||
|
||||
(defun guix-pcomplete-match-short-option-with-arg ()
|
||||
"Return non-nil, if the current argument is a short option with value."
|
||||
(pcomplete-match guix-pcomplete-short-option-with-arg-regexp 0))
|
||||
|
||||
(defun guix-pcomplete-long-option-arg (option args)
|
||||
"Return a long OPTION's argument from a list of arguments ARGS."
|
||||
(let* ((re (concat "\\`" option "=\\(.*\\)"))
|
||||
(args (cl-member-if (lambda (arg)
|
||||
(string-match re arg))
|
||||
args))
|
||||
(cur (car args)))
|
||||
(when cur
|
||||
(match-string-no-properties 1 cur))))
|
||||
|
||||
(defun guix-pcomplete-short-option-arg (option args)
|
||||
"Return a short OPTION's argument from a list of arguments ARGS."
|
||||
(let* ((re (concat "\\`" option "\\(.*\\)"))
|
||||
(args (cl-member-if (lambda (arg)
|
||||
(string-match re arg))
|
||||
args))
|
||||
(cur (car args)))
|
||||
(when cur
|
||||
(let ((arg (match-string-no-properties 1 cur)))
|
||||
(if (string= "" arg)
|
||||
(cadr args) ; take the next arg
|
||||
arg)))))
|
||||
|
||||
(defun guix-pcomplete-complete-comma-args (entries)
|
||||
"Complete comma separated arguments using ENTRIES."
|
||||
(let ((index pcomplete-index))
|
||||
(while (= index pcomplete-index)
|
||||
(let* ((args (if (or (guix-pcomplete-match-long-option-with-arg)
|
||||
(guix-pcomplete-match-short-option-with-arg))
|
||||
(pcomplete-match-string 2 0)
|
||||
(pcomplete-arg 0)))
|
||||
(input (if (string-match ".*,\\(.*\\)" args)
|
||||
(match-string-no-properties 1 args)
|
||||
args)))
|
||||
(pcomplete-here* entries input)))))
|
||||
|
||||
(defun guix-pcomplete-complete-command-arg (command)
|
||||
"Complete argument for guix COMMAND."
|
||||
(cond
|
||||
((member command
|
||||
'("archive" "build" "graph" "edit" "environment"
|
||||
"lint" "refresh" "size"))
|
||||
(while t
|
||||
(pcomplete-here (guix-pcomplete-all-packages))))
|
||||
(t (pcomplete-here* (pcomplete-entries)))))
|
||||
|
||||
(defun guix-pcomplete-complete-option-arg (command option &optional input)
|
||||
"Complete argument for COMMAND's OPTION.
|
||||
INPUT is the current partially completed string."
|
||||
(cl-flet ((option? (short long)
|
||||
(or (string= option short)
|
||||
(string= option long)))
|
||||
(command? (&rest commands)
|
||||
(member command commands))
|
||||
(complete (entries)
|
||||
(pcomplete-here entries input nil t))
|
||||
(complete* (entries)
|
||||
(pcomplete-here* entries input t)))
|
||||
(cond
|
||||
((option? "-L" "--load-path")
|
||||
(complete* (pcomplete-dirs)))
|
||||
((string= "--key-download" option)
|
||||
(complete* guix-help-key-policies))
|
||||
|
||||
((command? "package")
|
||||
(cond
|
||||
;; For '--install[=]' and '--remove[=]', try to complete a package
|
||||
;; name (INPUT) after the "=" sign, and then the rest packages
|
||||
;; separated with spaces.
|
||||
((option? "-i" "--install")
|
||||
(complete (guix-pcomplete-all-packages))
|
||||
(while (not (guix-pcomplete-match-option))
|
||||
(pcomplete-here (guix-pcomplete-all-packages))))
|
||||
((option? "-r" "--remove")
|
||||
(let* ((profile (or (guix-pcomplete-short-option-arg
|
||||
"-p" pcomplete-args)
|
||||
(guix-pcomplete-long-option-arg
|
||||
"--profile" pcomplete-args)))
|
||||
(profile (and profile (expand-file-name profile))))
|
||||
(complete (guix-pcomplete-installed-packages profile))
|
||||
(while (not (guix-pcomplete-match-option))
|
||||
(pcomplete-here (guix-pcomplete-installed-packages profile)))))
|
||||
((string= "--show" option)
|
||||
(complete (guix-pcomplete-all-packages)))
|
||||
((option? "-p" "--profile")
|
||||
(complete* (pcomplete-dirs)))
|
||||
((option? "-m" "--manifest")
|
||||
(complete* (pcomplete-entries)))))
|
||||
|
||||
((and (command? "archive" "build" "size")
|
||||
(option? "-s" "--system"))
|
||||
(complete* guix-help-system-types))
|
||||
|
||||
((and (command? "build")
|
||||
(option? "-r" "--root"))
|
||||
(complete* (pcomplete-entries)))
|
||||
|
||||
((and (command? "graph")
|
||||
(option? "-t" "--type"))
|
||||
(complete* (guix-pcomplete-graph-types)))
|
||||
|
||||
((and (command? "environment")
|
||||
(option? "-l" "--load"))
|
||||
(complete* (pcomplete-entries)))
|
||||
|
||||
((and (command? "hash" "download")
|
||||
(option? "-f" "--format"))
|
||||
(complete* guix-help-hash-formats))
|
||||
|
||||
((and (command? "lint")
|
||||
(option? "-c" "--checkers"))
|
||||
(guix-pcomplete-complete-comma-args
|
||||
(guix-pcomplete-lint-checkers)))
|
||||
|
||||
((and (command? "publish")
|
||||
(option? "-u" "--user"))
|
||||
(complete* (pcmpl-unix-user-names)))
|
||||
|
||||
((and (command? "refresh")
|
||||
(option? "-s" "--select"))
|
||||
(complete* guix-help-refresh-subsets))
|
||||
|
||||
((and (command? "size")
|
||||
(option? "-m" "--map-file"))
|
||||
(complete* (pcomplete-entries))))))
|
||||
|
||||
(defun guix-pcomplete-complete-options (command)
|
||||
"Complete options (with their arguments) for guix COMMAND."
|
||||
(while (guix-pcomplete-match-option)
|
||||
(let ((index pcomplete-index))
|
||||
(if (guix-pcomplete-match-long-option)
|
||||
|
||||
;; Long options.
|
||||
(if (guix-pcomplete-match-long-option-with-arg)
|
||||
(let ((option (pcomplete-match-string 1 0))
|
||||
(arg (pcomplete-match-string 2 0)))
|
||||
(guix-pcomplete-complete-option-arg
|
||||
command option arg))
|
||||
|
||||
(pcomplete-here* (guix-pcomplete-long-options command))
|
||||
;; We support '--opt arg' style (along with '--opt=arg'),
|
||||
;; because 'guix package --install/--remove' may be used this
|
||||
;; way. So try to complete an argument after the option has
|
||||
;; been completed.
|
||||
(unless (guix-pcomplete-match-option)
|
||||
(guix-pcomplete-complete-option-arg
|
||||
command (pcomplete-arg 0 -1))))
|
||||
|
||||
;; Short options.
|
||||
(let ((arg (pcomplete-arg 0)))
|
||||
(if (> (length arg) 2)
|
||||
;; Support specifying an argument after a short option without
|
||||
;; spaces (for example, '-L/tmp/foo').
|
||||
(guix-pcomplete-complete-option-arg
|
||||
command
|
||||
(substring-no-properties arg 0 2)
|
||||
(substring-no-properties arg 2))
|
||||
(pcomplete-opt (guix-pcomplete-short-options command))
|
||||
(guix-pcomplete-complete-option-arg
|
||||
command (pcomplete-arg 0 -1)))))
|
||||
|
||||
;; If there were no completions, move to the next argument and get
|
||||
;; out if the last argument is achieved.
|
||||
(when (= index pcomplete-index)
|
||||
(if (= pcomplete-index pcomplete-last)
|
||||
(throw 'pcompleted nil)
|
||||
(pcomplete-next-arg))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun pcomplete/guix ()
|
||||
"Completion for `guix'."
|
||||
(let ((commands (guix-pcomplete-commands)))
|
||||
(pcomplete-here* (cons "--help" commands))
|
||||
(let ((command (pcomplete-arg 'first 1)))
|
||||
(when (member command commands)
|
||||
(guix-pcomplete-complete-options command)
|
||||
(let ((subcommands (guix-pcomplete-commands command)))
|
||||
(when subcommands
|
||||
(pcomplete-here* subcommands)))
|
||||
(guix-pcomplete-complete-options command)
|
||||
(guix-pcomplete-complete-command-arg command)))))
|
||||
|
||||
(provide 'guix-pcomplete)
|
||||
|
||||
;;; guix-pcomplete.el ends here
|
||||
@@ -0,0 +1,48 @@
|
||||
;;; guix-popup.el --- Popup windows library
|
||||
|
||||
;; Copyright © 2015 Alex Kost <alezost@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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file provides `guix-define-popup' macro which is just an alias
|
||||
;; to `magit-define-popup'. According to the manual (info
|
||||
;; "(magit-popup) Defining prefix and suffix commands") `magit-popup'
|
||||
;; library will eventually be superseded by a more general library.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'magit-popup)
|
||||
|
||||
(defalias 'guix-define-popup 'magit-define-popup)
|
||||
|
||||
(defvar guix-popup-font-lock-keywords
|
||||
(eval-when-compile
|
||||
`((,(rx "("
|
||||
(group "guix-define-popup")
|
||||
symbol-end
|
||||
(zero-or-more blank)
|
||||
(zero-or-one
|
||||
(group (one-or-more (or (syntax word) (syntax symbol))))))
|
||||
(1 font-lock-keyword-face)
|
||||
(2 font-lock-function-name-face nil t)))))
|
||||
|
||||
(font-lock-add-keywords 'emacs-lisp-mode guix-popup-font-lock-keywords)
|
||||
|
||||
(provide 'guix-popup)
|
||||
|
||||
;;; guix-popup.el ends here
|
||||
@@ -0,0 +1,210 @@
|
||||
;;; guix-prettify.el --- Prettify Guix store file names
|
||||
|
||||
;; Copyright © 2014, 2015 Alex Kost <alezost@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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This package provides minor-mode for prettifying Guix store file
|
||||
;; names — i.e., after enabling `guix-prettify-mode',
|
||||
;; '/gnu/store/72f54nfp6g1hz873w8z3gfcah0h4nl9p-foo-0.1' names will be
|
||||
;; replaced with '/gnu/store/…-foo-0.1' in the current buffer. There is
|
||||
;; also `global-guix-prettify-mode' for global prettifying.
|
||||
|
||||
;; To install, add the following to your emacs init file:
|
||||
;;
|
||||
;; (add-to-list 'load-path "/path/to/dir-with-guix-prettify")
|
||||
;; (autoload 'guix-prettify-mode "guix-prettify" nil t)
|
||||
;; (autoload 'global-guix-prettify-mode "guix-prettify" nil t)
|
||||
|
||||
;; If you want to enable/disable composition after "M-x font-lock-mode",
|
||||
;; use the following setting:
|
||||
;;
|
||||
;; (setq font-lock-extra-managed-props
|
||||
;; (cons 'composition font-lock-extra-managed-props))
|
||||
|
||||
;; Credits:
|
||||
;;
|
||||
;; Thanks to Ludovic Courtès for the idea of this package.
|
||||
;;
|
||||
;; Thanks to the authors of `prettify-symbols-mode' (part of Emacs 24.4)
|
||||
;; and "pretty-symbols.el" <http://github.com/drothlis/pretty-symbols>
|
||||
;; for the code. It helped to write this package.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'guix-utils)
|
||||
|
||||
(defgroup guix-prettify nil
|
||||
"Prettify Guix store file names."
|
||||
:prefix "guix-prettify-"
|
||||
:group 'guix
|
||||
:group 'font-lock
|
||||
:group 'convenience)
|
||||
|
||||
(defcustom guix-prettify-char ?…
|
||||
"Character used for prettifying."
|
||||
:type 'character
|
||||
:group 'guix-prettify)
|
||||
|
||||
(defcustom guix-prettify-decompose-force nil
|
||||
"If non-nil, remove any composition.
|
||||
|
||||
By default, after disabling `guix-prettify-mode',
|
||||
compositions (prettifying names with `guix-prettify-char') are
|
||||
removed only from strings matching `guix-prettify-regexp', so
|
||||
that compositions created by other modes are left untouched.
|
||||
|
||||
Set this variable to non-nil, if you want to remove any
|
||||
composition unconditionally (like `prettify-symbols-mode' does).
|
||||
Most likely it will do no harm and will make the process of
|
||||
disabling `guix-prettify-mode' a little faster."
|
||||
:type 'boolean
|
||||
:group 'guix-prettify)
|
||||
|
||||
(defcustom guix-prettify-regexp
|
||||
;; The following file names / URLs should be abbreviated:
|
||||
|
||||
;; /gnu/store/…-foo-0.1
|
||||
;; /nix/store/…-foo-0.1
|
||||
;; http://hydra.gnu.org/nar/…-foo-0.1
|
||||
;; http://hydra.gnu.org/log/…-foo-0.1
|
||||
|
||||
(rx "/" (or "store" "nar" "log") "/"
|
||||
;; Hash-parts do not include "e", "o", "u" and "t". See base32Chars
|
||||
;; at <https://github.com/NixOS/nix/blob/master/src/libutil/hash.cc>
|
||||
(group (= 32 (any "0-9" "a-d" "f-n" "p-s" "v-z"))))
|
||||
"Regexp matching file names for prettifying.
|
||||
|
||||
Disable `guix-prettify-mode' before modifying this variable and
|
||||
make sure to modify `guix-prettify-regexp-group' if needed.
|
||||
|
||||
Example of a \"deeper\" prettifying:
|
||||
|
||||
(setq guix-prettify-regexp \"store/[[:alnum:]]\\\\\\={32\\\\}\"
|
||||
guix-prettify-regexp-group 0)
|
||||
|
||||
This will transform
|
||||
'/gnu/store/72f54nfp6g1hz873w8z3gfcah0h4nl9p-foo-0.1' into
|
||||
'/gnu/…-foo-0.1'"
|
||||
:type 'regexp
|
||||
:group 'guix-prettify)
|
||||
|
||||
(defcustom guix-prettify-regexp-group 1
|
||||
"Regexp group in `guix-prettify-regexp' for prettifying."
|
||||
:type 'integer
|
||||
:group 'guix-prettify)
|
||||
|
||||
(defvar guix-prettify-special-modes
|
||||
'(guix-info-mode ibuffer-mode)
|
||||
"List of special modes that support font-locking.
|
||||
|
||||
By default, \\[global-guix-prettify-mode] enables prettifying in
|
||||
all buffers except the ones where `font-lock-defaults' is
|
||||
nil (see Info node `(elisp) Font Lock Basics'), because it may
|
||||
break the existing highlighting.
|
||||
|
||||
Modes from this list and all derived modes are exceptions
|
||||
\(`global-guix-prettify-mode' enables prettifying there).")
|
||||
|
||||
(defvar guix-prettify-flush-function
|
||||
(cond ((fboundp 'font-lock-flush) #'font-lock-flush)
|
||||
((fboundp 'jit-lock-refontify) #'jit-lock-refontify))
|
||||
"Function used to refontify buffer.
|
||||
This function is called without arguments after
|
||||
enabling/disabling `guix-prettify-mode'. If nil, do nothing.")
|
||||
|
||||
(defun guix-prettify-compose ()
|
||||
"Compose matching region in the current buffer."
|
||||
(let ((beg (match-beginning guix-prettify-regexp-group))
|
||||
(end (match-end guix-prettify-regexp-group)))
|
||||
(compose-region beg end guix-prettify-char 'decompose-region))
|
||||
;; Return nil because we're not adding any face property.
|
||||
nil)
|
||||
|
||||
(defun guix-prettify-decompose-buffer ()
|
||||
"Remove file names compositions from the current buffer."
|
||||
(with-silent-modifications
|
||||
(let ((inhibit-read-only t))
|
||||
(if guix-prettify-decompose-force
|
||||
(remove-text-properties (point-min)
|
||||
(point-max)
|
||||
'(composition nil))
|
||||
(guix-while-search guix-prettify-regexp
|
||||
(remove-text-properties
|
||||
(match-beginning guix-prettify-regexp-group)
|
||||
(match-end guix-prettify-regexp-group)
|
||||
'(composition nil)))))))
|
||||
|
||||
;;;###autoload
|
||||
(define-minor-mode guix-prettify-mode
|
||||
"Toggle Guix Prettify mode.
|
||||
|
||||
With a prefix argument ARG, enable Guix Prettify mode if ARG is
|
||||
positive, and disable it otherwise. If called from Lisp, enable
|
||||
the mode if ARG is omitted or nil.
|
||||
|
||||
When Guix Prettify mode is enabled, hash-parts of the Guix store
|
||||
file names (see `guix-prettify-regexp') are prettified,
|
||||
i.e. displayed as `guix-prettify-char' character. This mode can
|
||||
be enabled programmatically using hooks:
|
||||
|
||||
(add-hook 'shell-mode-hook 'guix-prettify-mode)
|
||||
|
||||
It is possible to enable the mode in any buffer, however not any
|
||||
buffer's highlighting may survive after adding new elements to
|
||||
`font-lock-keywords' (see `guix-prettify-special-modes' for
|
||||
details).
|
||||
|
||||
Also you can use `global-guix-prettify-mode' to enable Guix
|
||||
Prettify mode for all modes that support font-locking."
|
||||
:init-value nil
|
||||
:lighter " …"
|
||||
(let ((keywords `((,guix-prettify-regexp
|
||||
(,guix-prettify-regexp-group
|
||||
(guix-prettify-compose))))))
|
||||
(if guix-prettify-mode
|
||||
;; Turn on.
|
||||
(font-lock-add-keywords nil keywords)
|
||||
;; Turn off.
|
||||
(font-lock-remove-keywords nil keywords)
|
||||
(guix-prettify-decompose-buffer))
|
||||
(and guix-prettify-flush-function
|
||||
(funcall guix-prettify-flush-function))))
|
||||
|
||||
(defun guix-prettify-supported-p ()
|
||||
"Return non-nil, if the mode can be harmlessly enabled in current buffer."
|
||||
(or font-lock-defaults
|
||||
(apply #'derived-mode-p guix-prettify-special-modes)))
|
||||
|
||||
(defun guix-prettify-turn-on ()
|
||||
"Enable `guix-prettify-mode' in the current buffer if needed.
|
||||
See `guix-prettify-special-modes' for details."
|
||||
(and (not guix-prettify-mode)
|
||||
(guix-prettify-supported-p)
|
||||
(guix-prettify-mode)))
|
||||
|
||||
;;;###autoload
|
||||
(define-globalized-minor-mode global-guix-prettify-mode
|
||||
guix-prettify-mode guix-prettify-turn-on)
|
||||
|
||||
;;;###autoload
|
||||
(defalias 'guix-prettify-global-mode 'global-guix-prettify-mode)
|
||||
|
||||
(provide 'guix-prettify)
|
||||
|
||||
;;; guix-prettify.el ends here
|
||||
@@ -0,0 +1,64 @@
|
||||
;;; guix-profiles.el --- Guix profiles
|
||||
|
||||
;; Copyright © 2014 Alex Kost <alezost@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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'guix-config)
|
||||
|
||||
(defvar guix-user-profile
|
||||
(expand-file-name "~/.guix-profile")
|
||||
"User profile.")
|
||||
|
||||
(defvar guix-default-profile
|
||||
(concat guix-config-state-directory
|
||||
"/profiles/per-user/"
|
||||
(getenv "USER")
|
||||
"/guix-profile")
|
||||
"Default Guix profile.")
|
||||
|
||||
(defvar guix-current-profile guix-default-profile
|
||||
"Current profile.")
|
||||
|
||||
(defun guix-profile-prompt (&optional default)
|
||||
"Prompt for profile and return it.
|
||||
Use DEFAULT as a start directory. If it is nil, use
|
||||
`guix-current-profile'."
|
||||
(let* ((path (read-file-name "Profile: "
|
||||
(file-name-directory
|
||||
(or default guix-current-profile))))
|
||||
(path (directory-file-name (expand-file-name path))))
|
||||
(if (string= path guix-user-profile)
|
||||
guix-default-profile
|
||||
path)))
|
||||
|
||||
(defun guix-set-current-profile (path)
|
||||
"Set `guix-current-profile' to PATH.
|
||||
Interactively, prompt for PATH. With prefix, use
|
||||
`guix-default-profile'."
|
||||
(interactive
|
||||
(list (if current-prefix-arg
|
||||
guix-default-profile
|
||||
(guix-profile-prompt))))
|
||||
(setq guix-current-profile path)
|
||||
(message "Current profile has been set to '%s'."
|
||||
guix-current-profile))
|
||||
|
||||
(provide 'guix-profiles)
|
||||
|
||||
;;; guix-profiles.el ends here
|
||||
@@ -0,0 +1,176 @@
|
||||
;;; guix-read.el --- Minibuffer readers
|
||||
|
||||
;; Copyright © 2015 Alex Kost <alezost@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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file provides functions to prompt a user for packages, system
|
||||
;; types, hash formats and other guix related stuff.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'guix-help-vars)
|
||||
(require 'guix-utils)
|
||||
(require 'guix-base)
|
||||
|
||||
(defun guix-read-file-name (prompt &optional dir default-filename
|
||||
mustmatch initial predicate)
|
||||
"Read file name.
|
||||
This function is similar to `read-file-name' except it also
|
||||
expands the file name."
|
||||
(expand-file-name (read-file-name prompt dir default-filename
|
||||
mustmatch initial predicate)))
|
||||
|
||||
(defmacro guix-define-reader (name read-fun completions prompt)
|
||||
"Define NAME function to read from minibuffer.
|
||||
READ-FUN may be `completing-read', `completing-read-multiple' or
|
||||
another function with the same arguments."
|
||||
`(defun ,name (&optional prompt initial-contents)
|
||||
(,read-fun ,(if prompt
|
||||
`(or prompt ,prompt)
|
||||
'prompt)
|
||||
,completions nil nil initial-contents)))
|
||||
|
||||
(defmacro guix-define-readers (&rest args)
|
||||
"Define reader functions.
|
||||
|
||||
ARGS should have a form [KEYWORD VALUE] ... The following
|
||||
keywords are available:
|
||||
|
||||
- `completions-var' - variable used to get completions.
|
||||
|
||||
- `completions-getter' - function used to get completions.
|
||||
|
||||
- `single-reader', `single-prompt' - name of a function to read
|
||||
a single value, and a prompt for it.
|
||||
|
||||
- `multiple-reader', `multiple-prompt' - name of a function to
|
||||
read multiple values, and a prompt for it.
|
||||
|
||||
- `multiple-separator' - if specified, another
|
||||
`<multiple-reader-name>-string' function returning a string
|
||||
of multiple values separated the specified separator will be
|
||||
defined."
|
||||
(let (completions-var
|
||||
completions-getter
|
||||
single-reader
|
||||
single-prompt
|
||||
multiple-reader
|
||||
multiple-prompt
|
||||
multiple-separator)
|
||||
|
||||
;; Process the keyword args.
|
||||
(while (keywordp (car args))
|
||||
(pcase (pop args)
|
||||
(`:completions-var (setq completions-var (pop args)))
|
||||
(`:completions-getter (setq completions-getter (pop args)))
|
||||
(`:single-reader (setq single-reader (pop args)))
|
||||
(`:single-prompt (setq single-prompt (pop args)))
|
||||
(`:multiple-reader (setq multiple-reader (pop args)))
|
||||
(`:multiple-prompt (setq multiple-prompt (pop args)))
|
||||
(`:multiple-separator (setq multiple-separator (pop args)))
|
||||
(_ (pop args))))
|
||||
|
||||
(let ((completions
|
||||
(cond ((and completions-var completions-getter)
|
||||
`(or ,completions-var
|
||||
(setq ,completions-var
|
||||
(funcall ',completions-getter))))
|
||||
(completions-var
|
||||
completions-var)
|
||||
(completions-getter
|
||||
`(funcall ',completions-getter)))))
|
||||
`(progn
|
||||
,(when (and completions-var
|
||||
(not (boundp completions-var)))
|
||||
`(defvar ,completions-var nil))
|
||||
|
||||
,(when single-reader
|
||||
`(guix-define-reader ,single-reader completing-read
|
||||
,completions ,single-prompt))
|
||||
|
||||
,(when multiple-reader
|
||||
`(guix-define-reader ,multiple-reader completing-read-multiple
|
||||
,completions ,multiple-prompt))
|
||||
|
||||
,(when (and multiple-reader multiple-separator)
|
||||
(let ((name (intern (concat (symbol-name multiple-reader)
|
||||
"-string"))))
|
||||
`(defun ,name (&optional prompt initial-contents)
|
||||
(guix-concat-strings
|
||||
(,multiple-reader prompt initial-contents)
|
||||
,multiple-separator))))))))
|
||||
|
||||
(guix-define-readers
|
||||
:completions-var guix-help-system-types
|
||||
:single-reader guix-read-system-type
|
||||
:single-prompt "System type: ")
|
||||
|
||||
(guix-define-readers
|
||||
:completions-var guix-help-source-types
|
||||
:single-reader guix-read-source-type
|
||||
:single-prompt "Source type: ")
|
||||
|
||||
(guix-define-readers
|
||||
:completions-var guix-help-hash-formats
|
||||
:single-reader guix-read-hash-format
|
||||
:single-prompt "Hash format: ")
|
||||
|
||||
(guix-define-readers
|
||||
:completions-var guix-help-refresh-subsets
|
||||
:single-reader guix-read-refresh-subset
|
||||
:single-prompt "Refresh subset: ")
|
||||
|
||||
(guix-define-readers
|
||||
:completions-var guix-help-key-policies
|
||||
:single-reader guix-read-key-policy
|
||||
:single-prompt "Key policy: ")
|
||||
|
||||
(guix-define-readers
|
||||
:completions-var guix-help-elpa-archives
|
||||
:single-reader guix-read-elpa-archive
|
||||
:single-prompt "ELPA archive: ")
|
||||
|
||||
(guix-define-readers
|
||||
:completions-var guix-help-verify-options
|
||||
:multiple-reader guix-read-verify-options
|
||||
:multiple-prompt "Verify option,s: "
|
||||
:multiple-separator ",")
|
||||
|
||||
(guix-define-readers
|
||||
:completions-getter guix-graph-type-names
|
||||
:single-reader guix-read-graph-type
|
||||
:single-prompt "Graph node type: ")
|
||||
|
||||
(guix-define-readers
|
||||
:completions-getter guix-lint-checker-names
|
||||
:multiple-reader guix-read-lint-checker-names
|
||||
:multiple-prompt "Linter,s: "
|
||||
:multiple-separator ",")
|
||||
|
||||
(guix-define-readers
|
||||
:completions-getter guix-package-names
|
||||
:single-reader guix-read-package-name
|
||||
:single-prompt "Package: "
|
||||
:multiple-reader guix-read-package-names
|
||||
:multiple-prompt "Package,s: "
|
||||
:multiple-separator " ")
|
||||
|
||||
(provide 'guix-read)
|
||||
|
||||
;;; guix-read.el ends here
|
||||
@@ -0,0 +1,310 @@
|
||||
;;; guix-utils.el --- General utility functions -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright © 2014, 2015 Alex Kost <alezost@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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file provides auxiliary general functions for guix.el package.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'cl-lib)
|
||||
|
||||
(defvar guix-true-string "Yes")
|
||||
(defvar guix-false-string "–")
|
||||
(defvar guix-list-separator ", ")
|
||||
|
||||
(defvar guix-time-format "%F %T"
|
||||
"String used to format time values.
|
||||
For possible formats, see `format-time-string'.")
|
||||
|
||||
(defun guix-get-string (val &optional face)
|
||||
"Convert VAL into a string and return it.
|
||||
|
||||
VAL can be an expression of any type.
|
||||
If VAL is t/nil, it is replaced with
|
||||
`guix-true-string'/`guix-false-string'.
|
||||
If VAL is list, its elements are concatenated using
|
||||
`guix-list-separator'.
|
||||
|
||||
If FACE is non-nil, propertize returned string with this FACE."
|
||||
(let ((str (cond
|
||||
((stringp val) val)
|
||||
((null val) guix-false-string)
|
||||
((eq t val) guix-true-string)
|
||||
((numberp val) (number-to-string val))
|
||||
((listp val) (mapconcat #'guix-get-string
|
||||
val guix-list-separator))
|
||||
(t (prin1-to-string val)))))
|
||||
(if (and val face)
|
||||
(propertize str 'font-lock-face face)
|
||||
str)))
|
||||
|
||||
(defun guix-get-time-string (seconds)
|
||||
"Return formatted time string from SECONDS.
|
||||
Use `guix-time-format'."
|
||||
(format-time-string guix-time-format (seconds-to-time seconds)))
|
||||
|
||||
(defun guix-get-one-line (str)
|
||||
"Return one-line string from a multi-line STR."
|
||||
(replace-regexp-in-string "\n" " " str))
|
||||
|
||||
(defun guix-format-insert (val &optional face format)
|
||||
"Convert VAL into a string and insert it at point.
|
||||
If FACE is non-nil, propertize VAL with FACE.
|
||||
If FORMAT is non-nil, format VAL with FORMAT."
|
||||
(let ((str (guix-get-string val face)))
|
||||
(insert (if format
|
||||
(format format str)
|
||||
str))))
|
||||
|
||||
(defun guix-mapinsert (function sequence separator)
|
||||
"Like `mapconcat' but for inserting text.
|
||||
Apply FUNCTION to each element of SEQUENCE, and insert SEPARATOR
|
||||
at point between each FUNCTION call."
|
||||
(when sequence
|
||||
(funcall function (car sequence))
|
||||
(mapc (lambda (obj)
|
||||
(insert separator)
|
||||
(funcall function obj))
|
||||
(cdr sequence))))
|
||||
|
||||
(defun guix-insert-button (label &optional type &rest properties)
|
||||
"Make button of TYPE with LABEL and insert it at point.
|
||||
See `insert-text-button' for the meaning of PROPERTIES."
|
||||
(if (null label)
|
||||
(guix-format-insert nil)
|
||||
(apply #'insert-text-button label
|
||||
:type (or type 'button)
|
||||
properties)))
|
||||
|
||||
(defun guix-split-insert (val &optional face col separator)
|
||||
"Convert VAL into a string, split it and insert at point.
|
||||
|
||||
If FACE is non-nil, propertize returned string with this FACE.
|
||||
|
||||
If COL is non-nil and result string is a one-line string longer
|
||||
than COL, split it into several short lines.
|
||||
|
||||
Separate inserted lines with SEPARATOR."
|
||||
(if (null val)
|
||||
(guix-format-insert nil)
|
||||
(let ((strings (guix-split-string (guix-get-string val) col)))
|
||||
(guix-mapinsert (lambda (str) (guix-format-insert str face))
|
||||
strings
|
||||
(or separator "")))))
|
||||
|
||||
(defun guix-split-string (str &optional col)
|
||||
"Split string STR by lines and return list of result strings.
|
||||
If COL is non-nil and STR is a one-line string longer than COL,
|
||||
split it into several short lines."
|
||||
(let ((strings (split-string str "\n *")))
|
||||
(if (and col
|
||||
(null (cdr strings)) ; if not multi-line
|
||||
(> (length str) col))
|
||||
(split-string (guix-get-filled-string str col) "\n")
|
||||
strings)))
|
||||
|
||||
(defun guix-get-filled-string (str col)
|
||||
"Return string by filling STR to column COL."
|
||||
(with-temp-buffer
|
||||
(insert str)
|
||||
(let ((fill-column col))
|
||||
(fill-region (point-min) (point-max)))
|
||||
(buffer-string)))
|
||||
|
||||
(defun guix-concat-strings (strings separator &optional location)
|
||||
"Return new string by concatenating STRINGS with SEPARATOR.
|
||||
If LOCATION is a symbol `head', add another SEPARATOR to the
|
||||
beginning of the returned string; if `tail' - add SEPARATOR to
|
||||
the end of the string; if nil, do not add SEPARATOR; otherwise
|
||||
add both to the end and to the beginning."
|
||||
(let ((str (mapconcat #'identity strings separator)))
|
||||
(cond ((null location)
|
||||
str)
|
||||
((eq location 'head)
|
||||
(concat separator str))
|
||||
((eq location 'tail)
|
||||
(concat str separator))
|
||||
(t
|
||||
(concat separator str separator)))))
|
||||
|
||||
(defun guix-shell-quote-argument (argument)
|
||||
"Quote shell command ARGUMENT.
|
||||
This function is similar to `shell-quote-argument', but less strict."
|
||||
(if (equal argument "")
|
||||
"''"
|
||||
(replace-regexp-in-string
|
||||
"\n" "'\n'"
|
||||
(replace-regexp-in-string
|
||||
(rx (not (any alnum "-=,./\n"))) "\\\\\\&" argument))))
|
||||
|
||||
(defun guix-command-symbol (&optional args)
|
||||
"Return symbol by concatenating 'guix' and ARGS (strings)."
|
||||
(intern (guix-concat-strings (cons "guix" args) "-")))
|
||||
|
||||
(defun guix-command-string (&optional args)
|
||||
"Return 'guix ARGS ...' string with quoted shell arguments."
|
||||
(let ((args (mapcar #'guix-shell-quote-argument args)))
|
||||
(guix-concat-strings (cons "guix" args) " ")))
|
||||
|
||||
(defun guix-copy-as-kill (string &optional no-message?)
|
||||
"Put STRING into `kill-ring'.
|
||||
If NO-MESSAGE? is non-nil, do not display a message about it."
|
||||
(kill-new string)
|
||||
(unless no-message?
|
||||
(message "'%s' has been added to kill ring." string)))
|
||||
|
||||
(defun guix-copy-command-as-kill (args &optional no-message?)
|
||||
"Put 'guix ARGS ...' string into `kill-ring'.
|
||||
See also `guix-copy-as-kill'."
|
||||
(guix-copy-as-kill (guix-command-string args) no-message?))
|
||||
|
||||
(defun guix-completing-read-multiple (prompt table &optional predicate
|
||||
require-match initial-input
|
||||
hist def inherit-input-method)
|
||||
"Same as `completing-read-multiple' but remove duplicates in result."
|
||||
(cl-remove-duplicates
|
||||
(completing-read-multiple prompt table predicate
|
||||
require-match initial-input
|
||||
hist def inherit-input-method)
|
||||
:test #'string=))
|
||||
|
||||
(declare-function org-read-date "org" t)
|
||||
|
||||
(defun guix-read-date (prompt)
|
||||
"Prompt for a date or time using `org-read-date'.
|
||||
Return time value."
|
||||
(require 'org)
|
||||
(org-read-date nil t nil prompt))
|
||||
|
||||
(defcustom guix-find-file-function #'find-file
|
||||
"Function used to find a file.
|
||||
The function is called by `guix-find-file' with a file name as a
|
||||
single argument."
|
||||
:type '(choice (function-item find-file)
|
||||
(function-item org-open-file)
|
||||
(function :tag "Other function"))
|
||||
:group 'guix)
|
||||
|
||||
(defun guix-find-file (file)
|
||||
"Find FILE if it exists."
|
||||
(if (file-exists-p file)
|
||||
(funcall guix-find-file-function file)
|
||||
(message "File '%s' does not exist." file)))
|
||||
|
||||
(defvar url-handler-regexp)
|
||||
|
||||
(defun guix-find-file-or-url (file-or-url)
|
||||
"Find FILE-OR-URL."
|
||||
(require 'url-handlers)
|
||||
(let ((file-name-handler-alist
|
||||
(cons (cons url-handler-regexp 'url-file-handler)
|
||||
file-name-handler-alist)))
|
||||
(find-file file-or-url)))
|
||||
|
||||
(defmacro guix-while-search (regexp &rest body)
|
||||
"Evaluate BODY after each search for REGEXP in the current buffer."
|
||||
(declare (indent 1) (debug t))
|
||||
`(save-excursion
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward ,regexp nil t)
|
||||
,@body)))
|
||||
|
||||
|
||||
;;; Alist accessors
|
||||
|
||||
(defmacro guix-define-alist-accessor (name assoc-fun)
|
||||
"Define NAME function to access alist values using ASSOC-FUN."
|
||||
`(defun ,name (alist &rest keys)
|
||||
,(format "Return value from ALIST by KEYS using `%s'.
|
||||
ALIST is alist of alists of alists ... which can be consecutively
|
||||
accessed with KEYS."
|
||||
assoc-fun)
|
||||
(if (or (null alist) (null keys))
|
||||
alist
|
||||
(apply #',name
|
||||
(cdr (,assoc-fun (car keys) alist))
|
||||
(cdr keys)))))
|
||||
|
||||
(guix-define-alist-accessor guix-assq-value assq)
|
||||
(guix-define-alist-accessor guix-assoc-value assoc)
|
||||
|
||||
|
||||
;;; Diff
|
||||
|
||||
(defvar guix-diff-switches "-u"
|
||||
"A string or list of strings specifying switches to be passed to diff.")
|
||||
|
||||
(defun guix-diff (old new &optional switches no-async)
|
||||
"Same as `diff', but use `guix-diff-switches' as default."
|
||||
(diff old new (or switches guix-diff-switches) no-async))
|
||||
|
||||
|
||||
;;; Memoizing
|
||||
|
||||
(defun guix-memoize (function)
|
||||
"Return a memoized version of FUNCTION."
|
||||
(let ((cache (make-hash-table :test 'equal)))
|
||||
(lambda (&rest args)
|
||||
(let ((result (gethash args cache 'not-found)))
|
||||
(if (eq result 'not-found)
|
||||
(let ((result (apply function args)))
|
||||
(puthash args result cache)
|
||||
result)
|
||||
result)))))
|
||||
|
||||
(defmacro guix-memoized-defun (name arglist docstring &rest body)
|
||||
"Define a memoized function NAME.
|
||||
See `defun' for the meaning of arguments."
|
||||
(declare (doc-string 3) (indent 2))
|
||||
`(defalias ',name
|
||||
(guix-memoize (lambda ,arglist ,@body))
|
||||
;; Add '(name args ...)' string with real arglist to the docstring,
|
||||
;; because *Help* will display '(name &rest ARGS)' for a defined
|
||||
;; function (since `guix-memoize' returns a lambda with '(&rest
|
||||
;; args)').
|
||||
,(format "(%S %s)\n\n%s"
|
||||
name
|
||||
(mapconcat #'symbol-name arglist " ")
|
||||
docstring)))
|
||||
|
||||
(defmacro guix-memoized-defalias (symbol definition &optional docstring)
|
||||
"Set SYMBOL's function definition to memoized version of DEFINITION."
|
||||
(declare (doc-string 3) (indent 1))
|
||||
`(defalias ',symbol
|
||||
(guix-memoize #',definition)
|
||||
,(or docstring
|
||||
(format "Memoized version of `%S'." definition))))
|
||||
|
||||
(defvar guix-memoized-font-lock-keywords
|
||||
(eval-when-compile
|
||||
`((,(rx "("
|
||||
(group "guix-memoized-" (or "defun" "defalias"))
|
||||
symbol-end
|
||||
(zero-or-more blank)
|
||||
(zero-or-one
|
||||
(group (one-or-more (or (syntax word) (syntax symbol))))))
|
||||
(1 font-lock-keyword-face)
|
||||
(2 font-lock-function-name-face nil t)))))
|
||||
|
||||
(font-lock-add-keywords 'emacs-lisp-mode guix-memoized-font-lock-keywords)
|
||||
|
||||
(provide 'guix-utils)
|
||||
|
||||
;;; guix-utils.el ends here
|
||||
+213
@@ -0,0 +1,213 @@
|
||||
;;; guix.el --- Interface for GNU Guix package manager
|
||||
|
||||
;; Copyright © 2014, 2015 Alex Kost <alezost@gmail.com>
|
||||
|
||||
;; Package-Requires: ((geiser "0.3"))
|
||||
;; Keywords: tools
|
||||
|
||||
;; 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 package provides an interface for searching, listing and getting
|
||||
;; information about Guix packages and generations; and for
|
||||
;; installing/upgrading/removing packages.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'guix-base)
|
||||
(require 'guix-list)
|
||||
(require 'guix-info)
|
||||
(require 'guix-utils)
|
||||
(require 'guix-read)
|
||||
|
||||
(defgroup guix nil
|
||||
"Interface for Guix package manager."
|
||||
:prefix "guix-"
|
||||
:group 'external)
|
||||
|
||||
(defgroup guix-faces nil
|
||||
"Guix faces."
|
||||
:group 'guix
|
||||
:group 'faces)
|
||||
|
||||
(defcustom guix-list-single-package nil
|
||||
"If non-nil, list a package even if it is the only matching result.
|
||||
If nil, show a single package in the info buffer."
|
||||
:type 'boolean
|
||||
:group 'guix)
|
||||
|
||||
(defvar guix-search-params '(name synopsis description)
|
||||
"Default list of package parameters for searching by regexp.")
|
||||
|
||||
(defvar guix-search-history nil
|
||||
"A history of minibuffer prompts.")
|
||||
|
||||
(defun guix-get-show-packages (profile search-type &rest search-vals)
|
||||
"Search for packages and show results.
|
||||
|
||||
If PROFILE is nil, use `guix-current-profile'.
|
||||
|
||||
See `guix-get-entries' for the meaning of SEARCH-TYPE and
|
||||
SEARCH-VALS.
|
||||
|
||||
Results are displayed in the list buffer, unless a single package
|
||||
is found and `guix-list-single-package' is nil."
|
||||
(or profile (setq profile guix-current-profile))
|
||||
(let ((packages (guix-get-entries profile guix-package-list-type
|
||||
search-type search-vals
|
||||
(guix-get-params-for-receiving
|
||||
'list guix-package-list-type))))
|
||||
(if (or guix-list-single-package
|
||||
(cdr packages))
|
||||
(guix-set-buffer profile packages 'list guix-package-list-type
|
||||
search-type search-vals)
|
||||
(let ((packages (guix-get-entries profile guix-package-info-type
|
||||
search-type search-vals
|
||||
(guix-get-params-for-receiving
|
||||
'info guix-package-info-type))))
|
||||
(guix-set-buffer profile packages 'info guix-package-info-type
|
||||
search-type search-vals)))))
|
||||
|
||||
(defun guix-get-show-generations (profile search-type &rest search-vals)
|
||||
"Search for generations and show results.
|
||||
|
||||
If PROFILE is nil, use `guix-current-profile'.
|
||||
|
||||
See `guix-get-entries' for the meaning of SEARCH-TYPE and
|
||||
SEARCH-VALS."
|
||||
(apply #'guix-get-show-entries
|
||||
(or profile guix-current-profile)
|
||||
'list 'generation search-type search-vals))
|
||||
|
||||
;;;###autoload
|
||||
(defun guix-search-by-name (name &optional profile)
|
||||
"Search for Guix packages by NAME.
|
||||
NAME is a string with name specification. It may optionally contain
|
||||
a version number. Examples: \"guile\", \"guile-2.0.11\".
|
||||
|
||||
If PROFILE is nil, use `guix-current-profile'.
|
||||
Interactively with prefix, prompt for PROFILE."
|
||||
(interactive
|
||||
(list (read-string "Package name: " nil 'guix-search-history)
|
||||
(and current-prefix-arg
|
||||
(guix-profile-prompt))))
|
||||
(guix-get-show-packages profile 'name name))
|
||||
|
||||
;;;###autoload
|
||||
(defun guix-search-by-regexp (regexp &optional params profile)
|
||||
"Search for Guix packages by REGEXP.
|
||||
PARAMS are package parameters that should be searched.
|
||||
If PARAMS are not specified, use `guix-search-params'.
|
||||
|
||||
If PROFILE is nil, use `guix-current-profile'.
|
||||
Interactively with prefix, prompt for PROFILE."
|
||||
(interactive
|
||||
(list (read-regexp "Regexp: " nil 'guix-search-history)
|
||||
nil
|
||||
(and current-prefix-arg
|
||||
(guix-profile-prompt))))
|
||||
(guix-get-show-packages profile 'regexp regexp
|
||||
(or params guix-search-params)))
|
||||
|
||||
;;;###autoload
|
||||
(defun guix-installed-packages (&optional profile)
|
||||
"Display information about installed Guix packages.
|
||||
If PROFILE is nil, use `guix-current-profile'.
|
||||
Interactively with prefix, prompt for PROFILE."
|
||||
(interactive
|
||||
(list (and current-prefix-arg
|
||||
(guix-profile-prompt))))
|
||||
(guix-get-show-packages profile 'installed))
|
||||
|
||||
;;;###autoload
|
||||
(defun guix-obsolete-packages (&optional profile)
|
||||
"Display information about obsolete Guix packages.
|
||||
If PROFILE is nil, use `guix-current-profile'.
|
||||
Interactively with prefix, prompt for PROFILE."
|
||||
(interactive
|
||||
(list (and current-prefix-arg
|
||||
(guix-profile-prompt))))
|
||||
(guix-get-show-packages profile 'obsolete))
|
||||
|
||||
;;;###autoload
|
||||
(defun guix-all-available-packages (&optional profile)
|
||||
"Display information about all available Guix packages.
|
||||
If PROFILE is nil, use `guix-current-profile'.
|
||||
Interactively with prefix, prompt for PROFILE."
|
||||
(interactive
|
||||
(list (and current-prefix-arg
|
||||
(guix-profile-prompt))))
|
||||
(guix-get-show-packages profile 'all-available))
|
||||
|
||||
;;;###autoload
|
||||
(defun guix-newest-available-packages (&optional profile)
|
||||
"Display information about the newest available Guix packages.
|
||||
If PROFILE is nil, use `guix-current-profile'.
|
||||
Interactively with prefix, prompt for PROFILE."
|
||||
(interactive
|
||||
(list (and current-prefix-arg
|
||||
(guix-profile-prompt))))
|
||||
(guix-get-show-packages profile 'newest-available))
|
||||
|
||||
;;;###autoload
|
||||
(defun guix-generations (&optional profile)
|
||||
"Display information about all generations.
|
||||
If PROFILE is nil, use `guix-current-profile'.
|
||||
Interactively with prefix, prompt for PROFILE."
|
||||
(interactive
|
||||
(list (and current-prefix-arg
|
||||
(guix-profile-prompt))))
|
||||
(guix-get-show-generations profile 'all))
|
||||
|
||||
;;;###autoload
|
||||
(defun guix-last-generations (number &optional profile)
|
||||
"Display information about last NUMBER generations.
|
||||
If PROFILE is nil, use `guix-current-profile'.
|
||||
Interactively with prefix, prompt for PROFILE."
|
||||
(interactive
|
||||
(list (read-number "The number of last generations: ")
|
||||
(and current-prefix-arg
|
||||
(guix-profile-prompt))))
|
||||
(guix-get-show-generations profile 'last number))
|
||||
|
||||
;;;###autoload
|
||||
(defun guix-generations-by-time (from to &optional profile)
|
||||
"Display information about generations created between FROM and TO.
|
||||
FROM and TO should be time values.
|
||||
If PROFILE is nil, use `guix-current-profile'.
|
||||
Interactively with prefix, prompt for PROFILE."
|
||||
(interactive
|
||||
(list (guix-read-date "Find generations (from): ")
|
||||
(guix-read-date "Find generations (to): ")
|
||||
(and current-prefix-arg
|
||||
(guix-profile-prompt))))
|
||||
(guix-get-show-generations profile 'time
|
||||
(float-time from)
|
||||
(float-time to)))
|
||||
|
||||
;;;###autoload
|
||||
(defun guix-edit (id-or-name)
|
||||
"Edit (go to location of) package with ID-OR-NAME."
|
||||
(interactive (list (guix-read-package-name)))
|
||||
(let ((loc (guix-package-location id-or-name)))
|
||||
(if loc
|
||||
(guix-find-location loc)
|
||||
(message "Couldn't find package location."))))
|
||||
|
||||
(provide 'guix)
|
||||
|
||||
;;; guix.el ends here
|
||||
+12
-48
@@ -1,5 +1,5 @@
|
||||
# GNU Guix --- Functional package management for GNU
|
||||
# Copyright © 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
|
||||
# Copyright © 2015 Ludovic Courtès <ludo@gnu.org>
|
||||
#
|
||||
# This file is part of GNU Guix.
|
||||
#
|
||||
@@ -20,15 +20,6 @@
|
||||
|
||||
declare _guix_available_packages
|
||||
|
||||
_guix_complete_subcommand ()
|
||||
{
|
||||
local command="${COMP_WORDS[1]}"
|
||||
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]}"))
|
||||
}
|
||||
|
||||
_guix_complete_available_package ()
|
||||
{
|
||||
local prefix="$1"
|
||||
@@ -36,8 +27,7 @@ _guix_complete_available_package ()
|
||||
then
|
||||
# Cache the complete list because it rarely changes and makes
|
||||
# completion much faster.
|
||||
_guix_available_packages="$(${COMP_WORDS[0]} package -A 2> /dev/null \
|
||||
| cut -f1)"
|
||||
_guix_available_packages="$(${COMP_WORDS[0]} package -A | cut -f1)"
|
||||
fi
|
||||
COMPREPLY=($(compgen -W "$_guix_available_packages" -- "$prefix"))
|
||||
}
|
||||
@@ -47,23 +37,17 @@ _guix_complete_installed_package ()
|
||||
# Here we do not cache the list of installed packages because that
|
||||
# may change over time and the list is relatively small anyway.
|
||||
local prefix="$1"
|
||||
local packages="$(${COMP_WORDS[0]} package -I "^$prefix" 2> /dev/null \
|
||||
| cut -f1)"
|
||||
local packages="$(${COMP_WORDS[0]} package -I "^$prefix" | cut -f1)"
|
||||
COMPREPLY=($(compgen -W "$packages" -- "$prefix"))
|
||||
}
|
||||
|
||||
_guix_complete_option ()
|
||||
{
|
||||
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 \
|
||||
local options="$(${COMP_WORDS[0]} ${COMP_WORDS[1]} --help \
|
||||
| grep '^ \+-' \
|
||||
| sed -e's/^.*--\([a-zA-Z0-9_-]\+\)\(=\?\).*/--\1\2/g')"
|
||||
| sed -e's/^.*--\([a-zA-Z0-9_-]\+\)\(=\?\).*/--\1\2/g' )"
|
||||
compopt -o nospace
|
||||
COMPREPLY=($(compgen -W "$options" -- "${COMP_WORDS[${#COMP_WORDS[*]} - 1]}"))
|
||||
COMPREPLY=($(compgen -W "$options" -- "${COMP_WORDS[$word_count - 1]}"))
|
||||
}
|
||||
|
||||
_guix_is_command ()
|
||||
@@ -113,12 +97,6 @@ _guix_complete_file ()
|
||||
COMPREPLY=()
|
||||
}
|
||||
|
||||
_guix_complete_pid ()
|
||||
{
|
||||
local pids="$(cd /proc; echo [0-9]*)"
|
||||
COMPREPLY=($(compgen -W "$pids" -- "$1"))
|
||||
}
|
||||
|
||||
declare _guix_subcommands
|
||||
|
||||
_guix_complete ()
|
||||
@@ -141,8 +119,7 @@ _guix_complete ()
|
||||
if [ -z "$_guix_subcommands" ]
|
||||
then
|
||||
# Cache the list of subcommands to speed things up.
|
||||
_guix_subcommands="$(guix --help 2> /dev/null \
|
||||
| grep '^ ' | cut -c 2-)"
|
||||
_guix_subcommands="$(guix --help | grep '^ ' | cut -c 2-)"
|
||||
fi
|
||||
COMPREPLY=($(compgen -W "$_guix_subcommands" -- "$word_at_point"))
|
||||
;;
|
||||
@@ -158,28 +135,15 @@ _guix_complete ()
|
||||
else
|
||||
_guix_complete_available_package "$word_at_point"
|
||||
fi
|
||||
elif _guix_is_command "download"
|
||||
then
|
||||
_guix_complete_file
|
||||
elif _guix_is_command "system"
|
||||
then
|
||||
case $COMP_CWORD in
|
||||
2) _guix_complete_subcommand;;
|
||||
*) _guix_complete_file;; # TODO: restrict to *.scm
|
||||
esac
|
||||
elif _guix_is_command "container"
|
||||
_guix_complete_file # TODO: complete sub-commands
|
||||
elif _guix_is_command "hash"
|
||||
then
|
||||
case $COMP_CWORD in
|
||||
2) _guix_complete_subcommand;;
|
||||
3) _guix_complete_pid "$word_at_point";;
|
||||
*) _guix_complete_file;;
|
||||
esac
|
||||
elif _guix_is_command "import"
|
||||
_guix_complete_file
|
||||
elif _guix_is_command "import" # TODO: complete sub-commands
|
||||
then
|
||||
_guix_complete_subcommand
|
||||
elif _guix_is_command "hash" || _guix_is_command "gc"
|
||||
then
|
||||
_guix_complete_file
|
||||
_guix_complete_file
|
||||
else
|
||||
_guix_complete_available_package "$word_at_point"
|
||||
fi
|
||||
|
||||
@@ -1,456 +0,0 @@
|
||||
#compdef guix
|
||||
#
|
||||
# GNU Guix --- Functional package management for GNU
|
||||
# Copyright © 2016 Eric Le Bihan <eric.le.bihan.dev@free.fr>
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
|
||||
_guix_caching_policy()
|
||||
{
|
||||
local -a old_policy
|
||||
old_policy=( "$1"(Nmh+24) )
|
||||
(( $#old_policy ))
|
||||
}
|
||||
|
||||
_guix_list_actions()
|
||||
{
|
||||
_guix_actions=( $(guix system --help | sed -n 's/^ \([a-z-]\+\)\s\+.\+/\1/p') )
|
||||
}
|
||||
|
||||
_guix_list_checkers()
|
||||
{
|
||||
_guix_checkers=( $(guix lint -l | sed -n 's/^- \(.\+\): .\+/\1/p') )
|
||||
}
|
||||
|
||||
_guix_list_graph_types()
|
||||
{
|
||||
_guix_graph_types=( $(guix graph --list-types | sed -n 's/^ - \(.\+\): .\+/\1/p') )
|
||||
}
|
||||
|
||||
_guix_list_importers()
|
||||
{
|
||||
_guix_importers=( $(guix import --help | sed -n 's/^\s\+\([a-z]\+\)$/\1/p') )
|
||||
}
|
||||
|
||||
_guix_list_updaters()
|
||||
{
|
||||
_guix_updaters=( $(guix lint -l | sed -n 's/^- \(.\+\): .\+/\1/p') )
|
||||
}
|
||||
|
||||
_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)"}})
|
||||
_store_cache GUIX_AVAILABLE_PACKAGES _guix_available_packages
|
||||
fi
|
||||
}
|
||||
|
||||
_guix_list_installed_packages()
|
||||
{
|
||||
_guix_installed_packages=( $(guix package -I "^${prefix}" | cut -f1) )
|
||||
}
|
||||
|
||||
(( $+functions[_guix_build] )) || _guix_build()
|
||||
{
|
||||
_arguments \
|
||||
'--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' \
|
||||
'--derivations[return the derivation paths of the given packages]' \
|
||||
'--check[rebuild items to check for non-determinism issues]' \
|
||||
'--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]' \
|
||||
'--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' \
|
||||
'--no-grafts[do not graft packages]' \
|
||||
'--no-build-hook[do not attempt to offload builds via the build hook]' \
|
||||
'--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' \
|
||||
'--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
|
||||
_guix_list_available_packages
|
||||
compadd -a -- _guix_available_packages
|
||||
fi
|
||||
}
|
||||
|
||||
(( $+functions[_guix_challenge] )) || _guix_challenge()
|
||||
{
|
||||
_arguments \
|
||||
'--substitute-urls=[fetch substitute from URLS if they are authorized]:URL:_urls' \
|
||||
'*:package:->packages'
|
||||
|
||||
if [[ "$state" = packages ]]; then
|
||||
_guix_list_available_packages
|
||||
compadd -a -- _guix_available_packages
|
||||
fi
|
||||
}
|
||||
|
||||
(( $+functions[_guix_container] )) || _guix_container()
|
||||
{
|
||||
_arguments \
|
||||
':action:(exec)' \
|
||||
'*:args'
|
||||
}
|
||||
|
||||
(( $+functions[_guix_download] )) || _guix_download()
|
||||
{
|
||||
_arguments \
|
||||
'--format=[write the hash in the given format]:FMT:(nix-base32 base16 base32 hex)' \
|
||||
'1:URL:_urls'
|
||||
}
|
||||
|
||||
(( $+functions[_guix_edit] )) || _guix_edit()
|
||||
{
|
||||
_guix_list_available_packages
|
||||
compadd -a -- _guix_available_packages
|
||||
}
|
||||
|
||||
(( $+functions[_guix_environment] )) || _guix_environment()
|
||||
{
|
||||
_arguments \
|
||||
'--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]' \
|
||||
'--search-paths[display needed environment variable definitions]' \
|
||||
'--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]' \
|
||||
'--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' \
|
||||
'--no-grafts[do not graft packages]' \
|
||||
'--no-build-hook[do not attempt to offload builds via the build hook]' \
|
||||
'--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' \
|
||||
'--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
|
||||
_guix_list_available_packages
|
||||
compadd -a -- _guix_available_packages
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
(( $+functions[_guix_gc] )) || _guix_gc()
|
||||
{
|
||||
_arguments \
|
||||
'--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]' \
|
||||
'--requisites[list the requisites of PATHS]' \
|
||||
'--referrers[list the referrers 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]' \
|
||||
'1:PATH:_dirs'
|
||||
}
|
||||
|
||||
(( $+functions[_guix_graph] )) || _guix_graph()
|
||||
{
|
||||
_arguments \
|
||||
'--type=[represent nodes of the given TYPE]:TYPE:->types' \
|
||||
'--list-types[list the available graph types]' \
|
||||
'--expression=[consider the package EXPR evaluates to]:EXPR' \
|
||||
'1:PACKAGE:->packages'
|
||||
|
||||
case "$state" in
|
||||
types)
|
||||
_guix_list_graph_types
|
||||
compadd -a -- _guix_graph_types
|
||||
;;
|
||||
packages)
|
||||
_guix_list_available_packages
|
||||
compadd -a -- _guix_available_packages
|
||||
;;
|
||||
esac
|
||||
|
||||
}
|
||||
|
||||
(( $+functions[_guix_hash] )) || _guix_hash()
|
||||
{
|
||||
_arguments \
|
||||
'--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 \
|
||||
'1:IMPORTER:->importer' \
|
||||
'*:args:'
|
||||
|
||||
if [[ "$state" = importer ]]; then
|
||||
_guix_list_importers
|
||||
compadd -a -- _guix_importers
|
||||
fi
|
||||
}
|
||||
|
||||
(( $+functions[_guix_lint] )) || _guix_lint()
|
||||
{
|
||||
_arguments \
|
||||
'--checkers=[only run the specified checkers]:CHECKERS:->checkers' \
|
||||
'--list-checkers[display the list of available lint checkers]' \
|
||||
'1:PACKAGE:->packages'
|
||||
|
||||
case "$state" in
|
||||
checkers)
|
||||
_guix_list_checkers
|
||||
compadd -a -- _guix_checkers
|
||||
;;
|
||||
packages)
|
||||
_guix_list_available_packages
|
||||
compadd -a -- _guix_available_packages
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
(( $+functions[_guix_package] )) || _guix_package()
|
||||
{
|
||||
_arguments \
|
||||
'--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' \
|
||||
'--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]' \
|
||||
'--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' \
|
||||
'--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' \
|
||||
'--no-grafts[do not graft packages]' \
|
||||
'--no-build-hook[do not attempt to offload builds via the build hook]' \
|
||||
'--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' \
|
||||
'--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)
|
||||
_guix_list_available_packages
|
||||
compadd -a -- _guix_available_packages
|
||||
;;
|
||||
remove)
|
||||
_guix_list_installed_packages
|
||||
compadd -a -- _guix_installed_packages
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
(( $+functions[_guix_publish] )) || _guix_publish()
|
||||
{
|
||||
_arguments \
|
||||
'--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' \
|
||||
'--repl=[spawn REPL server on PORT]:PORT'
|
||||
}
|
||||
|
||||
(( $+functions[_guix_pull] )) || _guix_pull()
|
||||
{
|
||||
_arguments \
|
||||
'--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 \
|
||||
'--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=[policy to handle missing OpenPGP keys]:POLICY:(always interactive never)' \
|
||||
'*:package:->packages'
|
||||
|
||||
case "$state" in
|
||||
updaters)
|
||||
_guix_list_updaters
|
||||
compadd -a -- _guix_updaters
|
||||
;;
|
||||
packages)
|
||||
_guix_list_available_packages
|
||||
compadd -a -- _guix_available_packages
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
(( $+functions[_guix_size] )) || _guix_size()
|
||||
{
|
||||
_arguments \
|
||||
'--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
|
||||
_guix_list_available_packages
|
||||
compadd -a -- _guix_available_packages
|
||||
fi
|
||||
}
|
||||
|
||||
(( $+functions[_guix_system] )) || _guix_system()
|
||||
{
|
||||
_arguments \
|
||||
'--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]:URL:_urls' \
|
||||
'--no-grafts[do not graft packages]' \
|
||||
'--no-build-hook[do not attempt to offload builds via the build hook]' \
|
||||
'--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' \
|
||||
'--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 "vm-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'
|
||||
|
||||
if [[ "$state" = actions ]]; then
|
||||
_guix_list_actions
|
||||
compadd -a -- _guix_actions
|
||||
fi
|
||||
}
|
||||
|
||||
(( $+functions[_guix_command] )) || _guix_command()
|
||||
{
|
||||
local -a _guix_cmds
|
||||
_guix_cmds=(
|
||||
"archive:Export/import one or more packages from/to the store"
|
||||
"build:Build a given package"
|
||||
"challenge:Challenge the substitutes for a package"
|
||||
"container:Build and manipulate Linux containers"
|
||||
"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"
|
||||
"graph:Emit a DOT representation of the dependencies of a package"
|
||||
"hash:Return the cryptographic hash of a file"
|
||||
"import:Run an importer"
|
||||
"lint:Run a set of checkers on a package"
|
||||
"package:Install, remove, or upgrade packages"
|
||||
"publish:Publish /gnu/store over HTTP."
|
||||
"pull:Download and deploy the latest version of Guix"
|
||||
"refresh:Update package definitions to match the latest version"
|
||||
"size:Report the size of a package and its dependencies"
|
||||
"system:Build the operating system"
|
||||
)
|
||||
|
||||
if (( CURRENT == 1 )); then
|
||||
_describe -t commands 'guix command' _guix_cmds || compadd "$@"
|
||||
else
|
||||
local curcontext="$curcontext"
|
||||
|
||||
cmd="${${_guix_cmds[(r)$words[1]:*]%%:*}}"
|
||||
|
||||
if (( $#cmd )); then
|
||||
local cache_policy
|
||||
|
||||
zstyle -s ":completion:${curcontext}:" cache-policy cache_policy
|
||||
if [[ -z "$cache_policy" ]]; then
|
||||
zstyle ":completion:${curcontext}:" cache-policy _guix_caching_policy
|
||||
fi
|
||||
|
||||
curcontext="${curcontext%:*:*}:guix-${cmd}:"
|
||||
|
||||
_call_function ret _guix_${cmd} || _message 'no more arguments'
|
||||
else
|
||||
_message "unknown guix command: $words[1]"
|
||||
fi
|
||||
return ret
|
||||
fi
|
||||
}
|
||||
|
||||
_arguments \
|
||||
'(--version)--version[Display version information and exit]' \
|
||||
'*::guix command:_guix_command'
|
||||
|
||||
# vim: ts=4 sts=4 sw=4 et ai
|
||||
# Local variables:
|
||||
# mode: sh
|
||||
# End:
|
||||
@@ -1,69 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# This hook script prevents the user from pushing to Savannah if any of the new
|
||||
# commits' OpenPGP signatures cannot be verified.
|
||||
|
||||
# Called by "git push" after it has checked the remote status, but before
|
||||
# anything has been pushed. If this script exits with a non-zero status nothing
|
||||
# will be pushed.
|
||||
#
|
||||
# This hook is called with the following parameters:
|
||||
#
|
||||
# $1 -- Name of the remote to which the push is being done
|
||||
# $2 -- URL to which the push is being done
|
||||
#
|
||||
# If pushing without using a named remote those arguments will be equal.
|
||||
#
|
||||
# Information about the commits which are being pushed is supplied as lines to
|
||||
# the standard input in the form:
|
||||
#
|
||||
# <local ref> <local sha1> <remote ref> <remote sha1>
|
||||
|
||||
z40=0000000000000000000000000000000000000000
|
||||
|
||||
# Only use the hook when pushing to Savannah.
|
||||
case "$2" in
|
||||
*git.sv.gnu.org*)
|
||||
break
|
||||
;;
|
||||
*)
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
while read local_ref local_sha remote_ref remote_sha
|
||||
do
|
||||
if [ "$local_sha" = $z40 ]
|
||||
then
|
||||
# Handle delete
|
||||
:
|
||||
else
|
||||
if [ "$remote_sha" = $z40 ]
|
||||
then
|
||||
# We are pushing a new branch. To prevent wasting too
|
||||
# much time for this relatively rare case, we examine
|
||||
# all commits since the first signed commit, rather than
|
||||
# the full history. This check *will* fail, and the user
|
||||
# will need to temporarily disable the hook to push the
|
||||
# new branch.
|
||||
range="e3d0fcbf7e55e8cbe8d0a1c5a24d73f341d7243b..$local_sha"
|
||||
else
|
||||
# Update to existing branch, examine new commits
|
||||
range="$remote_sha..$local_sha"
|
||||
fi
|
||||
|
||||
# Verify the signatures of all commits being pushed.
|
||||
ret=0
|
||||
for commit in $(git rev-list $range)
|
||||
do
|
||||
if ! git verify-commit $commit >/dev/null 2>&1
|
||||
then
|
||||
printf "%s failed signature check\n" $commit
|
||||
ret=1
|
||||
fi
|
||||
done
|
||||
exit $ret
|
||||
fi
|
||||
done
|
||||
|
||||
exit 0
|
||||
@@ -1,10 +0,0 @@
|
||||
# This is a "job" for the Upstart init system to launch 'guix-daemon'.
|
||||
# Drop it in /etc/init to have 'guix-daemon' automatically started.
|
||||
|
||||
description "Build daemon for GNU Guix"
|
||||
|
||||
start on runlevel [2345]
|
||||
|
||||
stop on runlevel [016]
|
||||
|
||||
exec @localstatedir@/guix/profiles/per-user/root/guix-profile/bin/guix-daemon --build-users-group=guixbuild
|
||||
@@ -6,16 +6,10 @@
|
||||
Description=Build daemon for GNU Guix
|
||||
|
||||
[Service]
|
||||
ExecStart=@localstatedir@/guix/profiles/per-user/root/guix-profile/bin/guix-daemon --build-users-group=guixbuild
|
||||
Environment=GUIX_LOCPATH=/root/.guix-profile/lib/locale
|
||||
ExecStart=@bindir@/guix-daemon --build-users-group=guixbuild
|
||||
RemainAfterExit=yes
|
||||
StandardOutput=syslog
|
||||
StandardError=syslog
|
||||
|
||||
# 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.
|
||||
TasksMax=8192
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
# This is a "job" for the Upstart init system to launch 'guix-daemon'.
|
||||
# Drop it in /etc/init to have 'guix-daemon' automatically started.
|
||||
|
||||
description "Publish the GNU Guix store"
|
||||
|
||||
start on runlevel [2345]
|
||||
|
||||
stop on runlevel [016]
|
||||
|
||||
task
|
||||
|
||||
exec @localstatedir@/guix/profiles/per-user/root/guix-profile/bin/guix publish --user=nobody --port=8181
|
||||
@@ -1,19 +0,0 @@
|
||||
# This is a "service unit file" for the systemd init system to launch
|
||||
# 'guix publish'. Drop it in /etc/systemd/system or similar to have
|
||||
# 'guix publish' automatically started.
|
||||
|
||||
[Unit]
|
||||
Description=Publish the GNU Guix store
|
||||
|
||||
[Service]
|
||||
ExecStart=@localstatedir@/guix/profiles/per-user/root/guix-profile/bin/guix publish --user=nobody --port=8181
|
||||
Environment=GUIX_LOCPATH=/root/.guix-profile/lib/locale
|
||||
RemainAfterExit=yes
|
||||
StandardOutput=syslog
|
||||
StandardError=syslog
|
||||
|
||||
# See <https://lists.gnu.org/archive/html/guix-devel/2016-04/msg00608.html>.
|
||||
TasksMax=1024
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1,114 +0,0 @@
|
||||
#!@EMACS@ --script
|
||||
;;; 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>
|
||||
|
||||
;; 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))
|
||||
|
||||
|
||||
(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
|
||||
+767
@@ -0,0 +1,767 @@
|
||||
# GNU Guix --- Functional package management for GNU
|
||||
# Copyright © 2012, 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
|
||||
# Copyright © 2013, 2014, 2015 Andreas Enge <andreas@enge.fr>
|
||||
# Copyright © 2013, 2014, 2015 Mark H Weaver <mhw@netris.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/>.
|
||||
|
||||
# Definitions for the GNU System: package modules, patches, bootstrap
|
||||
# binaries.
|
||||
|
||||
GNU_SYSTEM_MODULES = \
|
||||
gnu.scm \
|
||||
gnu/artwork.scm \
|
||||
gnu/packages.scm \
|
||||
gnu/packages/aarddict.scm \
|
||||
gnu/packages/abduco.scm \
|
||||
gnu/packages/abiword.scm \
|
||||
gnu/packages/acct.scm \
|
||||
gnu/packages/acl.scm \
|
||||
gnu/packages/admin.scm \
|
||||
gnu/packages/adns.scm \
|
||||
gnu/packages/algebra.scm \
|
||||
gnu/packages/aidc.scm \
|
||||
gnu/packages/apl.scm \
|
||||
gnu/packages/apr.scm \
|
||||
gnu/packages/asciidoc.scm \
|
||||
gnu/packages/aspell.scm \
|
||||
gnu/packages/attr.scm \
|
||||
gnu/packages/audacity.scm \
|
||||
gnu/packages/audio.scm \
|
||||
gnu/packages/autogen.scm \
|
||||
gnu/packages/autotools.scm \
|
||||
gnu/packages/avahi.scm \
|
||||
gnu/packages/avr.scm \
|
||||
gnu/packages/backup.scm \
|
||||
gnu/packages/base.scm \
|
||||
gnu/packages/bash.scm \
|
||||
gnu/packages/bdw-gc.scm \
|
||||
gnu/packages/bioinformatics.scm \
|
||||
gnu/packages/bittorrent.scm \
|
||||
gnu/packages/bison.scm \
|
||||
gnu/packages/boost.scm \
|
||||
gnu/packages/bootstrap.scm \
|
||||
gnu/packages/busybox.scm \
|
||||
gnu/packages/calcurse.scm \
|
||||
gnu/packages/ccache.scm \
|
||||
gnu/packages/cdrom.scm \
|
||||
gnu/packages/certs.scm \
|
||||
gnu/packages/check.scm \
|
||||
gnu/packages/ci.scm \
|
||||
gnu/packages/cmake.scm \
|
||||
gnu/packages/code.scm \
|
||||
gnu/packages/commencement.scm \
|
||||
gnu/packages/compression.scm \
|
||||
gnu/packages/conkeror.scm \
|
||||
gnu/packages/conky.scm \
|
||||
gnu/packages/cook.scm \
|
||||
gnu/packages/cpio.scm \
|
||||
gnu/packages/cppi.scm \
|
||||
gnu/packages/cross-base.scm \
|
||||
gnu/packages/crypto.scm \
|
||||
gnu/packages/cryptsetup.scm \
|
||||
gnu/packages/cups.scm \
|
||||
gnu/packages/curl.scm \
|
||||
gnu/packages/cursynth.scm \
|
||||
gnu/packages/cyrus-sasl.scm \
|
||||
gnu/packages/databases.scm \
|
||||
gnu/packages/datamash.scm \
|
||||
gnu/packages/dc.scm \
|
||||
gnu/packages/debug.scm \
|
||||
gnu/packages/dejagnu.scm \
|
||||
gnu/packages/dictionaries.scm \
|
||||
gnu/packages/disk.scm \
|
||||
gnu/packages/djvu.scm \
|
||||
gnu/packages/dns.scm \
|
||||
gnu/packages/docbook.scm \
|
||||
gnu/packages/doxygen.scm \
|
||||
gnu/packages/dunst.scm \
|
||||
gnu/packages/dvtm.scm \
|
||||
gnu/packages/ebook.scm \
|
||||
gnu/packages/ed.scm \
|
||||
gnu/packages/elf.scm \
|
||||
gnu/packages/emacs.scm \
|
||||
gnu/packages/enchant.scm \
|
||||
gnu/packages/engineering.scm \
|
||||
gnu/packages/enlightenment.scm \
|
||||
gnu/packages/fcitx.scm \
|
||||
gnu/packages/feh.scm \
|
||||
gnu/packages/figlet.scm \
|
||||
gnu/packages/file.scm \
|
||||
gnu/packages/finance.scm \
|
||||
gnu/packages/firmware.scm \
|
||||
gnu/packages/fish.scm \
|
||||
gnu/packages/flashing-tools.scm \
|
||||
gnu/packages/flex.scm \
|
||||
gnu/packages/fltk.scm \
|
||||
gnu/packages/fonts.scm \
|
||||
gnu/packages/fontutils.scm \
|
||||
gnu/packages/freedesktop.scm \
|
||||
gnu/packages/freeipmi.scm \
|
||||
gnu/packages/ftp.scm \
|
||||
gnu/packages/fribidi.scm \
|
||||
gnu/packages/fvwm.scm \
|
||||
gnu/packages/game-development.scm \
|
||||
gnu/packages/games.scm \
|
||||
gnu/packages/gawk.scm \
|
||||
gnu/packages/gcal.scm \
|
||||
gnu/packages/gcc.scm \
|
||||
gnu/packages/gd.scm \
|
||||
gnu/packages/gdb.scm \
|
||||
gnu/packages/gdbm.scm \
|
||||
gnu/packages/geeqie.scm \
|
||||
gnu/packages/gettext.scm \
|
||||
gnu/packages/ghostscript.scm \
|
||||
gnu/packages/gimp.scm \
|
||||
gnu/packages/gkrellm.scm \
|
||||
gnu/packages/gl.scm \
|
||||
gnu/packages/glib.scm \
|
||||
gnu/packages/gnome.scm \
|
||||
gnu/packages/gnucash.scm \
|
||||
gnu/packages/gnunet.scm \
|
||||
gnu/packages/gnupg.scm \
|
||||
gnu/packages/gnustep.scm \
|
||||
gnu/packages/gnuzilla.scm \
|
||||
gnu/packages/gnu-pw-mgr.scm \
|
||||
gnu/packages/gperf.scm \
|
||||
gnu/packages/gprolog.scm \
|
||||
gnu/packages/gps.scm \
|
||||
gnu/packages/graphics.scm \
|
||||
gnu/packages/graphviz.scm \
|
||||
gnu/packages/groff.scm \
|
||||
gnu/packages/grub.scm \
|
||||
gnu/packages/grue-hunter.scm \
|
||||
gnu/packages/gsasl.scm \
|
||||
gnu/packages/gstreamer.scm \
|
||||
gnu/packages/gtk.scm \
|
||||
gnu/packages/guile.scm \
|
||||
gnu/packages/guile-wm.scm \
|
||||
gnu/packages/gv.scm \
|
||||
gnu/packages/gxmessage.scm \
|
||||
gnu/packages/haskell.scm \
|
||||
gnu/packages/hugs.scm \
|
||||
gnu/packages/hurd.scm \
|
||||
gnu/packages/ibus.scm \
|
||||
gnu/packages/icu4c.scm \
|
||||
gnu/packages/idutils.scm \
|
||||
gnu/packages/image.scm \
|
||||
gnu/packages/imagemagick.scm \
|
||||
gnu/packages/indent.scm \
|
||||
gnu/packages/inkscape.scm \
|
||||
gnu/packages/irssi.scm \
|
||||
gnu/packages/iso-codes.scm \
|
||||
gnu/packages/java.scm \
|
||||
gnu/packages/jemalloc.scm \
|
||||
gnu/packages/jrnl.scm \
|
||||
gnu/packages/julia.scm \
|
||||
gnu/packages/kde.scm \
|
||||
gnu/packages/kde-frameworks.scm \
|
||||
gnu/packages/key-mon.scm \
|
||||
gnu/packages/language.scm \
|
||||
gnu/packages/less.scm \
|
||||
gnu/packages/lesstif.scm \
|
||||
gnu/packages/libcanberra.scm \
|
||||
gnu/packages/libdaemon.scm \
|
||||
gnu/packages/libedit.scm \
|
||||
gnu/packages/libevent.scm \
|
||||
gnu/packages/libffcall.scm \
|
||||
gnu/packages/libffi.scm \
|
||||
gnu/packages/libftdi.scm \
|
||||
gnu/packages/calendar.scm \
|
||||
gnu/packages/libidn.scm \
|
||||
gnu/packages/libphidget.scm \
|
||||
gnu/packages/libreoffice.scm \
|
||||
gnu/packages/libsigsegv.scm \
|
||||
gnu/packages/libunistring.scm \
|
||||
gnu/packages/libusb.scm \
|
||||
gnu/packages/libunwind.scm \
|
||||
gnu/packages/libupnp.scm \
|
||||
gnu/packages/lightning.scm \
|
||||
gnu/packages/links.scm \
|
||||
gnu/packages/linux.scm \
|
||||
gnu/packages/lirc.scm \
|
||||
gnu/packages/lisp.scm \
|
||||
gnu/packages/llvm.scm \
|
||||
gnu/packages/lout.scm \
|
||||
gnu/packages/lsh.scm \
|
||||
gnu/packages/lsof.scm \
|
||||
gnu/packages/lua.scm \
|
||||
gnu/packages/lxde.scm \
|
||||
gnu/packages/lxqt.scm \
|
||||
gnu/packages/lynx.scm \
|
||||
gnu/packages/m4.scm \
|
||||
gnu/packages/machine-learning.scm \
|
||||
gnu/packages/man.scm \
|
||||
gnu/packages/mail.scm \
|
||||
gnu/packages/make-bootstrap.scm \
|
||||
gnu/packages/markdown.scm \
|
||||
gnu/packages/maths.scm \
|
||||
gnu/packages/mc.scm \
|
||||
gnu/packages/mcrypt.scm \
|
||||
gnu/packages/messaging.scm \
|
||||
gnu/packages/mg.scm \
|
||||
gnu/packages/miscfiles.scm \
|
||||
gnu/packages/mit-krb5.scm \
|
||||
gnu/packages/moe.scm \
|
||||
gnu/packages/moreutils.scm \
|
||||
gnu/packages/mpd.scm \
|
||||
gnu/packages/mp3.scm \
|
||||
gnu/packages/mpi.scm \
|
||||
gnu/packages/multiprecision.scm \
|
||||
gnu/packages/music.scm \
|
||||
gnu/packages/mtools.scm \
|
||||
gnu/packages/nano.scm \
|
||||
gnu/packages/ncdu.scm \
|
||||
gnu/packages/ncurses.scm \
|
||||
gnu/packages/netpbm.scm \
|
||||
gnu/packages/nettle.scm \
|
||||
gnu/packages/networking.scm \
|
||||
gnu/packages/ninja.scm \
|
||||
gnu/packages/node.scm \
|
||||
gnu/packages/noweb.scm \
|
||||
gnu/packages/ntp.scm \
|
||||
gnu/packages/nutrition.scm \
|
||||
gnu/packages/nvi.scm \
|
||||
gnu/packages/ocaml.scm \
|
||||
gnu/packages/ocr.scm \
|
||||
gnu/packages/onc-rpc.scm \
|
||||
gnu/packages/openbox.scm \
|
||||
gnu/packages/openldap.scm \
|
||||
gnu/packages/openstack.scm \
|
||||
gnu/packages/orpheus.scm \
|
||||
gnu/packages/ots.scm \
|
||||
gnu/packages/package-management.scm \
|
||||
gnu/packages/parallel.scm \
|
||||
gnu/packages/password-utils.scm \
|
||||
gnu/packages/patchutils.scm \
|
||||
gnu/packages/pciutils.scm \
|
||||
gnu/packages/pcre.scm \
|
||||
gnu/packages/pdf.scm \
|
||||
gnu/packages/pem.scm \
|
||||
gnu/packages/perl.scm \
|
||||
gnu/packages/photo.scm \
|
||||
gnu/packages/pkg-config.scm \
|
||||
gnu/packages/plotutils.scm \
|
||||
gnu/packages/polkit.scm \
|
||||
gnu/packages/popt.scm \
|
||||
gnu/packages/pth.scm \
|
||||
gnu/packages/pulseaudio.scm \
|
||||
gnu/packages/pumpio.scm \
|
||||
gnu/packages/pretty-print.scm \
|
||||
gnu/packages/protobuf.scm \
|
||||
gnu/packages/pv.scm \
|
||||
gnu/packages/python.scm \
|
||||
gnu/packages/qemu.scm \
|
||||
gnu/packages/qt.scm \
|
||||
gnu/packages/ratpoison.scm \
|
||||
gnu/packages/rc.scm \
|
||||
gnu/packages/rdesktop.scm \
|
||||
gnu/packages/rdf.scm \
|
||||
gnu/packages/readline.scm \
|
||||
gnu/packages/rrdtool.scm \
|
||||
gnu/packages/rsync.scm \
|
||||
gnu/packages/ruby.scm \
|
||||
gnu/packages/rush.scm \
|
||||
gnu/packages/samba.scm \
|
||||
gnu/packages/sawfish.scm \
|
||||
gnu/packages/scanner.scm \
|
||||
gnu/packages/scheme.scm \
|
||||
gnu/packages/screen.scm \
|
||||
gnu/packages/sdl.scm \
|
||||
gnu/packages/search.scm \
|
||||
gnu/packages/serveez.scm \
|
||||
gnu/packages/shishi.scm \
|
||||
gnu/packages/skarnet.scm \
|
||||
gnu/packages/skribilo.scm \
|
||||
gnu/packages/slang.scm \
|
||||
gnu/packages/slim.scm \
|
||||
gnu/packages/smalltalk.scm \
|
||||
gnu/packages/ssh.scm \
|
||||
gnu/packages/stalonetray.scm \
|
||||
gnu/packages/statistics.scm \
|
||||
gnu/packages/suckless.scm \
|
||||
gnu/packages/swig.scm \
|
||||
gnu/packages/sxiv.scm \
|
||||
gnu/packages/synergy.scm \
|
||||
gnu/packages/task-management.scm \
|
||||
gnu/packages/tbb.scm \
|
||||
gnu/packages/tcl.scm \
|
||||
gnu/packages/tcsh.scm \
|
||||
gnu/packages/telephony.scm \
|
||||
gnu/packages/texinfo.scm \
|
||||
gnu/packages/texlive.scm \
|
||||
gnu/packages/textutils.scm \
|
||||
gnu/packages/time.scm \
|
||||
gnu/packages/tls.scm \
|
||||
gnu/packages/tmux.scm \
|
||||
gnu/packages/tor.scm \
|
||||
gnu/packages/tre.scm \
|
||||
gnu/packages/tv.scm \
|
||||
gnu/packages/unrtf.scm \
|
||||
gnu/packages/upnp.scm \
|
||||
gnu/packages/uucp.scm \
|
||||
gnu/packages/valgrind.scm \
|
||||
gnu/packages/version-control.scm \
|
||||
gnu/packages/video.scm \
|
||||
gnu/packages/vim.scm \
|
||||
gnu/packages/vpn.scm \
|
||||
gnu/packages/vtk.scm \
|
||||
gnu/packages/w3m.scm \
|
||||
gnu/packages/wdiff.scm \
|
||||
gnu/packages/web.scm \
|
||||
gnu/packages/webkit.scm \
|
||||
gnu/packages/weechat.scm \
|
||||
gnu/packages/wget.scm \
|
||||
gnu/packages/wicd.scm \
|
||||
gnu/packages/wine.scm \
|
||||
gnu/packages/wm.scm \
|
||||
gnu/packages/wordnet.scm \
|
||||
gnu/packages/wv.scm \
|
||||
gnu/packages/wxwidgets.scm \
|
||||
gnu/packages/xfig.scm \
|
||||
gnu/packages/xiph.scm \
|
||||
gnu/packages/xml.scm \
|
||||
gnu/packages/xnee.scm \
|
||||
gnu/packages/xdisorg.scm \
|
||||
gnu/packages/xorg.scm \
|
||||
gnu/packages/xfce.scm \
|
||||
gnu/packages/yasm.scm \
|
||||
gnu/packages/yubico.scm \
|
||||
gnu/packages/zile.scm \
|
||||
gnu/packages/zip.scm \
|
||||
gnu/packages/zsh.scm \
|
||||
\
|
||||
gnu/services.scm \
|
||||
gnu/services/avahi.scm \
|
||||
gnu/services/base.scm \
|
||||
gnu/services/databases.scm \
|
||||
gnu/services/dbus.scm \
|
||||
gnu/services/desktop.scm \
|
||||
gnu/services/dmd.scm \
|
||||
gnu/services/lirc.scm \
|
||||
gnu/services/networking.scm \
|
||||
gnu/services/ssh.scm \
|
||||
gnu/services/web.scm \
|
||||
gnu/services/xorg.scm \
|
||||
\
|
||||
gnu/system.scm \
|
||||
gnu/system/file-systems.scm \
|
||||
gnu/system/grub.scm \
|
||||
gnu/system/install.scm \
|
||||
gnu/system/linux.scm \
|
||||
gnu/system/linux-container.scm \
|
||||
gnu/system/linux-initrd.scm \
|
||||
gnu/system/locale.scm \
|
||||
gnu/system/nss.scm \
|
||||
gnu/system/shadow.scm \
|
||||
gnu/system/vm.scm \
|
||||
\
|
||||
gnu/build/activation.scm \
|
||||
gnu/build/file-systems.scm \
|
||||
gnu/build/install.scm \
|
||||
gnu/build/linux-boot.scm \
|
||||
gnu/build/linux-container.scm \
|
||||
gnu/build/linux-initrd.scm \
|
||||
gnu/build/linux-modules.scm \
|
||||
gnu/build/vm.scm
|
||||
|
||||
|
||||
patchdir = $(guilemoduledir)/gnu/packages/patches
|
||||
dist_patch_DATA = \
|
||||
gnu/packages/patches/abiword-explictly-cast-bools.patch \
|
||||
gnu/packages/patches/abiword-link-plugins-against-backend.patch \
|
||||
gnu/packages/patches/abiword-no-include-glib-internal-headers.patch \
|
||||
gnu/packages/patches/abiword-pass-no-undefined-to-linker.patch \
|
||||
gnu/packages/patches/abiword-use-proper-png-api.patch \
|
||||
gnu/packages/patches/abiword-wmf-version-lookup-fix.patch \
|
||||
gnu/packages/patches/acl-hurd-path-max.patch \
|
||||
gnu/packages/patches/aegis-constness-error.patch \
|
||||
gnu/packages/patches/aegis-perl-tempdir1.patch \
|
||||
gnu/packages/patches/aegis-perl-tempdir2.patch \
|
||||
gnu/packages/patches/aegis-test-fixup-1.patch \
|
||||
gnu/packages/patches/aegis-test-fixup-2.patch \
|
||||
gnu/packages/patches/agg-am_c_prototype.patch \
|
||||
gnu/packages/patches/alsa-lib-mips-atomic-fix.patch \
|
||||
gnu/packages/patches/apr-skip-getservbyname-test.patch \
|
||||
gnu/packages/patches/ath9k-htc-firmware-binutils.patch \
|
||||
gnu/packages/patches/ath9k-htc-firmware-gcc.patch \
|
||||
gnu/packages/patches/ath9k-htc-firmware-objcopy.patch \
|
||||
gnu/packages/patches/audacity-fix-ffmpeg-binding.patch \
|
||||
gnu/packages/patches/automake-skip-amhello-tests.patch \
|
||||
gnu/packages/patches/avahi-localstatedir.patch \
|
||||
gnu/packages/patches/avidemux-install-to-lib.patch \
|
||||
gnu/packages/patches/avrdude-fix-libusb.patch \
|
||||
gnu/packages/patches/bash-completion-directories.patch \
|
||||
gnu/packages/patches/bedtools-32bit-compilation.patch \
|
||||
gnu/packages/patches/bowtie-fix-makefile.patch \
|
||||
gnu/packages/patches/bigloo-gc-shebangs.patch \
|
||||
gnu/packages/patches/binutils-ld-new-dtags.patch \
|
||||
gnu/packages/patches/binutils-loongson-workaround.patch \
|
||||
gnu/packages/patches/bitlbee-configure-doc-fix.patch \
|
||||
gnu/packages/patches/boost-mips-avoid-m32.patch \
|
||||
gnu/packages/patches/calibre-drop-unrar.patch \
|
||||
gnu/packages/patches/calibre-no-updates-dialog.patch \
|
||||
gnu/packages/patches/cdparanoia-fpic.patch \
|
||||
gnu/packages/patches/chmlib-inttypes.patch \
|
||||
gnu/packages/patches/clang-libc-search-path.patch \
|
||||
gnu/packages/patches/clucene-pkgconfig.patch \
|
||||
gnu/packages/patches/cmake-fix-tests.patch \
|
||||
gnu/packages/patches/cpio-gets-undeclared.patch \
|
||||
gnu/packages/patches/cpufrequtils-fix-aclocal.patch \
|
||||
gnu/packages/patches/crda-optional-gcrypt.patch \
|
||||
gnu/packages/patches/crossmap-allow-system-pysam.patch \
|
||||
gnu/packages/patches/cssc-gets-undeclared.patch \
|
||||
gnu/packages/patches/cssc-missing-include.patch \
|
||||
gnu/packages/patches/clucene-contribs-lib.patch \
|
||||
gnu/packages/patches/cursynth-wave-rand.patch \
|
||||
gnu/packages/patches/dbus-localstatedir.patch \
|
||||
gnu/packages/patches/dealii-p4est-interface.patch \
|
||||
gnu/packages/patches/diffutils-gets-undeclared.patch \
|
||||
gnu/packages/patches/dfu-programmer-fix-libusb.patch \
|
||||
gnu/packages/patches/doxygen-test.patch \
|
||||
gnu/packages/patches/doxygen-tmake.patch \
|
||||
gnu/packages/patches/duplicity-piped-password.patch \
|
||||
gnu/packages/patches/duplicity-test_selection-tmp.patch \
|
||||
gnu/packages/patches/elfutils-tests-ptrace.patch \
|
||||
gnu/packages/patches/emacs-exec-path.patch \
|
||||
gnu/packages/patches/eudev-rules-directory.patch \
|
||||
gnu/packages/patches/evilwm-lost-focus-bug.patch \
|
||||
gnu/packages/patches/expat-CVE-2015-1283.patch \
|
||||
gnu/packages/patches/fastcap-mulGlobal.patch \
|
||||
gnu/packages/patches/fastcap-mulSetup.patch \
|
||||
gnu/packages/patches/fasthenry-spAllocate.patch \
|
||||
gnu/packages/patches/fasthenry-spBuild.patch \
|
||||
gnu/packages/patches/fasthenry-spUtils.patch \
|
||||
gnu/packages/patches/fasthenry-spSolve.patch \
|
||||
gnu/packages/patches/fasthenry-spFactor.patch \
|
||||
gnu/packages/patches/findutils-absolute-paths.patch \
|
||||
gnu/packages/patches/findutils-localstatedir.patch \
|
||||
gnu/packages/patches/flashrom-use-libftdi1.patch \
|
||||
gnu/packages/patches/flex-bison-tests.patch \
|
||||
gnu/packages/patches/flint-ldconfig.patch \
|
||||
gnu/packages/patches/fltk-shared-lib-defines.patch \
|
||||
gnu/packages/patches/freeimage-CVE-2015-0852.patch \
|
||||
gnu/packages/patches/fuse-CVE-2015-3202.patch \
|
||||
gnu/packages/patches/gawk-shell.patch \
|
||||
gnu/packages/patches/gcc-arm-link-spec-fix.patch \
|
||||
gnu/packages/patches/gcc-cross-environment-variables.patch \
|
||||
gnu/packages/patches/gcc-libvtv-runpath.patch \
|
||||
gnu/packages/patches/gcc-5.0-libvtv-runpath.patch \
|
||||
gnu/packages/patches/geoclue-config.patch \
|
||||
gnu/packages/patches/ghostscript-CVE-2015-3228.patch \
|
||||
gnu/packages/patches/ghostscript-runpath.patch \
|
||||
gnu/packages/patches/gitolite-openssh-6.8-compat.patch \
|
||||
gnu/packages/patches/glib-networking-ssl-cert-file.patch \
|
||||
gnu/packages/patches/glib-tests-desktop.patch \
|
||||
gnu/packages/patches/glib-tests-homedir.patch \
|
||||
gnu/packages/patches/glib-tests-prlimit.patch \
|
||||
gnu/packages/patches/glib-tests-timer.patch \
|
||||
gnu/packages/patches/glib-tests-gapplication.patch \
|
||||
gnu/packages/patches/glibc-bootstrap-system.patch \
|
||||
gnu/packages/patches/glibc-ldd-x86_64.patch \
|
||||
gnu/packages/patches/glibc-locales.patch \
|
||||
gnu/packages/patches/glibc-locale-incompatibility.patch \
|
||||
gnu/packages/patches/glibc-o-largefile.patch \
|
||||
gnu/packages/patches/glibc-versioned-locpath.patch \
|
||||
gnu/packages/patches/gmp-arm-asm-nothumb.patch \
|
||||
gnu/packages/patches/gmp-faulty-test.patch \
|
||||
gnu/packages/patches/gnucash-price-quotes-perl.patch \
|
||||
gnu/packages/patches/gnutls-doc-fix.patch \
|
||||
gnu/packages/patches/gobject-introspection-absolute-shlib-path.patch \
|
||||
gnu/packages/patches/gobject-introspection-cc.patch \
|
||||
gnu/packages/patches/gobject-introspection-girepository.patch \
|
||||
gnu/packages/patches/grep-CVE-2015-1345.patch \
|
||||
gnu/packages/patches/grub-gets-undeclared.patch \
|
||||
gnu/packages/patches/grub-freetype.patch \
|
||||
gnu/packages/patches/gsl-poly-test-fix-pt1.patch \
|
||||
gnu/packages/patches/gsl-poly-test-fix-pt2.patch \
|
||||
gnu/packages/patches/guile-1.8-cpp-4.5.patch \
|
||||
gnu/packages/patches/guile-arm-fixes.patch \
|
||||
gnu/packages/patches/guile-default-utf8.patch \
|
||||
gnu/packages/patches/guile-linux-syscalls.patch \
|
||||
gnu/packages/patches/guile-present-coding.patch \
|
||||
gnu/packages/patches/guile-relocatable.patch \
|
||||
gnu/packages/patches/guile-rsvg-pkgconfig.patch \
|
||||
gnu/packages/patches/gtkglext-disable-disable-deprecated.patch \
|
||||
gnu/packages/patches/hop-bigloo-4.0b.patch \
|
||||
gnu/packages/patches/hop-linker-flags.patch \
|
||||
gnu/packages/patches/hwloc-gather-topology-lstopo.patch \
|
||||
gnu/packages/patches/hydra-automake-1.15.patch \
|
||||
gnu/packages/patches/hydra-disable-darcs-test.patch \
|
||||
gnu/packages/patches/icecat-avoid-bundled-includes.patch \
|
||||
gnu/packages/patches/icecat-freetype-2.6.patch \
|
||||
gnu/packages/patches/icu4c-CVE-2014-6585.patch \
|
||||
gnu/packages/patches/icu4c-CVE-2015-1270.patch \
|
||||
gnu/packages/patches/icu4c-CVE-2015-4760.patch \
|
||||
gnu/packages/patches/imagemagick-test-segv.patch \
|
||||
gnu/packages/patches/irrlicht-mesa-10.patch \
|
||||
gnu/packages/patches/jbig2dec-ignore-testtest.patch \
|
||||
gnu/packages/patches/julia-0.3.10-fix-empty-array.patch \
|
||||
gnu/packages/patches/kmod-module-directory.patch \
|
||||
gnu/packages/patches/lftp-dont-save-unknown-host-fingerprint.patch \
|
||||
gnu/packages/patches/liba52-enable-pic.patch \
|
||||
gnu/packages/patches/liba52-link-with-libm.patch \
|
||||
gnu/packages/patches/liba52-set-soname.patch \
|
||||
gnu/packages/patches/liba52-use-mtune-not-mcpu.patch \
|
||||
gnu/packages/patches/libarchive-CVE-2013-0211.patch \
|
||||
gnu/packages/patches/libarchive-fix-lzo-test-case.patch \
|
||||
gnu/packages/patches/libarchive-mtree-filename-length-fix.patch \
|
||||
gnu/packages/patches/libbonobo-activation-test-race.patch \
|
||||
gnu/packages/patches/libcanberra-sound-theme-freedesktop.patch \
|
||||
gnu/packages/patches/libevent-dns-tests.patch \
|
||||
gnu/packages/patches/libmtp-devices.patch \
|
||||
gnu/packages/patches/liboop-mips64-deplibs-fix.patch \
|
||||
gnu/packages/patches/liblxqt-include.patch \
|
||||
gnu/packages/patches/libmad-armv7-thumb-pt1.patch \
|
||||
gnu/packages/patches/libmad-armv7-thumb-pt2.patch \
|
||||
gnu/packages/patches/libmad-frame-length.patch \
|
||||
gnu/packages/patches/libmad-mips-newgcc.patch \
|
||||
gnu/packages/patches/libtheora-config-guess.patch \
|
||||
gnu/packages/patches/libtool-skip-tests2.patch \
|
||||
gnu/packages/patches/libssh-CVE-2014-0017.patch \
|
||||
gnu/packages/patches/libunwind-CVE-2015-3239.patch \
|
||||
gnu/packages/patches/libwmf-CAN-2004-0941.patch \
|
||||
gnu/packages/patches/libwmf-CVE-2006-3376.patch \
|
||||
gnu/packages/patches/libwmf-CVE-2007-0455.patch \
|
||||
gnu/packages/patches/libwmf-CVE-2007-2756.patch \
|
||||
gnu/packages/patches/libwmf-CVE-2007-3472.patch \
|
||||
gnu/packages/patches/libwmf-CVE-2007-3473.patch \
|
||||
gnu/packages/patches/libwmf-CVE-2007-3477.patch \
|
||||
gnu/packages/patches/libwmf-CVE-2009-1364.patch \
|
||||
gnu/packages/patches/libwmf-CVE-2009-3546.patch \
|
||||
gnu/packages/patches/libwmf-CVE-2015-0848+CVE-2015-4588.patch \
|
||||
gnu/packages/patches/libwmf-CVE-2015-4695.patch \
|
||||
gnu/packages/patches/libwmf-CVE-2015-4696.patch \
|
||||
gnu/packages/patches/lirc-localstatedir.patch \
|
||||
gnu/packages/patches/libpthread-glibc-preparation.patch \
|
||||
gnu/packages/patches/lm-sensors-hwmon-attrs.patch \
|
||||
gnu/packages/patches/lua-pkgconfig.patch \
|
||||
gnu/packages/patches/lua51-liblua-so.patch \
|
||||
gnu/packages/patches/luajit-no_ldconfig.patch \
|
||||
gnu/packages/patches/luajit-symlinks.patch \
|
||||
gnu/packages/patches/luit-posix.patch \
|
||||
gnu/packages/patches/m4-gets-undeclared.patch \
|
||||
gnu/packages/patches/make-impure-dirs.patch \
|
||||
gnu/packages/patches/mars-install.patch \
|
||||
gnu/packages/patches/mars-sfml-2.3.patch \
|
||||
gnu/packages/patches/maxima-defsystem-mkdir.patch \
|
||||
gnu/packages/patches/mc-fix-ncurses-build.patch \
|
||||
gnu/packages/patches/mcron-install.patch \
|
||||
gnu/packages/patches/mdadm-gcc-4.9-fix.patch \
|
||||
gnu/packages/patches/mhash-keygen-test-segfault.patch \
|
||||
gnu/packages/patches/mit-krb5-init-fix.patch \
|
||||
gnu/packages/patches/mpc123-initialize-ao.patch \
|
||||
gnu/packages/patches/mplayer2-theora-fix.patch \
|
||||
gnu/packages/patches/module-init-tools-moduledir.patch \
|
||||
gnu/packages/patches/mumps-build-parallelism.patch \
|
||||
gnu/packages/patches/mupdf-buildsystem-fix.patch \
|
||||
gnu/packages/patches/mutt-store-references.patch \
|
||||
gnu/packages/patches/net-tools-bitrot.patch \
|
||||
gnu/packages/patches/ngircd-handle-zombies.patch \
|
||||
gnu/packages/patches/ngircd-no-dns-in-tests.patch \
|
||||
gnu/packages/patches/ninja-tests.patch \
|
||||
gnu/packages/patches/ninja-zero-mtime.patch \
|
||||
gnu/packages/patches/nss-pkgconfig.patch \
|
||||
gnu/packages/patches/nvi-assume-preserve-path.patch \
|
||||
gnu/packages/patches/nvi-dbpagesize-binpower.patch \
|
||||
gnu/packages/patches/nvi-db4.patch \
|
||||
gnu/packages/patches/openexr-missing-samples.patch \
|
||||
gnu/packages/patches/openjpeg-CVE-2015-6581.patch \
|
||||
gnu/packages/patches/openjpeg-use-after-free-fix.patch \
|
||||
gnu/packages/patches/openssl-runpath.patch \
|
||||
gnu/packages/patches/openssl-c-rehash.patch \
|
||||
gnu/packages/patches/orpheus-cast-errors-and-includes.patch \
|
||||
gnu/packages/patches/ots-no-include-missing-file.patch \
|
||||
gnu/packages/patches/patchelf-page-size.patch \
|
||||
gnu/packages/patches/patchelf-rework-for-arm.patch \
|
||||
gnu/packages/patches/patchutils-xfail-gendiff-tests.patch \
|
||||
gnu/packages/patches/patch-hurd-path-max.patch \
|
||||
gnu/packages/patches/perl-autosplit-default-time.patch \
|
||||
gnu/packages/patches/perl-finance-quote-unuse-mozilla-ca.patch \
|
||||
gnu/packages/patches/perl-gd-options-passthrough-and-fontconfig.patch \
|
||||
gnu/packages/patches/perl-module-pluggable-search.patch \
|
||||
gnu/packages/patches/perl-net-amazon-s3-moose-warning.patch \
|
||||
gnu/packages/patches/perl-net-ssleay-disable-ede-test.patch \
|
||||
gnu/packages/patches/perl-no-sys-dirs.patch \
|
||||
gnu/packages/patches/perl-tk-x11-discover.patch \
|
||||
gnu/packages/patches/pidgin-add-search-path.patch \
|
||||
gnu/packages/patches/pingus-sdl-libs-config.patch \
|
||||
gnu/packages/patches/plotutils-libpng-jmpbuf.patch \
|
||||
gnu/packages/patches/polkit-drop-test.patch \
|
||||
gnu/packages/patches/portaudio-audacity-compat.patch \
|
||||
gnu/packages/patches/preseq-1.0.2-install-to-PREFIX.patch \
|
||||
gnu/packages/patches/preseq-1.0.2-link-with-libbam.patch \
|
||||
gnu/packages/patches/procps-make-3.82.patch \
|
||||
gnu/packages/patches/pt-scotch-build-parallelism.patch \
|
||||
gnu/packages/patches/pulseaudio-fix-mult-test.patch \
|
||||
gnu/packages/patches/pulseaudio-longer-test-timeout.patch \
|
||||
gnu/packages/patches/pycairo-wscript.patch \
|
||||
gnu/packages/patches/pybugz-encode-error.patch \
|
||||
gnu/packages/patches/pybugz-stty.patch \
|
||||
gnu/packages/patches/pyqt-configure.patch \
|
||||
gnu/packages/patches/python-2.7-search-paths.patch \
|
||||
gnu/packages/patches/python-3-search-paths.patch \
|
||||
gnu/packages/patches/python-disable-ssl-test.patch \
|
||||
gnu/packages/patches/python-fix-tests.patch \
|
||||
gnu/packages/patches/python2-rdflib-drop-sparqlwrapper.patch \
|
||||
gnu/packages/patches/python2-pygobject-2-gi-info-type-error-domain.patch \
|
||||
gnu/packages/patches/qemu-CVE-2015-6855.patch \
|
||||
gnu/packages/patches/qt4-ldflags.patch \
|
||||
gnu/packages/patches/ratpoison-shell.patch \
|
||||
gnu/packages/patches/readline-link-ncurses.patch \
|
||||
gnu/packages/patches/ripperx-missing-file.patch \
|
||||
gnu/packages/patches/sed-hurd-path-max.patch \
|
||||
gnu/packages/patches/scheme48-tests.patch \
|
||||
gnu/packages/patches/scotch-test-threading.patch \
|
||||
gnu/packages/patches/sdl-libx11-1.6.patch \
|
||||
gnu/packages/patches/serf-comment-style-fix.patch \
|
||||
gnu/packages/patches/serf-deflate-buckets-test-fix.patch \
|
||||
gnu/packages/patches/slim-session.patch \
|
||||
gnu/packages/patches/slim-config.patch \
|
||||
gnu/packages/patches/slim-sigusr1.patch \
|
||||
gnu/packages/patches/soprano-find-clucene.patch \
|
||||
gnu/packages/patches/superlu-dist-scotchmetis.patch \
|
||||
gnu/packages/patches/tar-d_ino_in_dirent-fix.patch \
|
||||
gnu/packages/patches/tar-skip-unreliable-tests.patch \
|
||||
gnu/packages/patches/tcsh-fix-autotest.patch \
|
||||
gnu/packages/patches/texi2html-document-encoding.patch \
|
||||
gnu/packages/patches/texi2html-i18n.patch \
|
||||
gnu/packages/patches/tidy-CVE-2015-5522+5523.patch \
|
||||
gnu/packages/patches/tvtime-gcc41.patch \
|
||||
gnu/packages/patches/tvtime-pngoutput.patch \
|
||||
gnu/packages/patches/tvtime-videodev2.patch \
|
||||
gnu/packages/patches/tvtime-xmltv.patch \
|
||||
gnu/packages/patches/unzip-CVE-2014-8139.patch \
|
||||
gnu/packages/patches/unzip-CVE-2014-8140.patch \
|
||||
gnu/packages/patches/unzip-CVE-2014-8141.patch \
|
||||
gnu/packages/patches/unzip-CVE-2014-9636.patch \
|
||||
gnu/packages/patches/unzip-allow-greater-hostver-values.patch \
|
||||
gnu/packages/patches/unzip-attribs-overflow.patch \
|
||||
gnu/packages/patches/unzip-fix-overflows-and-infloop.patch \
|
||||
gnu/packages/patches/unzip-format-secure.patch \
|
||||
gnu/packages/patches/unzip-initialize-symlink-flag.patch \
|
||||
gnu/packages/patches/unzip-overflow-long-fsize.patch \
|
||||
gnu/packages/patches/unzip-remove-build-date.patch \
|
||||
gnu/packages/patches/util-linux-tests.patch \
|
||||
gnu/packages/patches/upower-builddir.patch \
|
||||
gnu/packages/patches/valgrind-enable-arm.patch \
|
||||
gnu/packages/patches/vpnc-script.patch \
|
||||
gnu/packages/patches/vtk-mesa-10.patch \
|
||||
gnu/packages/patches/w3m-fix-compile.patch \
|
||||
gnu/packages/patches/webkitgtk-2.4-sql-init-string.patch \
|
||||
gnu/packages/patches/weex-vacopy.patch \
|
||||
gnu/packages/patches/wicd-bitrate-none-fix.patch \
|
||||
gnu/packages/patches/wicd-get-selected-profile-fix.patch \
|
||||
gnu/packages/patches/wicd-template-instantiation.patch \
|
||||
gnu/packages/patches/wicd-urwid-1.3.patch \
|
||||
gnu/packages/patches/wmctrl-64-fix.patch \
|
||||
gnu/packages/patches/xf86-video-ark-remove-mibstore.patch \
|
||||
gnu/packages/patches/xf86-video-ast-remove-mibstore.patch \
|
||||
gnu/packages/patches/xf86-video-geode-glibc-2.20.patch \
|
||||
gnu/packages/patches/xf86-video-glint-remove-mibstore.patch \
|
||||
gnu/packages/patches/xf86-video-i128-remove-mibstore.patch \
|
||||
gnu/packages/patches/xf86-video-intel-compat-api.patch \
|
||||
gnu/packages/patches/xf86-video-intel-glibc-2.20.patch \
|
||||
gnu/packages/patches/xf86-video-mach64-glibc-2.20.patch \
|
||||
gnu/packages/patches/xf86-video-mga-glibc-2.20.patch \
|
||||
gnu/packages/patches/xf86-video-nv-remove-mibstore.patch \
|
||||
gnu/packages/patches/xf86-video-openchrome-glibc-2.20.patch \
|
||||
gnu/packages/patches/xf86-video-r128-glibc-2.20.patch \
|
||||
gnu/packages/patches/xf86-video-siliconmotion-remove-mibstore.patch \
|
||||
gnu/packages/patches/xf86-video-sis-fix-exa-crash.patch \
|
||||
gnu/packages/patches/xf86-video-sis-update-api.patch \
|
||||
gnu/packages/patches/xf86-video-tdfx-remove-mibstore.patch \
|
||||
gnu/packages/patches/xf86-video-tga-remove-mibstore.patch \
|
||||
gnu/packages/patches/xf86-video-trident-remove-mibstore.patch \
|
||||
gnu/packages/patches/xf86-video-vmware-glibc-2.20.patch \
|
||||
gnu/packages/patches/xfce4-panel-plugins.patch \
|
||||
gnu/packages/patches/xfce4-settings-defaults.patch \
|
||||
gnu/packages/patches/xmodmap-asprintf.patch \
|
||||
gnu/packages/patches/zathura-plugindir-environment-variable.patch
|
||||
|
||||
MISC_DISTRO_FILES = \
|
||||
gnu/packages/ld-wrapper.in
|
||||
|
||||
bootstrapdir = $(guilemoduledir)/gnu/packages/bootstrap
|
||||
bootstrap_x86_64_linuxdir = $(bootstrapdir)/x86_64-linux
|
||||
bootstrap_i686_linuxdir = $(bootstrapdir)/i686-linux
|
||||
bootstrap_armhf_linuxdir = $(bootstrapdir)/armhf-linux
|
||||
bootstrap_mips64el_linuxdir = $(bootstrapdir)/mips64el-linux
|
||||
|
||||
dist_bootstrap_x86_64_linux_DATA = \
|
||||
gnu/packages/bootstrap/x86_64-linux/bash \
|
||||
gnu/packages/bootstrap/x86_64-linux/mkdir \
|
||||
gnu/packages/bootstrap/x86_64-linux/tar \
|
||||
gnu/packages/bootstrap/x86_64-linux/xz
|
||||
|
||||
dist_bootstrap_i686_linux_DATA = \
|
||||
gnu/packages/bootstrap/i686-linux/bash \
|
||||
gnu/packages/bootstrap/i686-linux/mkdir \
|
||||
gnu/packages/bootstrap/i686-linux/tar \
|
||||
gnu/packages/bootstrap/i686-linux/xz
|
||||
|
||||
dist_bootstrap_armhf_linux_DATA = \
|
||||
gnu/packages/bootstrap/armhf-linux/bash \
|
||||
gnu/packages/bootstrap/armhf-linux/mkdir \
|
||||
gnu/packages/bootstrap/armhf-linux/tar \
|
||||
gnu/packages/bootstrap/armhf-linux/xz
|
||||
|
||||
dist_bootstrap_mips64el_linux_DATA = \
|
||||
gnu/packages/bootstrap/mips64el-linux/bash \
|
||||
gnu/packages/bootstrap/mips64el-linux/mkdir \
|
||||
gnu/packages/bootstrap/mips64el-linux/tar \
|
||||
gnu/packages/bootstrap/mips64el-linux/xz
|
||||
|
||||
# Big bootstrap binaries are not included in the tarball. Instead, they
|
||||
# are downloaded.
|
||||
nodist_bootstrap_x86_64_linux_DATA = \
|
||||
gnu/packages/bootstrap/x86_64-linux/guile-2.0.9.tar.xz
|
||||
nodist_bootstrap_i686_linux_DATA = \
|
||||
gnu/packages/bootstrap/i686-linux/guile-2.0.9.tar.xz
|
||||
nodist_bootstrap_armhf_linux_DATA = \
|
||||
gnu/packages/bootstrap/armhf-linux/guile-2.0.11.tar.xz
|
||||
nodist_bootstrap_mips64el_linux_DATA = \
|
||||
gnu/packages/bootstrap/mips64el-linux/guile-2.0.9.tar.xz
|
||||
|
||||
# Those files must remain executable, so they remain executable once
|
||||
# imported into the store.
|
||||
set-bootstrap-executable-permissions:
|
||||
chmod +x $(DESTDIR)$(bootstrapdir)/*/{bash,mkdir,tar,xz}
|
||||
|
||||
DISTCLEANFILES = \
|
||||
$(nodist_bootstrap_x86_64_linux_DATA) \
|
||||
$(nodist_bootstrap_i686_linux_DATA) \
|
||||
$(nodist_bootstrap_armhf_linux_DATA) \
|
||||
$(nodist_bootstrap_mips64el_linux_DATA)
|
||||
|
||||
# Method to download a file from an external source.
|
||||
DOWNLOAD_FILE = \
|
||||
GUILE_LOAD_COMPILED_PATH="$(top_builddir):$$GUILE_LOAD_COMPILED_PATH" \
|
||||
$(GUILE) --no-auto-compile -L "$(top_builddir)" -L "$(top_srcdir)" \
|
||||
"$(top_srcdir)/build-aux/download.scm"
|
||||
|
||||
gnu/packages/bootstrap/x86_64-linux/guile-2.0.9.tar.xz:
|
||||
$(MKDIR_P) `dirname "$@"`
|
||||
$(DOWNLOAD_FILE) "$@" "037b103522a2d0d7d69c7ffd8de683dfe5bb4b59c1fafd70b4ffd397fd2f57f0"
|
||||
gnu/packages/bootstrap/i686-linux/guile-2.0.9.tar.xz:
|
||||
$(MKDIR_P) `dirname "$@"`
|
||||
$(DOWNLOAD_FILE) "$@" "b757cd46bf13ecac83fb8e955fb50096ac2d17bb610ca8eb816f29302a00a846"
|
||||
gnu/packages/bootstrap/armhf-linux/guile-2.0.11.tar.xz:
|
||||
$(MKDIR_P) `dirname "$@"`
|
||||
$(DOWNLOAD_FILE) "$@" "e551d05d4d385d6706ab8d574856a087758294dc90ab4c06e70a157a685e23d6"
|
||||
gnu/packages/bootstrap/mips64el-linux/guile-2.0.9.tar.xz:
|
||||
$(MKDIR_P) `dirname "$@"`
|
||||
$(DOWNLOAD_FILE) "$@" "994680f0001346864aa2c2cc5110f380ee7518dcd701c614291682b8e948f73b"
|
||||
@@ -1,7 +1,6 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2014, 2015 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2015 Joshua S. Grant <jgrant@parenthetical.io>
|
||||
;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
@@ -19,14 +18,6 @@
|
||||
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
(define-module (gnu)
|
||||
#:use-module (guix i18n)
|
||||
#:use-module (guix utils)
|
||||
#:use-module (srfi srfi-34)
|
||||
#:use-module (srfi srfi-35)
|
||||
#:use-module (ice-9 match)
|
||||
#:use-module (guix packages)
|
||||
#:use-module (gnu packages)
|
||||
#:use-module (gnu services)
|
||||
#:export (use-package-modules
|
||||
use-service-modules
|
||||
use-system-modules))
|
||||
@@ -41,11 +32,9 @@
|
||||
(begin
|
||||
(define %public-modules
|
||||
'((gnu system)
|
||||
(gnu system mapped-devices)
|
||||
(gnu system file-systems)
|
||||
(gnu bootloader)
|
||||
(gnu bootloader grub)
|
||||
(gnu system pam)
|
||||
(gnu system grub) ; 'grub-configuration'
|
||||
(gnu system linux) ; 'base-pam-services'
|
||||
(gnu system shadow) ; 'user-account'
|
||||
(gnu system linux-initrd)
|
||||
(gnu system nss)
|
||||
@@ -60,97 +49,13 @@
|
||||
(module-use! i (resolve-interface m))))
|
||||
%public-modules)))
|
||||
|
||||
(define (%try-use-modules modules location make-hint)
|
||||
"Attempt to load all of MODULES. Report errors as coming from LOCATION, a
|
||||
<location> record, and use MAKE-HINT to produce a fix hint."
|
||||
(define (location->string loc)
|
||||
(match loc
|
||||
(#f "")
|
||||
(($ <location> file line column)
|
||||
(format #f "~a:~a:~a: " file line column))))
|
||||
|
||||
(for-each (lambda (module)
|
||||
(catch 'misc-error
|
||||
(lambda ()
|
||||
(process-use-modules `((,module))))
|
||||
(lambda _
|
||||
(raise
|
||||
(apply
|
||||
make-compound-condition
|
||||
(condition
|
||||
(&message
|
||||
(message (format #f (G_ "module ~a not found")
|
||||
module))))
|
||||
(condition
|
||||
(&error-location (location location)))
|
||||
(or (and=> (make-hint module) list)
|
||||
'()))))))
|
||||
modules))
|
||||
|
||||
(define (package-module-hint module)
|
||||
(define last-name
|
||||
(match module
|
||||
((_ ... last)
|
||||
(symbol->string last))))
|
||||
|
||||
(match (find-packages-by-name last-name)
|
||||
(()
|
||||
(condition
|
||||
(&fix-hint
|
||||
(hint (G_ "\
|
||||
You may use @command{guix package --show=foo | grep location} to search
|
||||
for the location of package @code{foo}.
|
||||
If you get the line @code{location: gnu/packages/bar.scm:174:2},
|
||||
add @code{bar} to the @code{use-package-modules} form.")))))
|
||||
((package _ ...)
|
||||
(condition
|
||||
(&fix-hint
|
||||
(hint (format #f (G_ "\
|
||||
Try adding @code{(use-package-modules ~a)}.")
|
||||
(basename (location-file (package-location package))
|
||||
".scm"))))))))
|
||||
|
||||
(define (service-module-hint module)
|
||||
(define last-name
|
||||
(match module
|
||||
((_ ... last)
|
||||
last)))
|
||||
|
||||
(match (lookup-service-types last-name)
|
||||
(()
|
||||
(condition
|
||||
(&fix-hint
|
||||
(hint (format #f (G_ "\
|
||||
You may use @command{guix system search ~a} to search for a service
|
||||
matching @code{~a}.
|
||||
If you get the line @code{location: gnu/services/foo.scm:188:2},
|
||||
add @code{foo} to the @code{use-service-modules} form.")
|
||||
last-name last-name)))))
|
||||
((package _ ...)
|
||||
(condition
|
||||
(&fix-hint
|
||||
(hint (format #f (G_ "\
|
||||
Try adding @code{(use-service-modules ~a)}.")
|
||||
(basename (location-file (service-type-location package))
|
||||
".scm"))))))))
|
||||
|
||||
(define-syntax-rule (try-use-modules hint modules ...)
|
||||
(eval-when (expand load eval)
|
||||
(%try-use-modules '(modules ...)
|
||||
(source-properties->location
|
||||
(current-source-location))
|
||||
hint)))
|
||||
|
||||
(define-syntax-rule (use-package-modules module ...)
|
||||
(try-use-modules package-module-hint
|
||||
(gnu packages module) ...))
|
||||
(use-modules (gnu packages module) ...))
|
||||
|
||||
(define-syntax-rule (use-service-modules module ...)
|
||||
(try-use-modules service-module-hint
|
||||
(gnu services module) ...))
|
||||
(use-modules (gnu services module) ...))
|
||||
|
||||
(define-syntax-rule (use-system-modules module ...)
|
||||
(try-use-modules (const #f) ;no hint
|
||||
(gnu system module) ...))
|
||||
(use-modules (gnu system module) ...))
|
||||
|
||||
;;; gnu.scm ends here
|
||||
|
||||
+8
-12
@@ -1,6 +1,5 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2014, 2015 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2017 Leo Famulari <leo@famulari.name>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
@@ -29,16 +28,13 @@
|
||||
;;; Code:
|
||||
|
||||
(define %artwork-repository
|
||||
(let ((commit "6998d30425289b087c64f63e7415df2241e591db"))
|
||||
(origin
|
||||
(method git-fetch)
|
||||
(uri (git-reference
|
||||
(url "git://git.savannah.gnu.org/guix/guix-artwork.git")
|
||||
(commit commit)))
|
||||
(file-name (string-append "guix-artwork-" (string-take commit 7)
|
||||
"-checkout"))
|
||||
(sha256
|
||||
(base32
|
||||
"0k7j3pj9s3zqiqmfkapypssvzx3f12yr0cc2rbzxqfii0b4clp1j")))))
|
||||
(origin
|
||||
(method git-fetch)
|
||||
(uri (git-reference
|
||||
(url "git://git.savannah.gnu.org/guix/guix-artwork.git")
|
||||
(commit "6998d30")))
|
||||
(sha256
|
||||
(base32
|
||||
"0k7j3pj9s3zqiqmfkapypssvzx3f12yr0cc2rbzxqfii0b4clp1j"))))
|
||||
|
||||
;;; artwork.scm ends here
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2017 David Craven <david@craven.ch>
|
||||
;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
|
||||
;;; Copyright © 2017 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/>.
|
||||
|
||||
(define-module (gnu bootloader)
|
||||
#:use-module (guix discovery)
|
||||
#:use-module (guix records)
|
||||
#:use-module (guix ui)
|
||||
#:use-module (srfi srfi-1)
|
||||
#:export (menu-entry
|
||||
menu-entry?
|
||||
menu-entry-label
|
||||
menu-entry-device
|
||||
menu-entry-linux
|
||||
menu-entry-linux-arguments
|
||||
menu-entry-initrd
|
||||
menu-entry-device-mount-point
|
||||
|
||||
bootloader
|
||||
bootloader?
|
||||
bootloader-name
|
||||
bootloader-package
|
||||
bootloader-installer
|
||||
bootloader-configuration-file
|
||||
bootloader-configuration-file-generator
|
||||
|
||||
bootloader-configuration
|
||||
bootloader-configuration?
|
||||
bootloader-configuration-bootloader
|
||||
bootloader-configuration-target
|
||||
bootloader-configuration-menu-entries
|
||||
bootloader-configuration-default-entry
|
||||
bootloader-configuration-timeout
|
||||
bootloader-configuration-theme
|
||||
bootloader-configuration-terminal-outputs
|
||||
bootloader-configuration-terminal-inputs
|
||||
bootloader-configuration-serial-unit
|
||||
bootloader-configuration-serial-speed
|
||||
bootloader-configuration-additional-configuration
|
||||
|
||||
%bootloaders
|
||||
lookup-bootloader-by-name))
|
||||
|
||||
|
||||
;;;
|
||||
;;; Menu-entry record.
|
||||
;;;
|
||||
|
||||
(define-record-type* <menu-entry>
|
||||
menu-entry make-menu-entry
|
||||
menu-entry?
|
||||
(label menu-entry-label)
|
||||
(device menu-entry-device ; file system uuid, label, or #f
|
||||
(default #f))
|
||||
(device-mount-point menu-entry-device-mount-point
|
||||
(default #f))
|
||||
(linux menu-entry-linux)
|
||||
(linux-arguments menu-entry-linux-arguments
|
||||
(default '())) ; list of string-valued gexps
|
||||
(initrd menu-entry-initrd)) ; file name of the initrd as a gexp
|
||||
|
||||
|
||||
;;;
|
||||
;;; Bootloader record.
|
||||
;;;
|
||||
|
||||
;; The <bootloader> record contains fields expressing how the bootloader
|
||||
;; should be installed. Every bootloader in gnu/bootloader/ directory
|
||||
;; has to be described by this record.
|
||||
|
||||
(define-record-type* <bootloader>
|
||||
bootloader make-bootloader
|
||||
bootloader?
|
||||
(name bootloader-name)
|
||||
(package bootloader-package)
|
||||
(installer bootloader-installer)
|
||||
(configuration-file bootloader-configuration-file)
|
||||
(configuration-file-generator bootloader-configuration-file-generator))
|
||||
|
||||
|
||||
;;;
|
||||
;;; Bootloader configuration record.
|
||||
;;;
|
||||
|
||||
;; The <bootloader-configuration> record contains bootloader independant
|
||||
;; configuration used to fill bootloader configuration file.
|
||||
|
||||
(define-record-type* <bootloader-configuration>
|
||||
bootloader-configuration make-bootloader-configuration
|
||||
bootloader-configuration?
|
||||
(bootloader bootloader-configuration-bootloader) ; <bootloader>
|
||||
(device bootloader-configuration-device ; string
|
||||
(default #f))
|
||||
(target %bootloader-configuration-target ; string
|
||||
(default #f))
|
||||
(menu-entries bootloader-configuration-menu-entries ; list of <boot-parameters>
|
||||
(default '()))
|
||||
(default-entry bootloader-configuration-default-entry ; integer
|
||||
(default 0))
|
||||
(timeout bootloader-configuration-timeout ; seconds as integer
|
||||
(default 5))
|
||||
(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))
|
||||
(additional-configuration bootloader-configuration-additional-configuration ; record
|
||||
(default #f)))
|
||||
|
||||
(define (bootloader-configuration-target config)
|
||||
(or (%bootloader-configuration-target config)
|
||||
(let ((device (bootloader-configuration-device config)))
|
||||
(when device
|
||||
(warning
|
||||
(G_ "The 'device' field of bootloader configurations is deprecated.~%"))
|
||||
(warning (G_ "Use 'target' instead.~%")))
|
||||
device)))
|
||||
|
||||
|
||||
;;;
|
||||
;;; Bootloaders.
|
||||
;;;
|
||||
|
||||
(define (bootloader-modules)
|
||||
"Return the list of bootloader modules."
|
||||
(all-modules (map (lambda (entry)
|
||||
`(,entry . "gnu/bootloader"))
|
||||
%load-path)))
|
||||
|
||||
(define %bootloaders
|
||||
;; The list of publically-known bootloaders.
|
||||
(delay (fold-module-public-variables (lambda (obj result)
|
||||
(if (bootloader? obj)
|
||||
(cons obj result)
|
||||
result))
|
||||
'()
|
||||
(bootloader-modules))))
|
||||
|
||||
(define (lookup-bootloader-by-name name)
|
||||
"Return the bootloader called NAME."
|
||||
(or (find (lambda (bootloader)
|
||||
(eq? name (bootloader-name bootloader)))
|
||||
(force %bootloaders))
|
||||
(leave (G_ "~a: no such bootloader~%") name)))
|
||||
@@ -1,132 +0,0 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2017 David Craven <david@craven.ch>
|
||||
;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@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/>.
|
||||
|
||||
(define-module (gnu bootloader extlinux)
|
||||
#:use-module (gnu bootloader)
|
||||
#:use-module (gnu system)
|
||||
#:use-module (gnu packages bootloaders)
|
||||
#:use-module (guix gexp)
|
||||
#:use-module (guix monads)
|
||||
#:use-module (guix records)
|
||||
#:use-module (guix utils)
|
||||
#:export (extlinux-bootloader
|
||||
extlinux-bootloader-gpt))
|
||||
|
||||
(define* (extlinux-configuration-file config entries
|
||||
#:key
|
||||
(system (%current-system))
|
||||
(old-entries '()))
|
||||
"Return the U-Boot configuration file corresponding to CONFIG, a
|
||||
<u-boot-configuration> object, and where the store is available at STORE-FS, a
|
||||
<file-system> object. OLD-ENTRIES is taken to be a list of menu entries
|
||||
corresponding to old generations of the system."
|
||||
|
||||
(define all-entries
|
||||
(append entries (bootloader-configuration-menu-entries config)))
|
||||
|
||||
(define (menu-entry->gexp entry)
|
||||
(let ((label (menu-entry-label entry))
|
||||
(kernel (menu-entry-linux entry))
|
||||
(kernel-arguments (menu-entry-linux-arguments entry))
|
||||
(initrd (menu-entry-initrd entry)))
|
||||
#~(format port "LABEL ~a
|
||||
MENU LABEL ~a
|
||||
KERNEL ~a
|
||||
FDTDIR ~a/lib/dtbs
|
||||
INITRD ~a
|
||||
APPEND ~a
|
||||
~%"
|
||||
#$label #$label
|
||||
#$kernel (dirname #$kernel) #$initrd
|
||||
(string-join (list #$@kernel-arguments)))))
|
||||
|
||||
(define builder
|
||||
#~(call-with-output-file #$output
|
||||
(lambda (port)
|
||||
(let ((timeout #$(bootloader-configuration-timeout config)))
|
||||
(format port "# This file was generated from your GuixSD configuration. Any changes
|
||||
# will be lost upon reconfiguration.
|
||||
UI menu.c32
|
||||
PROMPT ~a
|
||||
TIMEOUT ~a~%"
|
||||
(if (> timeout 0) 1 0)
|
||||
;; timeout is expressed in 1/10s of seconds.
|
||||
(* 10 timeout))
|
||||
#$@(map menu-entry->gexp all-entries)
|
||||
|
||||
#$@(if (pair? old-entries)
|
||||
#~((format port "~%")
|
||||
#$@(map menu-entry->gexp old-entries)
|
||||
(format port "~%"))
|
||||
#~())))))
|
||||
|
||||
(gexp->derivation "extlinux.conf" builder))
|
||||
|
||||
|
||||
|
||||
|
||||
;;;
|
||||
;;; Install procedures.
|
||||
;;;
|
||||
|
||||
(define dd
|
||||
#~(lambda (bs count if of)
|
||||
(zero? (system* "dd"
|
||||
(string-append "bs=" (number->string bs))
|
||||
(string-append "count=" (number->string count))
|
||||
(string-append "if=" if)
|
||||
(string-append "of=" of)))))
|
||||
|
||||
(define (install-extlinux mbr)
|
||||
#~(lambda (bootloader device mount-point)
|
||||
(let ((extlinux (string-append bootloader "/sbin/extlinux"))
|
||||
(install-dir (string-append mount-point "/boot/extlinux"))
|
||||
(syslinux-dir (string-append bootloader "/share/syslinux")))
|
||||
(for-each (lambda (file)
|
||||
(install-file file install-dir))
|
||||
(find-files syslinux-dir "\\.c32$"))
|
||||
|
||||
(unless (and (zero? (system* extlinux "--install" install-dir))
|
||||
(#$dd 440 1 (string-append syslinux-dir "/" #$mbr) device))
|
||||
(error "failed to install SYSLINUX")))))
|
||||
|
||||
(define install-extlinux-mbr
|
||||
(install-extlinux "mbr.bin"))
|
||||
|
||||
(define install-extlinux-gpt
|
||||
(install-extlinux "gptmbr.bin"))
|
||||
|
||||
|
||||
|
||||
;;;
|
||||
;;; Bootloader definitions.
|
||||
;;;
|
||||
|
||||
(define extlinux-bootloader
|
||||
(bootloader
|
||||
(name 'extlinux)
|
||||
(package syslinux)
|
||||
(installer install-extlinux-mbr)
|
||||
(configuration-file "/boot/extlinux/extlinux.conf")
|
||||
(configuration-file-generator extlinux-configuration-file)))
|
||||
|
||||
(define extlinux-bootloader-gpt
|
||||
(bootloader
|
||||
(inherit extlinux-bootloader)
|
||||
(installer install-extlinux-gpt)))
|
||||
@@ -1,453 +0,0 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2016 Chris Marusich <cmmarusich@gmail.com>
|
||||
;;; Copyright © 2017 Leo Famulari <leo@famulari.name>
|
||||
;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@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/>.
|
||||
|
||||
(define-module (gnu bootloader grub)
|
||||
#:use-module (guix store)
|
||||
#:use-module (guix packages)
|
||||
#:use-module (guix derivations)
|
||||
#:use-module (guix records)
|
||||
#:use-module (guix monads)
|
||||
#:use-module (guix gexp)
|
||||
#:use-module (guix download)
|
||||
#:use-module (gnu artwork)
|
||||
#:use-module (gnu system)
|
||||
#:use-module (gnu bootloader)
|
||||
#:use-module (gnu system uuid)
|
||||
#:autoload (gnu packages bootloaders) (grub)
|
||||
#:autoload (gnu packages compression) (gzip)
|
||||
#:autoload (gnu packages gtk) (guile-cairo guile-rsvg)
|
||||
#:autoload (gnu packages guile) (guile-2.2)
|
||||
#:use-module (ice-9 match)
|
||||
#:use-module (ice-9 regex)
|
||||
#:use-module (srfi srfi-1)
|
||||
#:use-module (rnrs bytevectors)
|
||||
#:export (grub-image
|
||||
grub-image?
|
||||
grub-image-aspect-ratio
|
||||
grub-image-file
|
||||
|
||||
grub-theme
|
||||
grub-theme?
|
||||
grub-theme-images
|
||||
grub-theme-color-normal
|
||||
grub-theme-color-highlight
|
||||
|
||||
%background-image
|
||||
%default-theme
|
||||
|
||||
grub-bootloader
|
||||
grub-efi-bootloader
|
||||
grub-mkrescue-bootloader
|
||||
|
||||
grub-configuration))
|
||||
|
||||
;;; Commentary:
|
||||
;;;
|
||||
;;; Configuration of GNU GRUB.
|
||||
;;;
|
||||
;;; Code:
|
||||
|
||||
(define (strip-mount-point mount-point file)
|
||||
"Strip MOUNT-POINT from FILE, which is a gexp or other lowerable object
|
||||
denoting a file name."
|
||||
(match mount-point
|
||||
((? string? mount-point)
|
||||
(if (string=? mount-point "/")
|
||||
file
|
||||
#~(let ((file #$file))
|
||||
(if (string-prefix? #$mount-point file)
|
||||
(substring #$file #$(string-length mount-point))
|
||||
file))))
|
||||
(#f file)))
|
||||
|
||||
(define-record-type* <grub-image>
|
||||
grub-image make-grub-image
|
||||
grub-image?
|
||||
(aspect-ratio grub-image-aspect-ratio ;rational number
|
||||
(default 4/3))
|
||||
(file grub-image-file)) ;file-valued gexp (SVG)
|
||||
|
||||
(define-record-type* <grub-theme>
|
||||
grub-theme make-grub-theme
|
||||
grub-theme?
|
||||
(images grub-theme-images
|
||||
(default '())) ;list of <grub-image>
|
||||
(color-normal grub-theme-color-normal
|
||||
(default '((fg . cyan) (bg . blue))))
|
||||
(color-highlight grub-theme-color-highlight
|
||||
(default '((fg . white) (bg . blue)))))
|
||||
|
||||
(define %background-image
|
||||
(grub-image
|
||||
(aspect-ratio 4/3)
|
||||
(file (file-append %artwork-repository
|
||||
"/grub/GuixSD-fully-black-4-3.svg"))))
|
||||
|
||||
(define %default-theme
|
||||
;; Default theme contributed by Felipe López.
|
||||
(grub-theme
|
||||
(images (list %background-image))
|
||||
(color-highlight '((fg . yellow) (bg . black)))
|
||||
(color-normal '((fg . light-gray) (bg . black))))) ;XXX: #x303030
|
||||
|
||||
|
||||
;;;
|
||||
;;; Background image & themes.
|
||||
;;;
|
||||
|
||||
(define (bootloader-theme config)
|
||||
"Return user defined theme in CONFIG if defined or %default-theme
|
||||
otherwise."
|
||||
(or (bootloader-configuration-theme config) %default-theme))
|
||||
|
||||
(define* (svg->png svg #:key width height)
|
||||
"Build a PNG of HEIGHT x WIDTH from SVG."
|
||||
;; Note: Guile-RSVG & co. are now built for Guile 2.2, so we use 2.2 here.
|
||||
;; TODO: Remove #:guile-for-build when 2.2 has become the default.
|
||||
(mlet %store-monad ((guile (package->derivation guile-2.2 #:graft? #f)))
|
||||
(gexp->derivation "grub-image.png"
|
||||
(with-imported-modules '((gnu build svg))
|
||||
#~(begin
|
||||
;; We need these two libraries.
|
||||
(add-to-load-path (string-append #+guile-rsvg
|
||||
"/share/guile/site/"
|
||||
(effective-version)))
|
||||
(add-to-load-path (string-append #+guile-cairo
|
||||
"/share/guile/site/"
|
||||
(effective-version)))
|
||||
|
||||
(use-modules (gnu build svg))
|
||||
(svg->png #+svg #$output
|
||||
#:width #$width
|
||||
#:height #$height)))
|
||||
#:guile-for-build guile)))
|
||||
|
||||
(define* (grub-background-image config #:key (width 1024) (height 768))
|
||||
"Return the GRUB background image defined in CONFIG with a ratio of
|
||||
WIDTH/HEIGHT, or #f if none was found."
|
||||
(let* ((ratio (/ width height))
|
||||
(image (find (lambda (image)
|
||||
(= (grub-image-aspect-ratio image) ratio))
|
||||
(grub-theme-images
|
||||
(bootloader-theme config)))))
|
||||
(if image
|
||||
(svg->png (grub-image-file image)
|
||||
#:width width #:height height)
|
||||
(with-monad %store-monad
|
||||
(return #f)))))
|
||||
|
||||
(define* (eye-candy config store-device store-mount-point
|
||||
#:key system port)
|
||||
"Return in %STORE-MONAD a gexp that writes to PORT (a port-valued gexp) the
|
||||
'grub.cfg' part concerned with graphics mode, background images, colors, and
|
||||
all that. STORE-DEVICE designates the device holding the store, and
|
||||
STORE-MOUNT-POINT is its mount point; these are used to determine where the
|
||||
background image and fonts must be searched for. SYSTEM must be the target
|
||||
system string---e.g., \"x86_64-linux\"."
|
||||
(define setup-gfxterm-body
|
||||
;; Intel and EFI systems need to be switched into graphics mode, whereas
|
||||
;; most other modern architectures have no other mode and therefore don't
|
||||
;; need to be switched.
|
||||
(if (string-match "^(x86_64|i[3-6]86)-" system)
|
||||
"
|
||||
# Leave 'gfxmode' to 'auto'.
|
||||
insmod video_bochs
|
||||
insmod video_cirrus
|
||||
insmod gfxterm
|
||||
|
||||
if [ \"${grub_platform}\" == efi ]; then
|
||||
# This is for (U)EFI systems (these modules are unavailable in the
|
||||
# non-EFI GRUB.) If we don't load them, GRUB boots in \"blind mode\",
|
||||
# which isn't convenient.
|
||||
insmod efi_gop
|
||||
insmod efi_uga
|
||||
else
|
||||
# These are specific to non-EFI Intel machines.
|
||||
insmod vbe
|
||||
insmod vga
|
||||
fi
|
||||
"
|
||||
""))
|
||||
|
||||
(define (setup-gfxterm config font-file)
|
||||
(if (memq 'gfxterm (bootloader-configuration-terminal-outputs config))
|
||||
#~(format #f "if loadfont ~a; then
|
||||
setup_gfxterm
|
||||
fi~%" #$font-file)
|
||||
""))
|
||||
|
||||
(define (theme-colors type)
|
||||
(let* ((theme (bootloader-theme config))
|
||||
(colors (type theme)))
|
||||
(string-append (symbol->string (assoc-ref colors 'fg)) "/"
|
||||
(symbol->string (assoc-ref colors 'bg)))))
|
||||
|
||||
(define font-file
|
||||
(strip-mount-point store-mount-point
|
||||
(file-append grub "/share/grub/unicode.pf2")))
|
||||
|
||||
(mlet* %store-monad ((image (grub-background-image config)))
|
||||
(return (and image
|
||||
#~(format #$port "
|
||||
function setup_gfxterm {~a}
|
||||
|
||||
# Set 'root' to the partition that contains /gnu/store.
|
||||
~a
|
||||
|
||||
~a
|
||||
~a
|
||||
|
||||
insmod png
|
||||
if background_image ~a; then
|
||||
set color_normal=~a
|
||||
set color_highlight=~a
|
||||
else
|
||||
set menu_color_normal=cyan/blue
|
||||
set menu_color_highlight=white/blue
|
||||
fi~%"
|
||||
#$setup-gfxterm-body
|
||||
#$(grub-root-search store-device font-file)
|
||||
#$(setup-gfxterm config font-file)
|
||||
#$(grub-setup-io config)
|
||||
|
||||
#$(strip-mount-point store-mount-point image)
|
||||
#$(theme-colors grub-theme-color-normal)
|
||||
#$(theme-colors grub-theme-color-highlight))))))
|
||||
|
||||
|
||||
;;;
|
||||
;;; Configuration file.
|
||||
;;;
|
||||
|
||||
(define (grub-setup-io config)
|
||||
"Return GRUB commands to configure the input / output interfaces. The result
|
||||
is a string that can be inserted in grub.cfg."
|
||||
(let* ((symbols->string (lambda (list)
|
||||
(string-join (map symbol->string list) " ")))
|
||||
(outputs (bootloader-configuration-terminal-outputs config))
|
||||
(inputs (bootloader-configuration-terminal-inputs config))
|
||||
(unit (bootloader-configuration-serial-unit config))
|
||||
(speed (bootloader-configuration-serial-speed config))
|
||||
|
||||
;; Respectively, GRUB_TERMINAL_OUTPUT and GRUB_TERMINAL_INPUT,
|
||||
;; as documented in GRUB manual section "Simple Configuration
|
||||
;; Handling".
|
||||
(valid-outputs '(console serial serial_0 serial_1 serial_2 serial_3
|
||||
gfxterm vga_text mda_text morse spkmodem))
|
||||
(valid-inputs '(console serial serial_0 serial_1 serial_2 serial_3
|
||||
at_keyboard usb_keyboard))
|
||||
|
||||
(io (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"))
|
||||
;; 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)
|
||||
"Return the GRUB 'search' command to look for DEVICE, which contains FILE,
|
||||
a gexp. The result is a gexp that can be inserted in the grub.cfg-generation
|
||||
code."
|
||||
;; Usually FILE is a file name gexp like "/gnu/store/…-linux/vmlinuz", but
|
||||
;; it can also be something like "(hd0,msdos1)/vmlinuz" in the case of
|
||||
;; custom menu entries. In the latter case, don't emit a 'search' command.
|
||||
(if (and (string? file) (not (string-prefix? "/" file)))
|
||||
""
|
||||
(match device
|
||||
;; Preferably refer to DEVICE by its UUID or label. This is more
|
||||
;; efficient and less ambiguous, see <http://bugs.gnu.org/22281>.
|
||||
((? uuid? uuid)
|
||||
(format #f "search --fs-uuid --set ~a"
|
||||
(uuid->string device)))
|
||||
((? string? label)
|
||||
(format #f "search --label --set ~a" label))
|
||||
(#f
|
||||
#~(format #f "search --file --set ~a" #$file)))))
|
||||
|
||||
(define* (grub-configuration-file config entries
|
||||
#:key
|
||||
(system (%current-system))
|
||||
(old-entries '()))
|
||||
"Return the GRUB configuration file corresponding to CONFIG, a
|
||||
<bootloader-configuration> object, and where the store is available at
|
||||
STORE-FS, a <file-system> object. OLD-ENTRIES is taken to be a list of menu
|
||||
entries corresponding to old generations of the system."
|
||||
(define all-entries
|
||||
(append entries (bootloader-configuration-menu-entries config)))
|
||||
(define (menu-entry->gexp entry)
|
||||
(let ((device (menu-entry-device entry))
|
||||
(device-mount-point (menu-entry-device-mount-point entry))
|
||||
(label (menu-entry-label entry))
|
||||
(kernel (menu-entry-linux entry))
|
||||
(arguments (menu-entry-linux-arguments entry))
|
||||
(initrd (menu-entry-initrd entry)))
|
||||
;; Here DEVICE is the store and DEVICE-MOUNT-POINT is its mount point.
|
||||
;; Use the right file names for KERNEL and INITRD in case
|
||||
;; DEVICE-MOUNT-POINT is not "/", meaning that the store is on a
|
||||
;; separate partition.
|
||||
(let ((kernel (strip-mount-point device-mount-point kernel))
|
||||
(initrd (strip-mount-point device-mount-point initrd)))
|
||||
#~(format port "menuentry ~s {
|
||||
~a
|
||||
linux ~a ~a
|
||||
initrd ~a
|
||||
}~%"
|
||||
#$label
|
||||
#$(grub-root-search device kernel)
|
||||
#$kernel (string-join (list #$@arguments))
|
||||
#$initrd))))
|
||||
(mlet %store-monad ((sugar (eye-candy config
|
||||
(menu-entry-device
|
||||
(first all-entries))
|
||||
(menu-entry-device-mount-point
|
||||
(first all-entries))
|
||||
#:system system
|
||||
#:port #~port)))
|
||||
(define builder
|
||||
#~(call-with-output-file #$output
|
||||
(lambda (port)
|
||||
(format port
|
||||
"# This file was generated from your GuixSD configuration. Any changes
|
||||
# will be lost upon reconfiguration.
|
||||
")
|
||||
#$sugar
|
||||
(format port "
|
||||
set default=~a
|
||||
set timeout=~a~%"
|
||||
#$(bootloader-configuration-default-entry config)
|
||||
#$(bootloader-configuration-timeout config))
|
||||
#$@(map menu-entry->gexp all-entries)
|
||||
|
||||
#$@(if (pair? old-entries)
|
||||
#~((format port "
|
||||
submenu \"GNU system, old configurations...\" {~%")
|
||||
#$@(map menu-entry->gexp old-entries)
|
||||
(format port "}~%"))
|
||||
#~()))))
|
||||
|
||||
(gexp->derivation "grub.cfg" builder)))
|
||||
|
||||
|
||||
|
||||
;;;
|
||||
;;; Install procedures.
|
||||
;;;
|
||||
|
||||
(define install-grub
|
||||
#~(lambda (bootloader device mount-point)
|
||||
;; Install GRUB on DEVICE which is mounted at MOUNT-POINT.
|
||||
(let ((grub (string-append bootloader "/sbin/grub-install"))
|
||||
(install-dir (string-append mount-point "/boot")))
|
||||
;; Tell 'grub-install' that there might be a LUKS-encrypted /boot or
|
||||
;; root partition.
|
||||
(setenv "GRUB_ENABLE_CRYPTODISK" "y")
|
||||
|
||||
(unless (zero? (system* grub "--no-floppy"
|
||||
"--boot-directory" install-dir
|
||||
device))
|
||||
(error "failed to install GRUB (BIOS)")))))
|
||||
|
||||
(define install-grub-efi
|
||||
#~(lambda (bootloader efi-dir mount-point)
|
||||
;; 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")))
|
||||
;; Tell 'grub-install' that there might be a LUKS-encrypted /boot or
|
||||
;; root partition.
|
||||
(setenv "GRUB_ENABLE_CRYPTODISK" "y")
|
||||
(unless (zero? (system* grub-install "--boot-directory" install-dir
|
||||
"--efi-directory" efi-dir))
|
||||
(error "failed to install GRUB (EFI)")))))
|
||||
|
||||
|
||||
|
||||
;;;
|
||||
;;; Bootloader definitions.
|
||||
;;;
|
||||
|
||||
(define grub-bootloader
|
||||
(bootloader
|
||||
(name 'grub)
|
||||
(package grub)
|
||||
(installer install-grub)
|
||||
(configuration-file "/boot/grub/grub.cfg")
|
||||
(configuration-file-generator grub-configuration-file)))
|
||||
|
||||
(define* grub-efi-bootloader
|
||||
(bootloader
|
||||
(inherit grub-bootloader)
|
||||
(installer install-grub-efi)
|
||||
(name 'grub-efi)
|
||||
(package grub-efi)))
|
||||
|
||||
(define* grub-mkrescue-bootloader
|
||||
(bootloader
|
||||
(inherit grub-efi-bootloader)
|
||||
(package grub-hybrid)))
|
||||
|
||||
|
||||
;;;
|
||||
;;; Compatibility macros.
|
||||
;;;
|
||||
|
||||
(define-syntax grub-configuration
|
||||
(syntax-rules (grub)
|
||||
((_ (grub package) fields ...)
|
||||
(if (eq? package grub)
|
||||
(bootloader-configuration
|
||||
(bootloader grub-bootloader)
|
||||
fields ...)
|
||||
(bootloader-configuration
|
||||
(bootloader grub-efi-bootloader)
|
||||
fields ...)))
|
||||
((_ fields ...)
|
||||
(bootloader-configuration
|
||||
(bootloader grub-bootloader)
|
||||
fields ...))))
|
||||
|
||||
;;; grub.scm ends here
|
||||
@@ -1,47 +0,0 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2017 David Craven <david@craven.ch>
|
||||
;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@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/>.
|
||||
|
||||
(define-module (gnu bootloader u-boot)
|
||||
#:use-module (gnu bootloader extlinux)
|
||||
#:use-module (gnu bootloader)
|
||||
#:use-module (gnu system)
|
||||
#:use-module (gnu packages bootloaders)
|
||||
#:use-module (guix gexp)
|
||||
#:use-module (guix monads)
|
||||
#:use-module (guix records)
|
||||
#:use-module (guix utils)
|
||||
#:export (u-boot-bootloader))
|
||||
|
||||
(define install-u-boot
|
||||
#~(lambda (bootloader device mount-point)
|
||||
(if bootloader
|
||||
(error "Failed to install U-Boot"))))
|
||||
|
||||
|
||||
|
||||
;;;
|
||||
;;; Bootloader definitions.
|
||||
;;;
|
||||
|
||||
(define u-boot-bootloader
|
||||
(bootloader
|
||||
(inherit extlinux-bootloader)
|
||||
(name 'u-boot)
|
||||
(package #f)
|
||||
(installer install-u-boot)))
|
||||
+33
-80
@@ -1,5 +1,5 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2015 Mark H Weaver <mhw@netris.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
@@ -25,10 +25,9 @@
|
||||
#:use-module (srfi srfi-1)
|
||||
#:use-module (srfi srfi-26)
|
||||
#:export (activate-users+groups
|
||||
activate-user-home
|
||||
activate-etc
|
||||
activate-setuid-programs
|
||||
activate-special-files
|
||||
activate-/bin/sh
|
||||
activate-modprobe
|
||||
activate-firmware
|
||||
activate-ptrace-attach
|
||||
@@ -79,28 +78,20 @@
|
||||
(define (dot-or-dot-dot? file)
|
||||
(member file '("." "..")))
|
||||
|
||||
(define* (copy-account-skeletons home
|
||||
#:key
|
||||
(directory %skeleton-directory)
|
||||
uid gid)
|
||||
"Copy the account skeletons from DIRECTORY to HOME. When UID is an integer,
|
||||
make it the owner of all the files created; likewise for GID."
|
||||
(define (set-owner file)
|
||||
(when (or uid gid)
|
||||
(chown file (or uid -1) (or gid -1))))
|
||||
(define (make-file-writable file)
|
||||
"Make FILE writable for its owner.."
|
||||
(let ((stat (lstat file))) ;XXX: symlinks
|
||||
(chmod file (logior #o600 (stat:perms stat)))))
|
||||
|
||||
(define* (copy-account-skeletons home
|
||||
#:optional (directory %skeleton-directory))
|
||||
"Copy the account skeletons from DIRECTORY to HOME."
|
||||
(let ((files (scandir directory (negate dot-or-dot-dot?)
|
||||
string<?)))
|
||||
(mkdir-p home)
|
||||
(set-owner home)
|
||||
(for-each (lambda (file)
|
||||
(let ((target (string-append home "/" file)))
|
||||
(copy-recursively (string-append directory "/" file)
|
||||
target
|
||||
#:log (%make-void-port "w"))
|
||||
(for-each set-owner
|
||||
(find-files target (const #t)
|
||||
#:directories? #t))
|
||||
(copy-file (string-append directory "/" file) target)
|
||||
(make-file-writable target)))
|
||||
files)))
|
||||
|
||||
@@ -117,8 +108,7 @@ owner-writable in HOME."
|
||||
files)))
|
||||
|
||||
(define* (add-user name group
|
||||
#:key uid comment home create-home?
|
||||
shell password system?
|
||||
#:key uid comment home shell password system?
|
||||
(supplementary-groups '())
|
||||
(log-port (current-error-port)))
|
||||
"Create an account for user NAME part of GROUP, with the specified
|
||||
@@ -130,15 +120,14 @@ properties. Return #t on success."
|
||||
;; 'useradd' fails with "Cannot determine your user name" if the root
|
||||
;; account doesn't exist. Thus, for bootstrapping purposes, create that
|
||||
;; one manually.
|
||||
(let ((home (or home "/root")))
|
||||
(begin
|
||||
(call-with-output-file "/etc/shadow"
|
||||
(cut format <> "~a::::::::~%" name))
|
||||
(call-with-output-file "/etc/passwd"
|
||||
(cut format <> "~a:x:~a:~a:~a:~a:~a~%"
|
||||
name "0" "0" comment home shell))
|
||||
(chmod "/etc/shadow" #o600)
|
||||
(copy-account-skeletons home)
|
||||
(chmod home #o700)
|
||||
(copy-account-skeletons (or home "/root"))
|
||||
#t)
|
||||
|
||||
;; Use 'useradd' from the Shadow package.
|
||||
@@ -148,7 +137,7 @@ properties. Return #t on success."
|
||||
`("-G" ,(string-join supplementary-groups ","))
|
||||
'())
|
||||
,@(if comment `("-c" ,comment) '())
|
||||
,@(if (and home create-home?)
|
||||
,@(if home
|
||||
(if (file-exists? home)
|
||||
`("-d" ,home) ; avoid warning from 'useradd'
|
||||
`("-d" ,home "--create-home"))
|
||||
@@ -167,8 +156,7 @@ properties. Return #t on success."
|
||||
#t)))))
|
||||
|
||||
(define* (modify-user name group
|
||||
#:key uid comment home create-home?
|
||||
shell password system?
|
||||
#:key uid comment home shell password system?
|
||||
(supplementary-groups '())
|
||||
(log-port (current-error-port)))
|
||||
"Modify user account NAME to have all the given settings."
|
||||
@@ -196,8 +184,7 @@ logged in."
|
||||
(zero? (system* "groupdel" name)))
|
||||
|
||||
(define* (ensure-user name group
|
||||
#:key uid comment home create-home?
|
||||
shell password system?
|
||||
#:key uid comment home shell password system?
|
||||
(supplementary-groups '())
|
||||
(log-port (current-error-port))
|
||||
#:rest rest)
|
||||
@@ -218,8 +205,7 @@ numeric gid or #f."
|
||||
|
||||
(define activate-user
|
||||
(match-lambda
|
||||
((name uid group supplementary-groups comment home create-home?
|
||||
shell password system?)
|
||||
((name uid group supplementary-groups comment home shell password system?)
|
||||
(let ((profile-dir (string-append "/var/guix/profiles/per-user/"
|
||||
name)))
|
||||
(ensure-user name group
|
||||
@@ -228,11 +214,6 @@ numeric gid or #f."
|
||||
#:supplementary-groups supplementary-groups
|
||||
#:comment comment
|
||||
#:home home
|
||||
|
||||
;; Home directories of non-system accounts are created by
|
||||
;; 'activate-user-home'.
|
||||
#:create-home? (and create-home? system?)
|
||||
|
||||
#:shell shell
|
||||
#:password password)
|
||||
|
||||
@@ -245,9 +226,6 @@ numeric gid or #f."
|
||||
;; 'groupadd' aborts if the file doesn't already exist.
|
||||
(touch "/etc/group")
|
||||
|
||||
;; Allow home directories to be created under /var/lib.
|
||||
(mkdir-p "/var/lib")
|
||||
|
||||
;; Create the root account so we can use 'useradd' and 'groupadd'.
|
||||
(activate-user (find (match-lambda
|
||||
((name (? zero?) _ ...) #t)
|
||||
@@ -280,28 +258,6 @@ numeric gid or #f."
|
||||
(((names . _) ...)
|
||||
names)))))
|
||||
|
||||
(define (activate-user-home users)
|
||||
"Create and populate the home directory of USERS, a list of tuples, unless
|
||||
they already exist."
|
||||
(define ensure-user-home
|
||||
(match-lambda
|
||||
((name uid group supplementary-groups comment home create-home?
|
||||
shell password system?)
|
||||
;; The home directories of system accounts are created during
|
||||
;; activation, not here.
|
||||
(unless (or (not home) (not create-home?) system?
|
||||
(directory-exists? home))
|
||||
(let* ((pw (getpwnam name))
|
||||
(uid (passwd:uid pw))
|
||||
(gid (passwd:gid pw)))
|
||||
(mkdir-p home)
|
||||
(chown home uid gid)
|
||||
(unless system?
|
||||
(copy-account-skeletons home
|
||||
#:uid uid #:gid gid)))))))
|
||||
|
||||
(for-each ensure-user-home users))
|
||||
|
||||
(define (activate-etc etc)
|
||||
"Install ETC, a directory in the store, as the source of static files for
|
||||
/etc."
|
||||
@@ -313,7 +269,6 @@ they already exist."
|
||||
(false-if-exception (delete-file file)))
|
||||
|
||||
(format #t "populating /etc from ~a...~%" etc)
|
||||
(mkdir-p "/etc")
|
||||
|
||||
;; Create the /etc/ssl -> /run/current-system/profile/etc/ssl symlink. This
|
||||
;; symlink, to a target outside of the store, probably doesn't belong in the
|
||||
@@ -353,13 +308,24 @@ they already exist."
|
||||
;; Place where setuid programs are stored.
|
||||
"/run/setuid-programs")
|
||||
|
||||
(define (link-or-copy source target)
|
||||
"Attempt to make TARGET a hard link to SOURCE; if it fails, fall back to
|
||||
copy SOURCE to TARGET."
|
||||
(catch 'system-error
|
||||
(lambda ()
|
||||
(link source target))
|
||||
(lambda args
|
||||
;; Perhaps SOURCE and TARGET live in a different file system, so copy
|
||||
;; SOURCE.
|
||||
(copy-file source target))))
|
||||
|
||||
(define (activate-setuid-programs programs)
|
||||
"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 prog))))
|
||||
(copy-file prog target)
|
||||
(link-or-copy prog target)
|
||||
(chown target 0 0)
|
||||
(chmod target #o6555)))
|
||||
|
||||
@@ -376,23 +342,10 @@ they already exist."
|
||||
|
||||
(for-each make-setuid-program programs))
|
||||
|
||||
(define (activate-special-files special-files)
|
||||
"Install the files listed in SPECIAL-FILES. Each element of SPECIAL-FILES
|
||||
is a pair where the first element is the name of the special file and the
|
||||
second element is the name it should appear at, such as:
|
||||
|
||||
((\"/bin/sh\" \"/gnu/store/…-bash/bin/sh\")
|
||||
(\"/usr/bin/env\" \"/gnu/store/…-coreutils/bin/env\"))
|
||||
"
|
||||
(define install-special-file
|
||||
(match-lambda
|
||||
((target file)
|
||||
(let ((pivot (string-append target ".new")))
|
||||
(mkdir-p (dirname target))
|
||||
(symlink file pivot)
|
||||
(rename-file pivot target)))))
|
||||
|
||||
(for-each install-special-file special-files))
|
||||
(define (activate-/bin/sh shell)
|
||||
"Change /bin/sh to point to SHELL."
|
||||
(symlink shell "/bin/sh.new")
|
||||
(rename-file "/bin/sh.new" "/bin/sh"))
|
||||
|
||||
(define (activate-modprobe modprobe)
|
||||
"Tell the kernel to use MODPROBE to load modules."
|
||||
|
||||
@@ -1,178 +0,0 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2014, 2015 Mark H Weaver <mhw@netris.org>
|
||||
;;; Copyright © 2016 Jan Nieuwenhuizen <janneke@gnu.org>
|
||||
;;; Copyright © 2016 Manolis Fragkiskos Ragkousis <manolis837@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/>.
|
||||
|
||||
(define-module (gnu build cross-toolchain)
|
||||
#:use-module (guix build utils)
|
||||
#:use-module (guix build gnu-build-system)
|
||||
#:use-module (srfi srfi-1)
|
||||
#:use-module (srfi srfi-26)
|
||||
#:use-module (ice-9 match)
|
||||
#:use-module (ice-9 ftw)
|
||||
#:export (cross-gcc-build-phases))
|
||||
|
||||
;;; Commentary:
|
||||
;;;
|
||||
;;; This module provides tools to build a cross-compiler.
|
||||
;;;
|
||||
;;; Code:
|
||||
|
||||
(define %gcc-include-paths
|
||||
;; Environment variables for header search paths.
|
||||
;; Note: See <http://bugs.gnu.org/22186> for why not 'CPATH'.
|
||||
'("C_INCLUDE_PATH"
|
||||
"CPLUS_INCLUDE_PATH"
|
||||
"OBJC_INCLUDE_PATH"
|
||||
"OBJCPLUS_INCLUDE_PATH"))
|
||||
|
||||
(define %gcc-cross-include-paths
|
||||
;; Search path for target headers when cross-compiling.
|
||||
(map (cut string-append "CROSS_" <>) %gcc-include-paths))
|
||||
|
||||
(define* (make-cross-binutils-visible #:key outputs inputs target
|
||||
#:allow-other-keys)
|
||||
"Create symlinks for 'as', 'nm', and 'ld' in the \"out\" output, under
|
||||
libexec/gcc, so that the cross-GCC can find them."
|
||||
(let* ((out (assoc-ref outputs "out"))
|
||||
(libexec (string-append out "/libexec/gcc/" target))
|
||||
(binutils (string-append (assoc-ref inputs "binutils-cross")
|
||||
"/bin/" target "-"))
|
||||
(wrapper (string-append (assoc-ref inputs "ld-wrapper-cross")
|
||||
"/bin/" target "-ld")))
|
||||
(for-each (lambda (file)
|
||||
(symlink (string-append binutils file)
|
||||
(string-append libexec "/" file)))
|
||||
'("as" "nm"))
|
||||
(symlink wrapper (string-append libexec "/ld"))
|
||||
#t))
|
||||
|
||||
(define* (set-cross-path #:key inputs #:allow-other-keys)
|
||||
"Add the cross kernel headers to CROSS_CPATH, and remove them from
|
||||
C_INCLUDE_PATH et al."
|
||||
(match (assoc-ref inputs "libc")
|
||||
((? string? libc)
|
||||
(let ((kernel (assoc-ref inputs "xkernel-headers")))
|
||||
(define (cross? x)
|
||||
;; Return #t if X is a cross-libc or cross Linux.
|
||||
(or (string-prefix? libc x)
|
||||
(string-prefix? kernel x)))
|
||||
|
||||
(let ((cpath (string-append libc "/include"
|
||||
":" kernel "/include")))
|
||||
(for-each (cut setenv <> cpath)
|
||||
%gcc-cross-include-paths))
|
||||
|
||||
(setenv "CROSS_LIBRARY_PATH"
|
||||
(string-append libc "/lib:" kernel "/lib")) ;for Hurd's libihash
|
||||
|
||||
(for-each (lambda (var)
|
||||
(and=> (getenv var)
|
||||
(lambda (value)
|
||||
(let* ((path (search-path-as-string->list value))
|
||||
(native-path (list->search-path-as-string
|
||||
(remove cross? path) ":")))
|
||||
(setenv var native-path)))))
|
||||
(cons "LIBRARY_PATH" %gcc-include-paths))
|
||||
#t))
|
||||
(#f
|
||||
;; We're building the sans-libc cross-compiler, so nothing to do.
|
||||
#t)))
|
||||
|
||||
(define* (set-cross-path/mingw #:key inputs #:allow-other-keys)
|
||||
"Add the cross MinGW headers to CROSS_C_*_INCLUDE_PATH, and remove them from
|
||||
C_*INCLUDE_PATH."
|
||||
(let ((libc (assoc-ref inputs "libc"))
|
||||
(gcc (assoc-ref inputs "gcc")))
|
||||
(define (cross? x)
|
||||
(and libc (string-prefix? libc x)))
|
||||
|
||||
(define (unpacked-mingw-dir)
|
||||
(match (scandir "." (lambda (name)
|
||||
(string-contains name "mingw-w64")))
|
||||
((mingw-dir)
|
||||
(string-append
|
||||
(getcwd) "/" mingw-dir "/mingw-w64-headers"))))
|
||||
|
||||
(if libc
|
||||
(let ((cpath (string-append libc "/include"
|
||||
":" libc "/i686-w64-mingw32/include")))
|
||||
(for-each (cut setenv <> cpath)
|
||||
%gcc-cross-include-paths))
|
||||
|
||||
;; libc is false, so we are building xgcc-sans-libc.
|
||||
;; Add essential headers from mingw-w64.
|
||||
(let ((mingw-source (assoc-ref inputs "mingw-source")))
|
||||
(system* "tar" "xvf" mingw-source)
|
||||
(let ((mingw-headers (unpacked-mingw-dir)))
|
||||
;; We need _mingw.h which will gets built from _mingw.h.in by
|
||||
;; mingw-w64's configure. We cannot configure mingw-w64 until we
|
||||
;; have xgcc-sans-libc; substitute to the rescue.
|
||||
(copy-file (string-append mingw-headers "/crt/_mingw.h.in")
|
||||
(string-append mingw-headers "/crt/_mingw.h"))
|
||||
|
||||
(substitute* (string-append mingw-headers "/crt/_mingw.h")
|
||||
(("@MINGW_HAS_SECURE_API@")
|
||||
"#define MINGW_HAS_SECURE_API 1"))
|
||||
|
||||
(let ((cpath (string-append mingw-headers "/include"
|
||||
":" mingw-headers "/crt"
|
||||
":" mingw-headers
|
||||
"/defaults/include")))
|
||||
(for-each (cut setenv <> cpath)
|
||||
(cons "CROSS_LIBRARY_PATH"
|
||||
%gcc-cross-include-paths))))))
|
||||
|
||||
(when libc
|
||||
(setenv "CROSS_LIBRARY_PATH"
|
||||
(string-append libc "/lib"
|
||||
":" libc "/i686-w64-mingw32/lib")))
|
||||
|
||||
(setenv "CPP" (string-append gcc "/bin/cpp"))
|
||||
(for-each (lambda (var)
|
||||
(and=> (getenv var)
|
||||
(lambda (value)
|
||||
(let* ((path (search-path-as-string->list
|
||||
value))
|
||||
(native-path (list->search-path-as-string
|
||||
(remove cross? path) ":")))
|
||||
(setenv var native-path)))))
|
||||
(cons "LIBRARY_PATH" %gcc-include-paths))
|
||||
#t))
|
||||
|
||||
(define (install-strip . _)
|
||||
"Install a stripped GCC."
|
||||
;; Unlike our 'strip' phase, this will do the right thing for
|
||||
;; cross-compilers.
|
||||
(zero? (system* "make" "install-strip")))
|
||||
|
||||
(define* (cross-gcc-build-phases target
|
||||
#:optional (phases %standard-phases))
|
||||
"Modify PHASES to include everything needed to build a cross-GCC for TARGET,
|
||||
a target triplet."
|
||||
(modify-phases phases
|
||||
(add-before 'configure 'set-cross-path
|
||||
(if (string-contains target "mingw")
|
||||
set-cross-path/mingw
|
||||
set-cross-path))
|
||||
(add-after 'install 'make-cross-binutils-visible
|
||||
(cut make-cross-binutils-visible #:target target <...>))
|
||||
(replace 'install install-strip)))
|
||||
|
||||
;;; cross-toolchain.scm ends here
|
||||
+184
-467
@@ -1,7 +1,5 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2016, 2017 David Craven <david@craven.ch>
|
||||
;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
|
||||
;;; Copyright © 2014, 2015 Ludovic Courtès <ludo@gnu.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
@@ -19,16 +17,12 @@
|
||||
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
(define-module (gnu build file-systems)
|
||||
#:use-module (gnu system uuid)
|
||||
#:use-module (gnu system file-systems)
|
||||
#:use-module (guix build utils)
|
||||
#:use-module (guix build bournish)
|
||||
#:use-module ((guix build syscalls)
|
||||
#:hide (file-system-type))
|
||||
#:use-module (rnrs io ports)
|
||||
#:use-module (rnrs bytevectors)
|
||||
#:use-module (ice-9 match)
|
||||
#:use-module (ice-9 rdelim)
|
||||
#:use-module (ice-9 format)
|
||||
#:use-module (system foreign)
|
||||
#:autoload (system repl repl) (start-repl)
|
||||
#:use-module (srfi srfi-1)
|
||||
@@ -36,12 +30,16 @@
|
||||
#:export (disk-partitions
|
||||
partition-label-predicate
|
||||
partition-uuid-predicate
|
||||
partition-luks-uuid-predicate
|
||||
find-partition-by-label
|
||||
find-partition-by-uuid
|
||||
find-partition-by-luks-uuid
|
||||
canonicalize-device-spec
|
||||
|
||||
MS_RDONLY
|
||||
MS_NOSUID
|
||||
MS_NODEV
|
||||
MS_NOEXEC
|
||||
MS_BIND
|
||||
MS_MOVE
|
||||
bind-mount
|
||||
|
||||
mount-flags->bit-mask
|
||||
@@ -55,294 +53,95 @@
|
||||
;;;
|
||||
;;; Code:
|
||||
|
||||
;; 'mount' is already defined in the statically linked Guile used for initial
|
||||
;; RAM disks, but in all other cases the (guix build syscalls) module contains
|
||||
;; the mount binding.
|
||||
(eval-when (expand load eval)
|
||||
(unless (defined? 'mount)
|
||||
(module-use! (current-module)
|
||||
(resolve-interface '(guix build syscalls)))))
|
||||
|
||||
;; Linux mount flags, from libc's <sys/mount.h>.
|
||||
(define MS_RDONLY 1)
|
||||
(define MS_NOSUID 2)
|
||||
(define MS_NODEV 4)
|
||||
(define MS_NOEXEC 8)
|
||||
(define MS_REMOUNT 32)
|
||||
(define MS_BIND 4096)
|
||||
(define MS_MOVE 8192)
|
||||
|
||||
(define (bind-mount source target)
|
||||
"Bind-mount SOURCE at TARGET."
|
||||
(mount source target "" MS_BIND))
|
||||
|
||||
(define (seek* fd/port offset whence)
|
||||
"Like 'seek' but return -1 instead of throwing to 'system-error' upon
|
||||
EINVAL. This makes it easier to catch cases like OFFSET being too large for
|
||||
FD/PORT."
|
||||
(catch 'system-error
|
||||
(lambda ()
|
||||
(seek fd/port offset whence))
|
||||
(lambda args
|
||||
(if (= EINVAL (system-error-errno args))
|
||||
-1
|
||||
(apply throw args)))))
|
||||
|
||||
(define (read-superblock device offset size magic?)
|
||||
"Read a superblock of SIZE from OFFSET and DEVICE. Return the raw
|
||||
superblock on success, and #f if no valid superblock was found. MAGIC?
|
||||
takes a bytevector and returns #t when it's a valid superblock."
|
||||
(call-with-input-file device
|
||||
(lambda (port)
|
||||
(and (= offset (seek* port offset SEEK_SET))
|
||||
(let ((block (make-bytevector size)))
|
||||
(match (get-bytevector-n! port block 0 (bytevector-length block))
|
||||
((? eof-object?)
|
||||
#f)
|
||||
((? number? len)
|
||||
(and (= len (bytevector-length block))
|
||||
(and (magic? block)
|
||||
block)))))))))
|
||||
|
||||
(define null-terminated-latin1->string
|
||||
(cut latin1->string <> zero?))
|
||||
|
||||
|
||||
;;;
|
||||
;;; Ext2 file systems.
|
||||
;;;
|
||||
|
||||
;; <http://www.nongnu.org/ext2-doc/ext2.html#DEF-SUPERBLOCK>.
|
||||
;; TODO: Use "packed structs" from Guile-OpenGL or similar.
|
||||
|
||||
(define-syntax %ext2-endianness
|
||||
;; Endianness of ext2 file systems.
|
||||
(identifier-syntax (endianness little)))
|
||||
|
||||
(define (ext2-superblock? sblock)
|
||||
"Return #t when SBLOCK is an ext2 superblock."
|
||||
(let ((magic (bytevector-u16-ref sblock 56 %ext2-endianness)))
|
||||
(= magic #xef53)))
|
||||
;; Offset in bytes of interesting parts of an ext2 superblock. See
|
||||
;; <http://www.nongnu.org/ext2-doc/ext2.html#DEF-SUPERBLOCK>.
|
||||
;; TODO: Use "packed structs" from Guile-OpenGL or similar.
|
||||
(define-syntax %ext2-sblock-magic (identifier-syntax 56))
|
||||
(define-syntax %ext2-sblock-creator-os (identifier-syntax 72))
|
||||
(define-syntax %ext2-sblock-uuid (identifier-syntax 104))
|
||||
(define-syntax %ext2-sblock-volume-name (identifier-syntax 120))
|
||||
|
||||
(define (read-ext2-superblock device)
|
||||
"Return the raw contents of DEVICE's ext2 superblock as a bytevector, or #f
|
||||
if DEVICE does not contain an ext2 file system."
|
||||
(read-superblock device 1024 264 ext2-superblock?))
|
||||
(define %ext2-magic
|
||||
;; The magic bytes that identify an ext2 file system.
|
||||
#xef53)
|
||||
|
||||
(define superblock-size
|
||||
;; Size of the interesting part of an ext2 superblock.
|
||||
264)
|
||||
|
||||
(define block
|
||||
;; The superblock contents.
|
||||
(make-bytevector superblock-size))
|
||||
|
||||
(call-with-input-file device
|
||||
(lambda (port)
|
||||
(seek port 1024 SEEK_SET)
|
||||
|
||||
;; Note: work around <http://bugs.gnu.org/17466>.
|
||||
(and (eqv? superblock-size (get-bytevector-n! port block 0
|
||||
superblock-size))
|
||||
(let ((magic (bytevector-u16-ref block %ext2-sblock-magic
|
||||
%ext2-endianness)))
|
||||
(and (= magic %ext2-magic)
|
||||
block))))))
|
||||
|
||||
(define (ext2-superblock-uuid sblock)
|
||||
"Return the UUID of ext2 superblock SBLOCK as a 16-byte bytevector."
|
||||
(sub-bytevector sblock 104 16))
|
||||
(let ((uuid (make-bytevector 16)))
|
||||
(bytevector-copy! sblock %ext2-sblock-uuid uuid 0 16)
|
||||
uuid))
|
||||
|
||||
(define (ext2-superblock-volume-name sblock)
|
||||
"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)))
|
||||
(let ((bv (make-bytevector 16)))
|
||||
(bytevector-copy! sblock %ext2-sblock-volume-name bv 0 16)
|
||||
|
||||
(define (check-ext2-file-system device)
|
||||
"Return the health of an ext2 file system on DEVICE."
|
||||
(match (status:exit-val
|
||||
(system* "e2fsck" "-v" "-p" "-C" "0" device))
|
||||
(0 'pass)
|
||||
(1 'errors-corrected)
|
||||
(2 'reboot-required)
|
||||
(_ 'fatal-error)))
|
||||
|
||||
|
||||
;;;
|
||||
;;; Btrfs file systems.
|
||||
;;;
|
||||
|
||||
;; <https://btrfs.wiki.kernel.org/index.php/On-disk_Format#Superblock>.
|
||||
|
||||
(define-syntax %btrfs-endianness
|
||||
;; Endianness of btrfs file systems.
|
||||
(identifier-syntax (endianness little)))
|
||||
|
||||
(define (btrfs-superblock? sblock)
|
||||
"Return #t when SBLOCK is a btrfs superblock."
|
||||
(bytevector=? (sub-bytevector sblock 64 8)
|
||||
(string->utf8 "_BHRfS_M")))
|
||||
|
||||
(define (read-btrfs-superblock device)
|
||||
"Return the raw contents of DEVICE's btrfs superblock as a bytevector, or #f
|
||||
if DEVICE does not contain a btrfs file system."
|
||||
(read-superblock device 65536 4096 btrfs-superblock?))
|
||||
|
||||
(define (btrfs-superblock-uuid sblock)
|
||||
"Return the UUID of a btrfs superblock SBLOCK as a 16-byte bytevector."
|
||||
(sub-bytevector sblock 32 16))
|
||||
|
||||
(define (btrfs-superblock-volume-name sblock)
|
||||
"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)
|
||||
"Return the health of a btrfs file system on DEVICE."
|
||||
(match (status:exit-val
|
||||
(system* "btrfs" "device" "scan"))
|
||||
(0 'pass)
|
||||
(_ 'fatal-error)))
|
||||
|
||||
|
||||
;;;
|
||||
;;; FAT32 file systems.
|
||||
;;;
|
||||
|
||||
;; <http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-107.pdf>.
|
||||
|
||||
(define (fat32-superblock? sblock)
|
||||
"Return #t when SBLOCK is a fat32 superblock."
|
||||
(bytevector=? (sub-bytevector sblock 82 8)
|
||||
(string->utf8 "FAT32 ")))
|
||||
|
||||
(define (read-fat32-superblock device)
|
||||
"Return the raw contents of DEVICE's fat32 superblock as a bytevector, or
|
||||
#f if DEVICE does not contain a fat32 file system."
|
||||
(read-superblock device 0 90 fat32-superblock?))
|
||||
|
||||
(define (fat32-superblock-uuid sblock)
|
||||
"Return the Volume ID of a fat superblock SBLOCK as a 4-byte bytevector."
|
||||
(sub-bytevector sblock 67 4))
|
||||
|
||||
(define (fat32-superblock-volume-name sblock)
|
||||
"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)
|
||||
"Return the health of a fat file system on DEVICE."
|
||||
(match (status:exit-val
|
||||
(system* "fsck.vfat" "-v" "-a" device))
|
||||
(0 'pass)
|
||||
(1 'errors-corrected)
|
||||
(_ 'fatal-error)))
|
||||
|
||||
|
||||
;;;
|
||||
;;; FAT16 file systems.
|
||||
;;;
|
||||
|
||||
(define (fat16-superblock? sblock)
|
||||
"Return #t when SBLOCK is a fat16 boot record."
|
||||
(bytevector=? (sub-bytevector sblock 54 8)
|
||||
(string->utf8 "FAT16 ")))
|
||||
|
||||
(define (read-fat16-superblock device)
|
||||
"Return the raw contents of DEVICE's fat16 superblock as a bytevector, or
|
||||
#f if DEVICE does not contain a fat16 file system."
|
||||
(read-superblock device 0 62 fat16-superblock?))
|
||||
|
||||
(define (fat16-superblock-uuid sblock)
|
||||
"Return the Volume ID of a fat superblock SBLOCK as a 4-byte bytevector."
|
||||
(sub-bytevector sblock 39 4))
|
||||
|
||||
(define (fat16-superblock-volume-name sblock)
|
||||
"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))
|
||||
|
||||
|
||||
;;;
|
||||
;;; ISO9660 file systems.
|
||||
;;;
|
||||
|
||||
;; <http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-119.pdf>.
|
||||
|
||||
(define (iso9660-superblock? sblock)
|
||||
"Return #t when SBLOCK is an iso9660 volume descriptor."
|
||||
(bytevector=? (sub-bytevector sblock 1 6)
|
||||
;; Note: "\x01" is the volume descriptor format version
|
||||
(string->utf8 "CD001\x01")))
|
||||
|
||||
(define (read-iso9660-primary-volume-descriptor device offset)
|
||||
"Find and read the first primary volume descriptor, starting at OFFSET.
|
||||
Return #f if not found."
|
||||
(let* ((sblock (read-superblock device offset 2048 iso9660-superblock?))
|
||||
(type-code (if sblock
|
||||
(bytevector-u8-ref sblock 0)
|
||||
(error (format #f
|
||||
"Could not read ISO9660 primary
|
||||
volume descriptor from ~s"
|
||||
device)))))
|
||||
(match type-code
|
||||
(255 #f) ; Volume Descriptor Set Terminator.
|
||||
(1 sblock) ; Primary Volume Descriptor
|
||||
(_ (read-iso9660-primary-volume-descriptor device (+ offset 2048))))))
|
||||
|
||||
(define (read-iso9660-superblock device)
|
||||
"Return the raw contents of DEVICE's iso9660 primary volume descriptor
|
||||
as a bytevector, or #f if DEVICE does not contain an iso9660 file system."
|
||||
;; Start reading at sector 16.
|
||||
;; Since we are not sure that the device contains an ISO9660 filesystem,
|
||||
;; we have to find that out first.
|
||||
(if (read-superblock device (* 2048 16) 2048 iso9660-superblock?)
|
||||
(read-iso9660-primary-volume-descriptor device (* 2048 16))
|
||||
#f)) ; Device does not contain an iso9660 filesystem.
|
||||
|
||||
(define (iso9660-superblock-uuid sblock)
|
||||
"Return the modification time of an iso9660 primary volume descriptor
|
||||
SBLOCK as a bytevector. If that's not set, returns the creation time."
|
||||
;; Drops GMT offset for compatibility with Grub, blkid and /dev/disk/by-uuid.
|
||||
;; Compare Grub: "2014-12-02-19-30-23-00".
|
||||
;; Compare blkid result: "2014-12-02-19-30-23-00".
|
||||
;; Compare /dev/disk/by-uuid entry: "2014-12-02-19-30-23-00".
|
||||
(let* ((creation-time (sub-bytevector sblock 813 17))
|
||||
(modification-time (sub-bytevector sblock 830 17))
|
||||
(unset-time (make-bytevector 17 0))
|
||||
(time (if (bytevector=? unset-time modification-time)
|
||||
creation-time
|
||||
modification-time)))
|
||||
(sub-bytevector time 0 16))) ; strips GMT offset.
|
||||
|
||||
(define (iso9660-superblock-volume-name sblock)
|
||||
"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))
|
||||
|
||||
|
||||
;;;
|
||||
;;; LUKS encrypted devices.
|
||||
;;;
|
||||
|
||||
;; The LUKS header format is described in "LUKS On-Disk Format Specification":
|
||||
;; <https://gitlab.com/cryptsetup/cryptsetup/wikis/Specification>. We follow
|
||||
;; version 1.2.1 of this document.
|
||||
|
||||
(define-syntax %luks-endianness
|
||||
;; Endianness of LUKS headers.
|
||||
(identifier-syntax (endianness big)))
|
||||
|
||||
(define (luks-superblock? sblock)
|
||||
"Return #t when SBLOCK is a luks superblock."
|
||||
(define %luks-magic
|
||||
;; The 'LUKS_MAGIC' constant.
|
||||
(u8-list->bytevector (append (map char->integer (string->list "LUKS"))
|
||||
(list #xba #xbe))))
|
||||
(let ((magic (sub-bytevector sblock 0 6))
|
||||
(version (bytevector-u16-ref sblock 6 %luks-endianness)))
|
||||
(and (bytevector=? magic %luks-magic)
|
||||
(= version 1))))
|
||||
|
||||
(define (read-luks-header file)
|
||||
"Read a LUKS header from FILE. Return the raw header on success, and #f if
|
||||
not valid header was found."
|
||||
;; Size in bytes of the LUKS header, including key slots.
|
||||
(read-superblock file 0 592 luks-superblock?))
|
||||
|
||||
(define (luks-header-uuid header)
|
||||
"Return the LUKS UUID from HEADER, as a 16-byte bytevector."
|
||||
;; 40 bytes are reserved for the UUID, but in practice, it contains the 36
|
||||
;; bytes of its ASCII representation.
|
||||
(let ((uuid (sub-bytevector header 168 36)))
|
||||
(string->uuid (utf8->string uuid))))
|
||||
|
||||
|
||||
;;;
|
||||
;;; Partition lookup.
|
||||
;;;
|
||||
;; This is a Latin-1, nul-terminated string.
|
||||
(let ((bytes (take-while (negate zero?) (bytevector->u8-list bv))))
|
||||
(if (null? bytes)
|
||||
#f
|
||||
(list->string (map integer->char bytes))))))
|
||||
|
||||
(define (disk-partitions)
|
||||
"Return the list of device names corresponding to valid disk partitions."
|
||||
(define (partition? name major minor)
|
||||
;; grub-mkrescue does some funny things for EFI support which
|
||||
;; makes it a lot more difficult than one would expect to support
|
||||
;; booting an ISO-9660 image from an USB flash drive.
|
||||
;; For example there's a buggy (too small) hidden partition in it
|
||||
;; which Linux mounts and then proceeds to fail while trying to
|
||||
;; fall off the edge.
|
||||
;; In any case, partition tables are supposed to be optional so
|
||||
;; here we allow checking entire disks for file systems, too.
|
||||
(> major 2)) ;ignore RAM disks and floppy disks
|
||||
(define (partition? major minor)
|
||||
(let ((marker (format #f "/sys/dev/block/~a:~a/partition" major minor)))
|
||||
(catch 'system-error
|
||||
(lambda ()
|
||||
(not (zero? (call-with-input-file marker read))))
|
||||
(lambda args
|
||||
(if (= ENOENT (system-error-errno args))
|
||||
#f
|
||||
(apply throw args))))))
|
||||
|
||||
(call-with-input-file "/proc/partitions"
|
||||
(lambda (port)
|
||||
@@ -359,120 +158,76 @@ not valid header was found."
|
||||
(match (string-tokenize line)
|
||||
(((= string->number major) (= string->number minor)
|
||||
blocks name)
|
||||
(if (partition? name major minor)
|
||||
(if (partition? major minor)
|
||||
(loop (cons name parts))
|
||||
(loop parts))))))))))
|
||||
|
||||
(define (ENOENT-safe proc)
|
||||
"Wrap the one-argument PROC such that ENOENT errors are caught and lead to a
|
||||
warning and #f as the result."
|
||||
(lambda (device)
|
||||
(catch 'system-error
|
||||
(lambda ()
|
||||
(proc device))
|
||||
(lambda args
|
||||
;; When running on the hand-made /dev,
|
||||
;; 'disk-partitions' could return partitions for which
|
||||
;; we have no /dev node. Handle that gracefully.
|
||||
(let ((errno (system-error-errno args)))
|
||||
(cond ((= ENOENT errno)
|
||||
(format (current-error-port)
|
||||
"warning: device '~a' not found~%" device)
|
||||
#f)
|
||||
((= ENOMEDIUM errno) ;for removable media
|
||||
#f)
|
||||
((= EIO errno) ;unreadable hardware like audio CDs
|
||||
(format (current-error-port)
|
||||
"warning: failed to read from device '~a'~%" device)
|
||||
#f)
|
||||
(else
|
||||
(apply throw args))))))))
|
||||
(define (read-ext2-superblock* device)
|
||||
"Like 'read-ext2-superblock', but return #f when DEVICE does not exist
|
||||
instead of throwing an exception."
|
||||
(catch 'system-error
|
||||
(lambda ()
|
||||
(read-ext2-superblock device))
|
||||
(lambda args
|
||||
;; When running on the hand-made /dev,
|
||||
;; 'disk-partitions' could return partitions for which
|
||||
;; we have no /dev node. Handle that gracefully.
|
||||
(if (= ENOENT (system-error-errno args))
|
||||
(begin
|
||||
(format (current-error-port)
|
||||
"warning: device '~a' not found~%" device)
|
||||
#f)
|
||||
(apply throw args)))))
|
||||
|
||||
(define (partition-field-reader read field)
|
||||
"Return a procedure that takes a device and returns the value of a FIELD in
|
||||
the partition superblock or #f."
|
||||
(let ((read (ENOENT-safe read)))
|
||||
(lambda (device)
|
||||
(let ((sblock (read device)))
|
||||
(and sblock
|
||||
(field sblock))))))
|
||||
|
||||
(define (read-partition-field device partition-field-readers)
|
||||
"Returns the value of a FIELD in the partition superblock of DEVICE or #f. It
|
||||
takes a list of PARTITION-FIELD-READERS and returns the result of the first
|
||||
partition field reader that returned a value."
|
||||
(match (filter-map (cut apply <> (list device)) partition-field-readers)
|
||||
((field . _) field)
|
||||
(_ #f)))
|
||||
|
||||
(define %partition-label-readers
|
||||
(list (partition-field-reader read-iso9660-superblock
|
||||
iso9660-superblock-volume-name)
|
||||
(partition-field-reader read-ext2-superblock
|
||||
ext2-superblock-volume-name)
|
||||
(partition-field-reader read-btrfs-superblock
|
||||
btrfs-superblock-volume-name)
|
||||
(partition-field-reader read-fat32-superblock
|
||||
fat32-superblock-volume-name)
|
||||
(partition-field-reader read-fat16-superblock
|
||||
fat16-superblock-volume-name)))
|
||||
|
||||
(define %partition-uuid-readers
|
||||
(list (partition-field-reader read-iso9660-superblock
|
||||
iso9660-superblock-uuid)
|
||||
(partition-field-reader read-ext2-superblock
|
||||
ext2-superblock-uuid)
|
||||
(partition-field-reader read-btrfs-superblock
|
||||
btrfs-superblock-uuid)
|
||||
(partition-field-reader read-fat32-superblock
|
||||
fat32-superblock-uuid)
|
||||
(partition-field-reader read-fat16-superblock
|
||||
fat16-superblock-uuid)))
|
||||
|
||||
(define read-partition-label
|
||||
(cut read-partition-field <> %partition-label-readers))
|
||||
|
||||
(define read-partition-uuid
|
||||
(cut read-partition-field <> %partition-uuid-readers))
|
||||
|
||||
(define (partition-predicate reader =)
|
||||
"Return a predicate that returns true if the FIELD of partition header that
|
||||
was READ is = to the given value."
|
||||
(define (partition-predicate field =)
|
||||
"Return a predicate that returns true if the FIELD of an ext2 superblock is
|
||||
= to the given value."
|
||||
(lambda (expected)
|
||||
(lambda (device)
|
||||
(let ((actual (reader device)))
|
||||
(and actual
|
||||
(= actual expected))))))
|
||||
"Return a procedure that, when applied to a partition name such as \"sda1\",
|
||||
returns #t if that partition's volume name is LABEL."
|
||||
(lambda (part)
|
||||
(let* ((device (string-append "/dev/" part))
|
||||
(sblock (read-ext2-superblock* device)))
|
||||
(and sblock
|
||||
(let ((actual (field sblock)))
|
||||
(and actual
|
||||
(= actual expected))))))))
|
||||
|
||||
(define partition-label-predicate
|
||||
(partition-predicate read-partition-label string=?))
|
||||
(partition-predicate ext2-superblock-volume-name string=?))
|
||||
|
||||
(define partition-uuid-predicate
|
||||
(partition-predicate read-partition-uuid uuid=?))
|
||||
(partition-predicate ext2-superblock-uuid bytevector=?))
|
||||
|
||||
(define luks-partition-uuid-predicate
|
||||
(partition-predicate
|
||||
(partition-field-reader read-luks-header luks-header-uuid)
|
||||
uuid=?))
|
||||
|
||||
(define (find-partition predicate)
|
||||
"Return the first partition found that matches PREDICATE, or #f if none
|
||||
(define (find-partition-by-label label)
|
||||
"Return the first partition found whose volume name is LABEL, or #f if none
|
||||
were found."
|
||||
(lambda (expected)
|
||||
(find (predicate expected)
|
||||
(map (cut string-append "/dev/" <>)
|
||||
(disk-partitions)))))
|
||||
(and=> (find (partition-label-predicate label)
|
||||
(disk-partitions))
|
||||
(cut string-append "/dev/" <>)))
|
||||
|
||||
(define find-partition-by-label
|
||||
(find-partition partition-label-predicate))
|
||||
(define (find-partition-by-uuid uuid)
|
||||
"Return the first partition whose unique identifier is UUID (a bytevector),
|
||||
or #f if none was found."
|
||||
(and=> (find (partition-uuid-predicate uuid)
|
||||
(disk-partitions))
|
||||
(cut string-append "/dev/" <>)))
|
||||
|
||||
(define find-partition-by-uuid
|
||||
(find-partition partition-uuid-predicate))
|
||||
(define-syntax %network-byte-order
|
||||
(identifier-syntax (endianness big)))
|
||||
|
||||
(define find-partition-by-luks-uuid
|
||||
(find-partition luks-partition-uuid-predicate))
|
||||
(define (uuid->string uuid)
|
||||
"Convert UUID, a 16-byte bytevector, to its string representation, something
|
||||
like \"6b700d61-5550-48a1-874c-a3d86998990e\"."
|
||||
;; See <https://tools.ietf.org/html/rfc4122>.
|
||||
(let ((time-low (bytevector-uint-ref uuid 0 %network-byte-order 4))
|
||||
(time-mid (bytevector-uint-ref uuid 4 %network-byte-order 2))
|
||||
(time-hi (bytevector-uint-ref uuid 6 %network-byte-order 2))
|
||||
(clock-seq (bytevector-uint-ref uuid 8 %network-byte-order 2))
|
||||
(node (bytevector-uint-ref uuid 10 %network-byte-order 6)))
|
||||
(format #f "~8,'0x-~4,'0x-~4,'0x-~4,'0x-~12,'0x"
|
||||
time-low time-mid time-hi clock-seq node)))
|
||||
|
||||
|
||||
(define* (canonicalize-device-spec spec #:optional (title 'any))
|
||||
"Return the device name corresponding to SPEC. TITLE is a symbol, one of
|
||||
the following:
|
||||
@@ -481,7 +236,8 @@ the following:
|
||||
\"/dev/sda1\";
|
||||
• 'label', in which case SPEC is known to designate a partition label--e.g.,
|
||||
\"my-root-part\";
|
||||
• 'uuid', in which case SPEC must be a UUID designating a partition;
|
||||
• 'uuid', in which case SPEC must be a UUID (a 16-byte bytevector)
|
||||
designating a partition;
|
||||
• 'any', in which case SPEC can be anything.
|
||||
"
|
||||
(define max-trials
|
||||
@@ -495,12 +251,9 @@ the following:
|
||||
;; The realm of canonicalization.
|
||||
(if (eq? title 'any)
|
||||
(if (string? spec)
|
||||
;; The "--root=SPEC" kernel command-line option always provides a
|
||||
;; string, but the string can represent a device, a UUID, or a
|
||||
;; label. So check for all three.
|
||||
(cond ((string-prefix? "/" spec) 'device)
|
||||
((string->uuid spec) 'uuid)
|
||||
(else 'label))
|
||||
(if (string-prefix? "/" spec)
|
||||
'device
|
||||
'label)
|
||||
'uuid)
|
||||
title))
|
||||
|
||||
@@ -526,47 +279,31 @@ the following:
|
||||
;; Resolve the label.
|
||||
(resolve find-partition-by-label spec identity))
|
||||
((uuid)
|
||||
(resolve find-partition-by-uuid
|
||||
(cond ((string? spec)
|
||||
(string->uuid spec))
|
||||
((uuid? spec)
|
||||
(uuid-bytevector spec))
|
||||
(else spec))
|
||||
uuid->string))
|
||||
(resolve find-partition-by-uuid spec uuid->string))
|
||||
(else
|
||||
(error "unknown device title" title))))
|
||||
|
||||
(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)
|
||||
((string-prefix? "btrfs" type) check-btrfs-file-system)
|
||||
((string-suffix? "fat" type) check-fat-file-system)
|
||||
(else #f)))
|
||||
(define fsck
|
||||
(string-append "fsck." type))
|
||||
|
||||
(if check-procedure
|
||||
(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; spawning Bourne-like REPL~%"
|
||||
device)
|
||||
(start-repl %bournish-language)))
|
||||
(format (current-error-port)
|
||||
"No file system check procedure for ~a; skipping~%"
|
||||
device)))
|
||||
(let ((status (system* fsck "-v" "-p" "-C" "0" device)))
|
||||
(match (status:exit-val status)
|
||||
(0
|
||||
#t)
|
||||
(1
|
||||
(format (current-error-port) "'~a' corrected errors on ~a; continuing~%"
|
||||
fsck device))
|
||||
(2
|
||||
(format (current-error-port) "'~a' corrected errors on ~a; rebooting~%"
|
||||
fsck device)
|
||||
(sleep 3)
|
||||
(reboot))
|
||||
(code
|
||||
(format (current-error-port) "'~a' exited with code ~a on ~a; spawning REPL~%"
|
||||
fsck code device)
|
||||
(start-repl)))))
|
||||
|
||||
(define (mount-flags->bit-mask flags)
|
||||
"Return the number suitable for the 'flags' argument of 'mount' that
|
||||
@@ -586,63 +323,43 @@ corresponds to the symbols listed in FLAGS."
|
||||
(()
|
||||
0))))
|
||||
|
||||
(define* (mount-file-system fs #:key (root "/root"))
|
||||
"Mount the file system described by FS, a <file-system> object, under ROOT.
|
||||
(define (regular-file? file-name)
|
||||
"Return #t if FILE-NAME is a regular file."
|
||||
(eq? (stat:type (stat file-name)) 'regular))
|
||||
|
||||
(define* (mount-file-system spec #:key (root "/root"))
|
||||
"Mount the file system described by SPEC under ROOT. SPEC must have the
|
||||
form:
|
||||
|
||||
(DEVICE TITLE MOUNT-POINT TYPE (FLAGS ...) OPTIONS CHECK?)
|
||||
|
||||
DEVICE, MOUNT-POINT, and TYPE must be strings; OPTIONS can be a string or #f;
|
||||
FLAGS must be a list of symbols. CHECK? is a Boolean indicating whether to
|
||||
run a file system check."
|
||||
(match spec
|
||||
((source title mount-point type (flags ...) options check?)
|
||||
(let ((source (canonicalize-device-spec source title))
|
||||
(mount-point (string-append root "/" mount-point))
|
||||
(flags (mount-flags->bit-mask flags)))
|
||||
(when check?
|
||||
(check-file-system source type))
|
||||
|
||||
(define (mount-nfs source mount-point type flags options)
|
||||
(let* ((idx (string-rindex source #\:))
|
||||
(host-part (string-take source idx))
|
||||
;; Strip [] from around host if present
|
||||
(host (match (string-split host-part (string->char-set "[]"))
|
||||
(("" h "") h)
|
||||
((h) h)))
|
||||
(aa (match (getaddrinfo host "nfs") ((x . _) x)))
|
||||
(sa (addrinfo:addr aa))
|
||||
(inet-addr (inet-ntop (sockaddr:fam sa)
|
||||
(sockaddr:addr sa))))
|
||||
;; Create the mount point. Most of the time this is a directory, but
|
||||
;; in the case of a bind mount, a regular file may be needed.
|
||||
(if (and (= MS_BIND (logand flags MS_BIND))
|
||||
(regular-file? source))
|
||||
(unless (file-exists? mount-point)
|
||||
(mkdir-p (dirname mount-point))
|
||||
(call-with-output-file mount-point (const #t)))
|
||||
(mkdir-p mount-point))
|
||||
|
||||
;; Mounting an NFS file system requires passing the address
|
||||
;; of the server in the addr= option
|
||||
(mount source mount-point type flags
|
||||
(string-append "addr="
|
||||
inet-addr
|
||||
(if options
|
||||
(string-append "," options)
|
||||
"")))))
|
||||
(let ((type (file-system-type fs))
|
||||
(options (file-system-options fs))
|
||||
(source (canonicalize-device-spec (file-system-device fs)
|
||||
(file-system-title fs)))
|
||||
(mount-point (string-append root "/"
|
||||
(file-system-mount-point fs)))
|
||||
(flags (mount-flags->bit-mask (file-system-flags fs))))
|
||||
(when (file-system-check? fs)
|
||||
(check-file-system source type))
|
||||
(mount source mount-point type flags options)
|
||||
|
||||
;; Create the mount point. Most of the time this is a directory, but
|
||||
;; in the case of a bind mount, a regular file or socket may be needed.
|
||||
(if (and (= MS_BIND (logand flags MS_BIND))
|
||||
(not (file-is-directory? source)))
|
||||
(unless (file-exists? mount-point)
|
||||
(mkdir-p (dirname mount-point))
|
||||
(call-with-output-file mount-point (const #t)))
|
||||
(mkdir-p mount-point))
|
||||
|
||||
(cond
|
||||
((string-prefix? "nfs" type)
|
||||
(mount-nfs source mount-point type flags options))
|
||||
(else
|
||||
(mount source mount-point type flags options)))
|
||||
|
||||
;; For read-only bind mounts, an extra remount is needed, as per
|
||||
;; <http://lwn.net/Articles/281157/>, which still applies to Linux 4.0.
|
||||
(when (and (= MS_BIND (logand flags MS_BIND))
|
||||
(= MS_RDONLY (logand flags MS_RDONLY)))
|
||||
(let ((flags (logior MS_BIND MS_REMOUNT MS_RDONLY)))
|
||||
(mount source mount-point type flags #f)))))
|
||||
;; For read-only bind mounts, an extra remount is needed, as per
|
||||
;; <http://lwn.net/Articles/281157/>, which still applies to Linux 4.0.
|
||||
(when (and (= MS_BIND (logand flags MS_BIND))
|
||||
(= MS_RDONLY (logand flags MS_RDONLY)))
|
||||
(let ((flags (logior MS_BIND MS_REMOUNT MS_RDONLY)))
|
||||
(mount source mount-point type flags #f)))))))
|
||||
|
||||
;;; file-systems.scm ends here
|
||||
|
||||
+31
-33
@@ -1,6 +1,5 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2016 Chris Marusich <cmmarusich@gmail.com>
|
||||
;;; Copyright © 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
@@ -22,8 +21,7 @@
|
||||
#:use-module (guix build store-copy)
|
||||
#:use-module (srfi srfi-26)
|
||||
#:use-module (ice-9 match)
|
||||
#:export (install-boot-config
|
||||
evaluate-populate-directive
|
||||
#:export (install-grub
|
||||
populate-root-file-system
|
||||
reset-timestamps
|
||||
register-closure
|
||||
@@ -38,18 +36,27 @@
|
||||
;;;
|
||||
;;; Code:
|
||||
|
||||
(define (install-boot-config bootcfg bootcfg-location mount-point)
|
||||
"Atomically copy BOOTCFG into BOOTCFG-LOCATION on the MOUNT-POINT. Note
|
||||
that the caller must make sure that BOOTCFG is registered as a GC root so
|
||||
that the fonts, background images, etc. referred to by BOOTCFG are not GC'd."
|
||||
(let* ((target (string-append mount-point bootcfg-location))
|
||||
(define* (install-grub grub.cfg device mount-point)
|
||||
"Install GRUB with GRUB.CFG on DEVICE, which is assumed to be mounted on
|
||||
MOUNT-POINT.
|
||||
|
||||
Note that the caller must make sure that GRUB.CFG is registered as a GC root
|
||||
so that the fonts, background images, etc. referred to by GRUB.CFG are not
|
||||
GC'd."
|
||||
(let* ((target (string-append mount-point "/boot/grub/grub.cfg"))
|
||||
(pivot (string-append target ".new")))
|
||||
(mkdir-p (dirname target))
|
||||
|
||||
;; Copy BOOTCFG instead of just symlinking it, because symlinks won't
|
||||
;; Copy GRUB.CFG instead of just symlinking it, because symlinks won't
|
||||
;; work when /boot is on a separate partition. Do that atomically.
|
||||
(copy-file bootcfg pivot)
|
||||
(rename-file pivot target)))
|
||||
(copy-file grub.cfg pivot)
|
||||
(rename-file pivot target)
|
||||
|
||||
(unless (zero? (system* "grub-install" "--no-floppy"
|
||||
"--boot-directory"
|
||||
(string-append mount-point "/boot")
|
||||
device))
|
||||
(error "failed to install GRUB"))))
|
||||
|
||||
(define (evaluate-populate-directive directive target)
|
||||
"Evaluate DIRECTIVE, an sexp describing a file or directory to create under
|
||||
@@ -96,7 +103,7 @@ STORE."
|
||||
(directory ,store 0 30000 #o1775)
|
||||
|
||||
(directory "/etc")
|
||||
(directory "/var/log") ; for shepherd
|
||||
(directory "/var/log") ; for dmd
|
||||
(directory "/var/guix/gcroots")
|
||||
(directory "/var/empty") ; for no-login accounts
|
||||
(directory "/var/db") ; for dhclient, etc.
|
||||
@@ -111,10 +118,6 @@ STORE."
|
||||
("/var/guix/gcroots/booted-system" -> "/run/booted-system")
|
||||
("/var/guix/gcroots/current-system" -> "/run/current-system")
|
||||
|
||||
;; XXX: 'guix-register' creates this symlink with a wrong target, so
|
||||
;; create it upfront to be sure.
|
||||
("/var/guix/gcroots/profiles" -> "/var/guix/profiles")
|
||||
|
||||
(directory "/bin")
|
||||
(directory "/tmp" 0 0 #o1777) ; sticky bit
|
||||
(directory "/var/tmp" 0 0 #o1777)
|
||||
@@ -156,7 +159,7 @@ as created and modified at the Epoch."
|
||||
;; read-only store.
|
||||
(unless (eq? (stat:type s) 'symlink)
|
||||
(utime file 0 0 0 0))))
|
||||
(find-files directory #:directories? #t)))
|
||||
(find-files directory "")))
|
||||
|
||||
(define* (register-closure store closure
|
||||
#:key (deduplicate? #t))
|
||||
@@ -173,16 +176,13 @@ rest of STORE."
|
||||
|
||||
(define* (populate-single-profile-directory directory
|
||||
#:key profile closure
|
||||
deduplicate?
|
||||
register?)
|
||||
deduplicate?)
|
||||
"Populate DIRECTORY with a store containing PROFILE, whose closure is given
|
||||
in the file called CLOSURE (as generated by #:references-graphs.) DIRECTORY
|
||||
is initialized to contain a single profile under /root pointing to PROFILE.
|
||||
When REGISTER? is true, initialize DIRECTORY/var/guix/db to reflect the
|
||||
contents of the store; DEDUPLICATE? determines whether to deduplicate files in
|
||||
the store.
|
||||
DEDUPLICATE? determines whether to deduplicate files in the store.
|
||||
|
||||
This is used to create the self-contained tarballs with 'guix pack'."
|
||||
This is used to create the self-contained Guix tarball."
|
||||
(define (scope file)
|
||||
(string-append directory "/" file))
|
||||
|
||||
@@ -197,16 +197,14 @@ This is used to create the self-contained tarballs with 'guix pack'."
|
||||
|
||||
;; Populate the store.
|
||||
(populate-store (list closure) directory)
|
||||
(register-closure (canonicalize-path directory) closure
|
||||
#:deduplicate? deduplicate?)
|
||||
|
||||
(when register?
|
||||
(register-closure (canonicalize-path directory) closure
|
||||
#:deduplicate? deduplicate?)
|
||||
|
||||
;; XXX: 'guix-register' registers profiles as GC roots but the symlink
|
||||
;; target uses $TMPDIR. Fix that.
|
||||
(delete-file (scope "/var/guix/gcroots/profiles"))
|
||||
(symlink* "/var/guix/profiles"
|
||||
"/var/guix/gcroots/profiles"))
|
||||
;; XXX: 'guix-register' registers profiles as GC roots but the symlink
|
||||
;; target uses $TMPDIR. Fix that.
|
||||
(delete-file (scope "/var/guix/gcroots/profiles"))
|
||||
(symlink* "/var/guix/profiles"
|
||||
"/var/guix/gcroots/profiles")
|
||||
|
||||
;; Make root's profile, which makes it a GC root.
|
||||
(mkdir-p* %root-profile)
|
||||
|
||||
+40
-24
@@ -1,6 +1,5 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
|
||||
;;; Copyright © 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
@@ -21,16 +20,14 @@
|
||||
#:use-module (rnrs io ports)
|
||||
#:use-module (system repl error-handling)
|
||||
#:autoload (system repl repl) (start-repl)
|
||||
#:autoload (system base compile) (compile-file)
|
||||
#:use-module (srfi srfi-1)
|
||||
#:use-module (srfi srfi-26)
|
||||
#:use-module (ice-9 match)
|
||||
#:use-module (ice-9 ftw)
|
||||
#:use-module (guix build utils)
|
||||
#:use-module ((guix build syscalls)
|
||||
#:hide (file-system-type))
|
||||
#:use-module (gnu build linux-modules)
|
||||
#:use-module (gnu build file-systems)
|
||||
#:use-module (gnu system file-systems)
|
||||
#:export (mount-essential-file-systems
|
||||
linux-command-line
|
||||
find-long-option
|
||||
@@ -240,10 +237,20 @@ the last argument of `mknod'."
|
||||
(filter-map string->number (scandir "/proc")))))
|
||||
|
||||
(define* (mount-root-file-system root type
|
||||
#:key volatile-root?)
|
||||
#:key volatile-root? (unionfs "unionfs"))
|
||||
"Mount the root file system of type TYPE at device ROOT. If VOLATILE-ROOT?
|
||||
is true, mount ROOT read-only and make it a overlay with a writable tmpfs
|
||||
using the kernel build-in overlayfs."
|
||||
is true, mount ROOT read-only and make it a union with a writable tmpfs using
|
||||
UNIONFS."
|
||||
(define (mark-as-not-killable pid)
|
||||
;; Tell the 'user-processes' dmd service that PID must be kept alive when
|
||||
;; shutting down.
|
||||
(mkdir-p "/root/etc/dmd")
|
||||
(let ((port (open-file "/root/etc/dmd/do-not-kill" "a")))
|
||||
(chmod port #o600)
|
||||
(write pid port)
|
||||
(newline port)
|
||||
(close-port port)))
|
||||
|
||||
(if volatile-root?
|
||||
(begin
|
||||
(mkdir-p "/real-root")
|
||||
@@ -251,17 +258,24 @@ using the kernel build-in overlayfs."
|
||||
(mkdir-p "/rw-root")
|
||||
(mount "none" "/rw-root" "tmpfs")
|
||||
|
||||
;; Create the upperdir and the workdir of the overlayfs
|
||||
(mkdir-p "/rw-root/upper")
|
||||
(mkdir-p "/rw-root/work")
|
||||
|
||||
;; We want read-write /dev nodes.
|
||||
(mkdir-p "/rw-root/upper/dev")
|
||||
(mount "none" "/rw-root/upper/dev" "devtmpfs")
|
||||
(mkdir-p "/rw-root/dev")
|
||||
(mount "none" "/rw-root/dev" "devtmpfs")
|
||||
|
||||
;; Make /root an overlay of the tmpfs and the actual root.
|
||||
(mount "none" "/root" "overlay" 0
|
||||
"lowerdir=/real-root,upperdir=/rw-root/upper,workdir=/rw-root/work"))
|
||||
;; Make /root a union of the tmpfs and the actual root. Use
|
||||
;; 'max_files' to set a high RLIMIT_NOFILE for the unionfs process
|
||||
;; itself. Failing to do that, we quickly run out of file
|
||||
;; descriptors; see <http://bugs.gnu.org/17827>.
|
||||
(unless (zero? (system* unionfs "-o"
|
||||
"cow,allow_other,use_ino,suid,dev,max_files=65536"
|
||||
"/rw-root=RW:/real-root=RO"
|
||||
"/root"))
|
||||
(error "unionfs failed"))
|
||||
|
||||
;; Make sure unionfs remains alive till the end. Because
|
||||
;; 'fuse_daemonize' doesn't tell the PID of the forked daemon, we
|
||||
;; have to resort to 'pidof' here.
|
||||
(mark-as-not-killable (pidof unionfs)))
|
||||
(begin
|
||||
(check-file-system root type)
|
||||
(mount root "/root" type)))
|
||||
@@ -269,7 +283,6 @@ using the kernel build-in overlayfs."
|
||||
;; Make sure /root/etc/mtab is a symlink to /proc/self/mounts.
|
||||
(false-if-exception
|
||||
(delete-file "/root/etc/mtab"))
|
||||
(mkdir-p "/root/etc")
|
||||
(symlink "/proc/self/mounts" "/root/etc/mtab"))
|
||||
|
||||
(define (switch-root root)
|
||||
@@ -334,17 +347,19 @@ supports kernel command-line options '--load', '--root', and '--repl'.
|
||||
Mount the root file system, specified by the '--root' command-line argument,
|
||||
if any.
|
||||
|
||||
MOUNTS must be a list of <file-system> objects.
|
||||
MOUNTS must be a list suitable for 'mount-file-system'.
|
||||
|
||||
When VOLATILE-ROOT? is true, the root file system is writable but any changes
|
||||
to it are lost."
|
||||
(define (root-mount-point? fs)
|
||||
(string=? (file-system-mount-point fs) "/"))
|
||||
(define root-mount-point?
|
||||
(match-lambda
|
||||
((device _ "/" _ ...) #t)
|
||||
(_ #f)))
|
||||
|
||||
(define root-fs-type
|
||||
(or (any (lambda (fs)
|
||||
(and (root-mount-point? fs)
|
||||
(file-system-type fs)))
|
||||
(or (any (match-lambda
|
||||
((device _ "/" type _ ...) type)
|
||||
(_ #f))
|
||||
mounts)
|
||||
"ext4"))
|
||||
|
||||
@@ -366,6 +381,7 @@ to it are lost."
|
||||
(start-repl))
|
||||
|
||||
(display "loading kernel modules...\n")
|
||||
(current-module-debugging-port (current-output-port))
|
||||
(for-each (cut load-linux-module* <>
|
||||
#:lookup-module lookup-module)
|
||||
(map lookup-module linux-modules))
|
||||
|
||||
+41
-114
@@ -1,6 +1,5 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2015 David Thompson <davet@gnu.org>
|
||||
;;; Copyright © 2017 Ludovic Courtès <ludo@gnu.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
@@ -20,37 +19,15 @@
|
||||
(define-module (gnu build linux-container)
|
||||
#:use-module (ice-9 format)
|
||||
#:use-module (ice-9 match)
|
||||
#:use-module (ice-9 rdelim)
|
||||
#:use-module (srfi srfi-98)
|
||||
#:use-module (guix utils)
|
||||
#:use-module (guix build utils)
|
||||
#:use-module (guix build syscalls)
|
||||
#:use-module (gnu system file-systems) ;<file-system>
|
||||
#:use-module ((gnu build file-systems) #:select (mount-file-system))
|
||||
#:export (user-namespace-supported?
|
||||
unprivileged-user-namespace-supported?
|
||||
setgroups-supported?
|
||||
%namespaces
|
||||
#:export (%namespaces
|
||||
run-container
|
||||
call-with-container
|
||||
container-excursion
|
||||
container-excursion*))
|
||||
|
||||
(define (user-namespace-supported?)
|
||||
"Return #t if user namespaces are supported on this system."
|
||||
(file-exists? "/proc/self/ns/user"))
|
||||
|
||||
(define (unprivileged-user-namespace-supported?)
|
||||
"Return #t if user namespaces can be created by unprivileged users."
|
||||
(let ((userns-file "/proc/sys/kernel/unprivileged_userns_clone"))
|
||||
(if (file-exists? userns-file)
|
||||
(eqv? #\1 (call-with-input-file userns-file read-char))
|
||||
#t)))
|
||||
|
||||
(define (setgroups-supported?)
|
||||
"Return #t if the setgroups proc file, introduced in Linux-libre 3.19,
|
||||
exists."
|
||||
(file-exists? "/proc/self/setgroups"))
|
||||
container-excursion))
|
||||
|
||||
(define %namespaces
|
||||
'(mnt pid ipc uts user net))
|
||||
@@ -75,9 +52,8 @@ exists."
|
||||
;; specification:
|
||||
;; https://raw.githubusercontent.com/docker/libcontainer/master/SPEC.md
|
||||
(define* (mount-file-systems root mounts #:key mount-/sys? mount-/proc?)
|
||||
"Mount the essential file systems and the those in MOUNTS, a list of
|
||||
<file-system> objects, relative to ROOT; then make ROOT the new root directory
|
||||
for the process."
|
||||
"Mount the essential file systems and the those in the MOUNTS list relative
|
||||
to ROOT, then make ROOT the new root directory for the process."
|
||||
(define (scope dir)
|
||||
(string-append root dir))
|
||||
|
||||
@@ -130,19 +106,13 @@ for the process."
|
||||
"/dev/fuse"))
|
||||
|
||||
;; Setup the container's /dev/console by bind mounting the pseudo-terminal
|
||||
;; associated with standard input when there is one.
|
||||
(let* ((in (current-input-port))
|
||||
(tty (catch 'system-error
|
||||
(lambda ()
|
||||
;; This call throws if IN does not correspond to a tty.
|
||||
;; This is more reliable than 'isatty?'.
|
||||
(ttyname in))
|
||||
(const #f)))
|
||||
(console (scope "/dev/console")))
|
||||
(when tty
|
||||
;; associated with standard input.
|
||||
(let ((in (current-input-port))
|
||||
(console (scope "/dev/console")))
|
||||
(when (isatty? in)
|
||||
(touch console)
|
||||
(chmod console #o600)
|
||||
(bind-mount tty console)))
|
||||
(bind-mount (ttyname in) console)))
|
||||
|
||||
;; Setup standard input/output/error.
|
||||
(symlink "/proc/self/fd" (scope "/dev/fd"))
|
||||
@@ -151,8 +121,8 @@ for the process."
|
||||
(symlink "/proc/self/fd/2" (scope "/dev/stderr"))
|
||||
|
||||
;; Mount user-specified file systems.
|
||||
(for-each (lambda (file-system)
|
||||
(mount-file-system file-system #:root root))
|
||||
(for-each (lambda (spec)
|
||||
(mount-file-system spec #:root root))
|
||||
mounts)
|
||||
|
||||
;; Jail the process inside the container's root file system.
|
||||
@@ -195,7 +165,7 @@ host user identifiers to map into the user namespace."
|
||||
"Return the number suitable for the 'flags' argument of 'clone' that
|
||||
corresponds to the symbols in NAMESPACES."
|
||||
;; Use the same flags as fork(3) in addition to the namespace flags.
|
||||
(apply logior SIGCHLD
|
||||
(apply logior SIGCHLD CLONE_CHILD_CLEARTID CLONE_CHILD_SETTID
|
||||
(map (match-lambda
|
||||
('mnt CLONE_NEWNS)
|
||||
('uts CLONE_NEWUTS)
|
||||
@@ -207,69 +177,46 @@ corresponds to the symbols in NAMESPACES."
|
||||
|
||||
(define (run-container root mounts namespaces host-uids thunk)
|
||||
"Run THUNK in a new container process and return its PID. ROOT specifies
|
||||
the root directory for the container. MOUNTS is a list of <file-system>
|
||||
objects that specify file systems to mount inside the container. NAMESPACES
|
||||
the root directory for the container. MOUNTS is a list of file system specs
|
||||
that specify the mapping of host file systems into the container. NAMESPACES
|
||||
is a list of symbols that correspond to the possible Linux namespaces: mnt,
|
||||
ipc, uts, user, and net. HOST-UIDS specifies the number of
|
||||
host user identifiers to map into the user 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 SOCK_STREAM 0)
|
||||
((child . parent)
|
||||
(match (pipe)
|
||||
((in . out)
|
||||
(let ((flags (namespaces->bit-mask namespaces)))
|
||||
(match (clone flags)
|
||||
(0
|
||||
(call-with-clean-exit
|
||||
(lambda ()
|
||||
(close-port parent)
|
||||
(close out)
|
||||
;; Wait for parent to set things up.
|
||||
(match (read child)
|
||||
('ready
|
||||
(purify-environment)
|
||||
(when (memq 'mnt namespaces)
|
||||
(catch #t
|
||||
(lambda ()
|
||||
(mount-file-systems root mounts
|
||||
#:mount-/proc? (memq 'pid namespaces)
|
||||
#:mount-/sys? (memq 'net
|
||||
namespaces)))
|
||||
(lambda args
|
||||
;; Forward the exception to the parent process.
|
||||
;; FIXME: SRFI-35 conditions and non-trivial objects
|
||||
;; cannot be 'read' so they shouldn't be written as is.
|
||||
(write args child)
|
||||
(primitive-exit 3))))
|
||||
;; TODO: Manage capabilities.
|
||||
(write 'ready child)
|
||||
(close-port child)
|
||||
(thunk))
|
||||
(_ ;parent died or something
|
||||
(primitive-exit 2))))))
|
||||
(read in)
|
||||
(close in)
|
||||
(purify-environment)
|
||||
(when (memq 'mnt namespaces)
|
||||
(mount-file-systems root mounts
|
||||
#:mount-/proc? (memq 'pid namespaces)
|
||||
#:mount-/sys? (memq 'net namespaces)))
|
||||
;; TODO: Manage capabilities.
|
||||
(thunk))))
|
||||
(pid
|
||||
(close-port child)
|
||||
(when (memq 'user namespaces)
|
||||
(initialize-user-namespace pid host-uids))
|
||||
;; TODO: Initialize cgroups.
|
||||
(write 'ready parent)
|
||||
(newline parent)
|
||||
|
||||
;; Check whether the child process' setup phase succeeded.
|
||||
(let ((message (read parent)))
|
||||
(close-port parent)
|
||||
(match message
|
||||
('ready ;success
|
||||
pid)
|
||||
(((? symbol? key) args ...) ;exception
|
||||
(apply throw key args))
|
||||
(_ ;unexpected termination
|
||||
#f)))))))))
|
||||
(close in)
|
||||
(write 'ready out)
|
||||
(close out)
|
||||
pid))))))
|
||||
|
||||
(define* (call-with-container mounts thunk #:key (namespaces %namespaces)
|
||||
(host-uids 1))
|
||||
"Run THUNK in a new container process and return its exit status.
|
||||
MOUNTS is a list of <file-system> objects that specify file systems to mount
|
||||
inside the container. NAMESPACES is a list of symbols corresponding to
|
||||
MOUNTS is a list of file system specs that specify the mapping of host file
|
||||
systems into the container. NAMESPACES is a list of symbols corresponding to
|
||||
the identifiers for Linux namespaces: mnt, ipc, uts, pid, user, and net. By
|
||||
default, all namespaces are used. HOST-UIDS is the number of host user
|
||||
identifiers to map into the container's user namespace, if there is one. By
|
||||
@@ -303,17 +250,15 @@ return the exit status."
|
||||
(call-with-clean-exit
|
||||
(lambda ()
|
||||
(for-each (lambda (ns)
|
||||
(let ((source (namespace-file (getpid) ns))
|
||||
(target (namespace-file pid ns)))
|
||||
;; Joining the namespace that the process already
|
||||
;; belongs to would throw an error so avoid that.
|
||||
;; XXX: This /proc interface leads to TOCTTOU.
|
||||
(unless (string=? (readlink source) (readlink target))
|
||||
(call-with-input-file source
|
||||
(lambda (current-ns-port)
|
||||
(call-with-input-file target
|
||||
(lambda (new-ns-port)
|
||||
(setns (fileno new-ns-port) 0))))))))
|
||||
(call-with-input-file (namespace-file (getpid) ns)
|
||||
(lambda (current-ns-port)
|
||||
(call-with-input-file (namespace-file pid ns)
|
||||
(lambda (new-ns-port)
|
||||
;; Joining the namespace that the process
|
||||
;; already belongs to would throw an error.
|
||||
(unless (= (port->fdes current-ns-port)
|
||||
(port->fdes new-ns-port))
|
||||
(setns (port->fdes new-ns-port) 0)))))))
|
||||
;; It's important that the user namespace is joined first,
|
||||
;; so that the user will have the privileges to join the
|
||||
;; other namespaces. Furthermore, it's important that the
|
||||
@@ -327,21 +272,3 @@ return the exit status."
|
||||
(match (waitpid pid)
|
||||
((_ . status)
|
||||
(status:exit-val status))))))
|
||||
|
||||
(define (container-excursion* pid thunk)
|
||||
"Like 'container-excursion', but return the return value of THUNK."
|
||||
(match (pipe)
|
||||
((in . out)
|
||||
(match (container-excursion pid
|
||||
(lambda ()
|
||||
(close-port in)
|
||||
(write (thunk) out)))
|
||||
(0
|
||||
(close-port out)
|
||||
(let ((result (read in)))
|
||||
(close-port in)
|
||||
result))
|
||||
(_ ;maybe PID died already
|
||||
(close-port out)
|
||||
(close-port in)
|
||||
#f)))))
|
||||
|
||||
+20
-70
@@ -1,6 +1,5 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2014, 2016 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
|
||||
;;; Copyright © 2014 Ludovic Courtès <ludo@gnu.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
@@ -19,7 +18,6 @@
|
||||
|
||||
(define-module (gnu build linux-modules)
|
||||
#:use-module (guix elf)
|
||||
#:use-module (guix build syscalls)
|
||||
#:use-module (rnrs io ports)
|
||||
#:use-module (rnrs bytevectors)
|
||||
#:use-module (srfi srfi-1)
|
||||
@@ -98,21 +96,6 @@ contains module names, not actual file names."
|
||||
name
|
||||
(dot-ko name)))
|
||||
|
||||
(define (normalize-module-name module)
|
||||
"Return the \"canonical\" name for MODULE, replacing hyphens with
|
||||
underscores."
|
||||
;; See 'modname_normalize' in libkmod.
|
||||
(string-map (lambda (chr)
|
||||
(case chr
|
||||
((#\-) #\_)
|
||||
(else chr)))
|
||||
module))
|
||||
|
||||
(define (file-name->module-name file)
|
||||
"Return the module name corresponding to FILE, stripping the trailing '.ko'
|
||||
and normalizing it."
|
||||
(normalize-module-name (basename file ".ko")))
|
||||
|
||||
(define* (recursive-module-dependencies files
|
||||
#:key (lookup-module dot-ko))
|
||||
"Return the topologically-sorted list of file names of the modules depended
|
||||
@@ -147,24 +130,6 @@ LOOKUP-MODULE to the module name."
|
||||
(((modules . _) ...)
|
||||
modules))))
|
||||
|
||||
(define (module-black-list)
|
||||
"Return the black list of modules that must not be loaded. This black list
|
||||
is specified using 'modprobe.blacklist=MODULE1,MODULE2,...' on the kernel
|
||||
command line; it is honored by libkmod for users that pass
|
||||
'KMOD_PROBE_APPLY_BLACKLIST', which includes 'modprobe --use-blacklist' and
|
||||
udev."
|
||||
(define parameter
|
||||
"modprobe.blacklist=")
|
||||
|
||||
(let ((command (call-with-input-file "/proc/cmdline"
|
||||
get-string-all)))
|
||||
(append-map (lambda (arg)
|
||||
(if (string-prefix? parameter arg)
|
||||
(string-tokenize (string-drop arg (string-length parameter))
|
||||
%not-comma)
|
||||
'()))
|
||||
(string-tokenize command))))
|
||||
|
||||
(define (module-loaded? module)
|
||||
"Return #t if MODULE is already loaded. MODULE must be a Linux module name,
|
||||
not a file name."
|
||||
@@ -173,44 +138,29 @@ not a file name."
|
||||
(define* (load-linux-module* file
|
||||
#:key
|
||||
(recursive? #t)
|
||||
(lookup-module dot-ko)
|
||||
(black-list (module-black-list)))
|
||||
"Load Linux module from FILE, the name of a '.ko' file; return true on
|
||||
success, false otherwise. When RECURSIVE? is true, load its dependencies
|
||||
first (à la 'modprobe'.) The actual files containing modules depended on are
|
||||
obtained by calling LOOKUP-MODULE with the module name. Modules whose name
|
||||
appears in BLACK-LIST are not loaded."
|
||||
(lookup-module dot-ko))
|
||||
"Load Linux module from FILE, the name of a `.ko' file. When RECURSIVE? is
|
||||
true, load its dependencies first (à la 'modprobe'.) The actual files
|
||||
containing modules depended on are obtained by calling LOOKUP-MODULE with the
|
||||
module name."
|
||||
(define (slurp module)
|
||||
;; TODO: Use 'finit_module' to reduce memory usage.
|
||||
;; TODO: Use 'mmap' to reduce memory usage.
|
||||
(call-with-input-file file get-bytevector-all))
|
||||
|
||||
(define (black-listed? module)
|
||||
(let ((result (member module black-list)))
|
||||
(when result
|
||||
(format (current-module-debugging-port)
|
||||
"not loading module '~a' because it's black-listed~%"
|
||||
module))
|
||||
result))
|
||||
(when recursive?
|
||||
(for-each (cut load-linux-module* <> #:lookup-module lookup-module)
|
||||
(map lookup-module (module-dependencies file))))
|
||||
|
||||
(define (load-dependencies file)
|
||||
(let ((dependencies (module-dependencies file)))
|
||||
(every (cut load-linux-module* <> #:lookup-module lookup-module)
|
||||
(map lookup-module dependencies))))
|
||||
(format (current-module-debugging-port)
|
||||
"loading Linux module from '~a'...~%" file)
|
||||
|
||||
(and (not (black-listed? (file-name->module-name file)))
|
||||
(or (not recursive?)
|
||||
(load-dependencies file))
|
||||
(begin
|
||||
(format (current-module-debugging-port)
|
||||
"loading Linux module from '~a'...~%" file)
|
||||
|
||||
(catch 'system-error
|
||||
(lambda ()
|
||||
(load-linux-module (slurp file)))
|
||||
(lambda args
|
||||
;; If this module was already loaded and we're in modprobe style, ignore
|
||||
;; the error.
|
||||
(or (and recursive? (= EEXIST (system-error-errno args)))
|
||||
(apply throw args)))))))
|
||||
(catch 'system-error
|
||||
(lambda ()
|
||||
(load-linux-module (slurp file)))
|
||||
(lambda args
|
||||
;; If this module was already loaded and we're in modprobe style, ignore
|
||||
;; the error.
|
||||
(unless (and recursive? (= EEXIST (system-error-errno args)))
|
||||
(apply throw args)))))
|
||||
|
||||
;;; linux-modules.scm ends here
|
||||
|
||||
@@ -1,301 +0,0 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2016, 2017 Ludovic Courtès <ludo@gnu.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
;;; GNU Guix is free software; you can redistribute it and/or modify it
|
||||
;;; under the terms of the GNU General Public License as published by
|
||||
;;; the Free Software Foundation; either version 3 of the License, or (at
|
||||
;;; your option) any later version.
|
||||
;;;
|
||||
;;; GNU Guix is distributed in the hope that it will be useful, but
|
||||
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;;; GNU General Public License for more details.
|
||||
;;;
|
||||
;;; You should have received a copy of the GNU General Public License
|
||||
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
(define-module (gnu build marionette)
|
||||
#:use-module (srfi srfi-9)
|
||||
#:use-module (srfi srfi-26)
|
||||
#:use-module (rnrs io ports)
|
||||
#:use-module (ice-9 match)
|
||||
#:use-module (ice-9 popen)
|
||||
#:export (marionette?
|
||||
make-marionette
|
||||
marionette-eval
|
||||
wait-for-file
|
||||
marionette-control
|
||||
marionette-screen-text
|
||||
wait-for-screen-text
|
||||
%qwerty-us-keystrokes
|
||||
marionette-type))
|
||||
|
||||
;;; Commentary:
|
||||
;;;
|
||||
;;; Instrumentation tools for QEMU virtual machines (VMs). A "marionette" is
|
||||
;;; essentially a VM (a QEMU instance) with its monitor connected to a
|
||||
;;; Unix-domain socket, and with a REPL inside the guest listening on a
|
||||
;;; virtual console, which is itself connected to the host via a Unix-domain
|
||||
;;; socket--these are the marionette's strings, connecting it to the almighty
|
||||
;;; puppeteer.
|
||||
;;;
|
||||
;;; Code:
|
||||
|
||||
(define-record-type <marionette>
|
||||
(marionette command pid monitor repl)
|
||||
marionette?
|
||||
(command marionette-command) ;list of strings
|
||||
(pid marionette-pid) ;integer
|
||||
(monitor marionette-monitor) ;port
|
||||
(repl %marionette-repl)) ;promise of a port
|
||||
|
||||
(define-syntax-rule (marionette-repl marionette)
|
||||
(force (%marionette-repl marionette)))
|
||||
|
||||
(define* (wait-for-monitor-prompt port #:key (quiet? #t))
|
||||
"Read from PORT until we have seen all of QEMU's monitor prompt. When
|
||||
QUIET? is false, the monitor's output is written to the current output port."
|
||||
(define full-prompt
|
||||
(string->list "(qemu) "))
|
||||
|
||||
(let loop ((prompt full-prompt)
|
||||
(matches '())
|
||||
(prefix '()))
|
||||
(match prompt
|
||||
(()
|
||||
;; It's useful to set QUIET? so we don't display the echo of our own
|
||||
;; commands.
|
||||
(unless quiet?
|
||||
(for-each (lambda (line)
|
||||
(format #t "qemu monitor: ~a~%" line))
|
||||
(string-tokenize (list->string (reverse prefix))
|
||||
(char-set-complement (char-set #\newline))))))
|
||||
((chr rest ...)
|
||||
(let ((read (read-char port)))
|
||||
(cond ((eqv? read chr)
|
||||
(loop rest (cons read matches) prefix))
|
||||
((eof-object? read)
|
||||
(error "EOF while waiting for QEMU monitor prompt"
|
||||
(list->string (reverse prefix))))
|
||||
(else
|
||||
(loop full-prompt
|
||||
'()
|
||||
(cons read (append matches prefix))))))))))
|
||||
|
||||
(define* (make-marionette command
|
||||
#:key (socket-directory "/tmp") (timeout 20))
|
||||
"Return a QEMU marionette--i.e., a virtual machine with open connections to the
|
||||
QEMU monitor and to the guest's backdoor REPL."
|
||||
(define (file->sockaddr file)
|
||||
(make-socket-address AF_UNIX
|
||||
(string-append socket-directory "/" file)))
|
||||
|
||||
(define extra-options
|
||||
(list "-nographic"
|
||||
"-monitor" (string-append "unix:" socket-directory "/monitor")
|
||||
"-chardev" (string-append "socket,id=repl,path=" socket-directory
|
||||
"/repl")
|
||||
"-device" "virtio-serial"
|
||||
"-device" "virtconsole,chardev=repl"))
|
||||
|
||||
(define (accept* port)
|
||||
(match (select (list port) '() (list port) timeout)
|
||||
(((port) () ())
|
||||
(accept port))
|
||||
(_
|
||||
(error "timeout in 'accept'" port))))
|
||||
|
||||
(let ((monitor (socket AF_UNIX SOCK_STREAM 0))
|
||||
(repl (socket AF_UNIX SOCK_STREAM 0)))
|
||||
(bind monitor (file->sockaddr "monitor"))
|
||||
(listen monitor 1)
|
||||
(bind repl (file->sockaddr "repl"))
|
||||
(listen repl 1)
|
||||
|
||||
(match (primitive-fork)
|
||||
(0
|
||||
(catch #t
|
||||
(lambda ()
|
||||
(close monitor)
|
||||
(close repl)
|
||||
(match command
|
||||
((program . args)
|
||||
(apply execl program program
|
||||
(append args extra-options)))))
|
||||
(lambda (key . args)
|
||||
(print-exception (current-error-port)
|
||||
(stack-ref (make-stack #t) 1)
|
||||
key args)
|
||||
(primitive-exit 1))))
|
||||
(pid
|
||||
(format #t "QEMU runs as PID ~a~%" pid)
|
||||
|
||||
(match (accept* monitor)
|
||||
((monitor-conn . _)
|
||||
(display "connected to QEMU's monitor\n")
|
||||
(close-port monitor)
|
||||
(wait-for-monitor-prompt monitor-conn)
|
||||
(display "read QEMU monitor prompt\n")
|
||||
|
||||
(marionette (append command extra-options) pid
|
||||
monitor-conn
|
||||
|
||||
;; The following 'accept' call connects immediately, but
|
||||
;; we don't know whether the guest has connected until
|
||||
;; we actually receive the 'ready' message.
|
||||
(match (accept* repl)
|
||||
((repl-conn . addr)
|
||||
(display "connected to guest REPL\n")
|
||||
(close-port repl)
|
||||
;; Delay reception of the 'ready' message so that the
|
||||
;; caller can already send monitor commands.
|
||||
(delay
|
||||
(match (read repl-conn)
|
||||
('ready
|
||||
(display "marionette is ready\n")
|
||||
repl-conn))))))))))))
|
||||
|
||||
(define (marionette-eval exp marionette)
|
||||
"Evaluate EXP in MARIONETTE's backdoor REPL. Return the result."
|
||||
(match marionette
|
||||
(($ <marionette> command pid monitor (= force repl))
|
||||
(write exp repl)
|
||||
(newline repl)
|
||||
(read repl))))
|
||||
|
||||
(define* (wait-for-file file marionette
|
||||
#:key (timeout 10) (read 'read))
|
||||
"Wait until FILE exists in MARIONETTE; READ its content and return it. If
|
||||
FILE has not shown up after TIMEOUT seconds, raise an error."
|
||||
(match (marionette-eval
|
||||
`(let loop ((i ,timeout))
|
||||
(cond ((file-exists? ,file)
|
||||
(cons 'success (call-with-input-file ,file ,read)))
|
||||
((> i 0)
|
||||
(sleep 1)
|
||||
(loop (- i 1)))
|
||||
(else
|
||||
'failure)))
|
||||
marionette)
|
||||
(('success . result)
|
||||
result)
|
||||
('failure
|
||||
(error "file didn't show up" file))))
|
||||
|
||||
(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-doc)
|
||||
pcsys_monitor\")."
|
||||
(match marionette
|
||||
(($ <marionette> _ _ monitor)
|
||||
(display command monitor)
|
||||
(newline monitor)
|
||||
(wait-for-monitor-prompt monitor))))
|
||||
|
||||
(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"))
|
||||
|
||||
(let ((image (random-file-name)))
|
||||
(dynamic-wind
|
||||
(const #t)
|
||||
(lambda ()
|
||||
(marionette-control (string-append "screendump " image)
|
||||
marionette)
|
||||
|
||||
;; 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 (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."
|
||||
(define start
|
||||
(car (gettimeofday)))
|
||||
|
||||
(define end
|
||||
(+ start timeout))
|
||||
|
||||
(let loop ()
|
||||
(if (> (car (gettimeofday)) end)
|
||||
(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.
|
||||
'((#\newline . "ret")
|
||||
(#\space . "spc")
|
||||
(#\- . "minus")
|
||||
(#\+ . "shift-equal")
|
||||
(#\* . "shift-8")
|
||||
(#\= . "equal")
|
||||
(#\? . "shift-slash")
|
||||
(#\[ . "bracket_left")
|
||||
(#\] . "bracket_right")
|
||||
(#\( . "shift-9")
|
||||
(#\) . "shift-0")
|
||||
(#\/ . "slash")
|
||||
(#\< . "less")
|
||||
(#\> . "shift-less")
|
||||
(#\. . "dot")
|
||||
(#\, . "comma")
|
||||
(#\; . "semicolon")
|
||||
(#\' . "apostrophe")
|
||||
(#\" . "shift-apostrophe")
|
||||
(#\` . "grave_accent")
|
||||
(#\bs . "backspace")
|
||||
(#\tab . "tab")))
|
||||
|
||||
(define (character->keystroke chr keystrokes)
|
||||
"Return the keystroke for CHR according to the keyboard layout defined by
|
||||
KEYSTROKES."
|
||||
(if (char-set-contains? char-set:upper-case chr)
|
||||
(string-append "shift-" (string (char-downcase chr)))
|
||||
(or (assoc-ref keystrokes chr)
|
||||
(string chr))))
|
||||
|
||||
(define* (string->keystroke-commands str
|
||||
#:optional
|
||||
(keystrokes
|
||||
%qwerty-us-keystrokes))
|
||||
"Return a list of QEMU monitor commands to send the keystrokes corresponding
|
||||
to STR. KEYSTROKES is an alist specifying a mapping from characters to
|
||||
keystrokes."
|
||||
(string-fold-right (lambda (chr result)
|
||||
(cons (string-append
|
||||
"sendkey "
|
||||
(character->keystroke chr keystrokes))
|
||||
result))
|
||||
'()
|
||||
str))
|
||||
|
||||
(define* (marionette-type str marionette
|
||||
#:key (keystrokes %qwerty-us-keystrokes))
|
||||
"Type STR on MARIONETTE's keyboard, using the KEYSTROKES alist to map characters
|
||||
to actual keystrokes."
|
||||
(for-each (cut marionette-control <> marionette)
|
||||
(string->keystroke-commands str keystrokes)))
|
||||
|
||||
;;; marionette.scm ends here
|
||||
@@ -1,179 +0,0 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2017 Ludovic Courtès <ludo@gnu.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
;;; GNU Guix is free software; you can redistribute it and/or modify it
|
||||
;;; under the terms of the GNU General Public License as published by
|
||||
;;; the Free Software Foundation; either version 3 of the License, or (at
|
||||
;;; your option) any later version.
|
||||
;;;
|
||||
;;; GNU Guix is distributed in the hope that it will be useful, but
|
||||
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;;; GNU General Public License for more details.
|
||||
;;;
|
||||
;;; You should have received a copy of the GNU General Public License
|
||||
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
(define-module (gnu build shepherd)
|
||||
#:use-module (gnu system file-systems)
|
||||
#:use-module (gnu build linux-container)
|
||||
#:use-module (guix build utils)
|
||||
#:use-module (srfi srfi-1)
|
||||
#:use-module (ice-9 match)
|
||||
#:export (make-forkexec-constructor/container))
|
||||
|
||||
;;; Commentary:
|
||||
;;;
|
||||
;;; This module provides extensions to the GNU Shepherd. In particular, it
|
||||
;;; provides a helper to start services in a container.
|
||||
;;;
|
||||
;;; Code:
|
||||
|
||||
(define (clean-up file)
|
||||
(when file
|
||||
(catch 'system-error
|
||||
(lambda ()
|
||||
(delete-file file))
|
||||
(lambda args
|
||||
(unless (= ENOENT (system-error-errno args))
|
||||
(apply throw args))))))
|
||||
|
||||
(define-syntax-rule (catch-system-error exp)
|
||||
(catch 'system-error
|
||||
(lambda ()
|
||||
exp)
|
||||
(const #f)))
|
||||
|
||||
(define (default-namespaces args)
|
||||
;; Most daemons are here to talk to the network, and most of them expect to
|
||||
;; run under a non-zero UID.
|
||||
(fold delq %namespaces '(net user)))
|
||||
|
||||
(define* (default-mounts #:key (namespaces (default-namespaces '())))
|
||||
(define (tmpfs directory)
|
||||
(file-system
|
||||
(device "none")
|
||||
(title 'device)
|
||||
(mount-point directory)
|
||||
(type "tmpfs")
|
||||
(check? #f)))
|
||||
|
||||
(define accounts
|
||||
;; This is for processes in the default user namespace but living in a
|
||||
;; different mount namespace, so that they can lookup users.
|
||||
(list (file-system-mapping
|
||||
(source "/etc/passwd") (target source))
|
||||
(file-system-mapping
|
||||
(source "/etc/group") (target source))))
|
||||
|
||||
(define nscd-socket
|
||||
(file-system-mapping
|
||||
(source "/var/run/nscd") (target source)
|
||||
(writable? #t)))
|
||||
|
||||
(append (cons (tmpfs "/tmp") %container-file-systems)
|
||||
(let ((mappings `(,@(if (memq 'net namespaces)
|
||||
'()
|
||||
(cons nscd-socket
|
||||
%network-file-mappings))
|
||||
,@(if (and (memq 'mnt namespaces)
|
||||
(not (memq 'user namespaces)))
|
||||
accounts
|
||||
'())
|
||||
,%store-mapping))) ;XXX: coarse-grain
|
||||
(map file-system-mapping->bind-mount
|
||||
(filter (lambda (mapping)
|
||||
(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) '(read-pid-file exec-command))
|
||||
|
||||
(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 ()
|
||||
(read-pid-file pid-file
|
||||
#:max-delay max-delay)))
|
||||
(#f
|
||||
(catch-system-error (kill pid SIGTERM))
|
||||
#f)
|
||||
((? integer? container-pid)
|
||||
;; XXX: When COMMAND is started in a separate PID namespace, its
|
||||
;; PID is always 1, but that's not what Shepherd needs to know.
|
||||
pid)))
|
||||
|
||||
(define* (make-forkexec-constructor/container command
|
||||
#:key
|
||||
(namespaces
|
||||
(default-namespaces args))
|
||||
(mappings '())
|
||||
(user #f)
|
||||
(group #f)
|
||||
(log-file #f)
|
||||
pid-file
|
||||
(pid-file-timeout 5)
|
||||
(directory "/")
|
||||
(environment-variables
|
||||
(environ))
|
||||
#:rest args)
|
||||
"This is a variant of 'make-forkexec-constructor' that starts COMMAND in
|
||||
NAMESPACES, a list of Linux namespaces such as '(mnt ipc). MAPPINGS is the
|
||||
list of <file-system-mapping> to make in the case of a separate mount
|
||||
namespace, in addition to essential bind-mounts such /proc."
|
||||
(define container-directory
|
||||
(match command
|
||||
((program _ ...)
|
||||
(string-append "/var/run/containers/" (basename program)))))
|
||||
|
||||
(define auto-mappings
|
||||
`(,@(if log-file
|
||||
(list (file-system-mapping
|
||||
(source log-file)
|
||||
(target source)
|
||||
(writable? #t)))
|
||||
'())))
|
||||
|
||||
(define mounts
|
||||
(append (map file-system-mapping->bind-mount
|
||||
(append auto-mappings mappings))
|
||||
(default-mounts #:namespaces namespaces)))
|
||||
|
||||
(lambda args
|
||||
(mkdir-p container-directory)
|
||||
|
||||
(when log-file
|
||||
;; Create LOG-FILE so we can map it in the container.
|
||||
(unless (file-exists? log-file)
|
||||
(call-with-output-file log-file (const #t))))
|
||||
|
||||
(let ((pid (run-container container-directory
|
||||
mounts namespaces 1
|
||||
(lambda ()
|
||||
(mkdir-p "/var/run")
|
||||
(clean-up pid-file)
|
||||
(clean-up log-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
|
||||
#:max-delay pid-file-timeout)
|
||||
(read-pid-file pid-file #:max-delay pid-file-timeout))
|
||||
pid))))
|
||||
|
||||
;; Local Variables:
|
||||
;; eval: (put 'container-excursion* 'scheme-indent-function 1)
|
||||
;; End:
|
||||
|
||||
;;; shepherd.scm ends here
|
||||
@@ -1,71 +0,0 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2016, 2017 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2015 Andy Wingo <wingo@igalia.com>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
;;; GNU Guix is free software; you can redistribute it and/or modify it
|
||||
;;; under the terms of the GNU General Public License as published by
|
||||
;;; the Free Software Foundation; either version 3 of the License, or (at
|
||||
;;; your option) any later version.
|
||||
;;;
|
||||
;;; GNU Guix is distributed in the hope that it will be useful, but
|
||||
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;;; GNU General Public License for more details.
|
||||
;;;
|
||||
;;; You should have received a copy of the GNU General Public License
|
||||
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
(define-module (gnu build svg)
|
||||
#:use-module (srfi srfi-11)
|
||||
#:export (svg->png))
|
||||
|
||||
;; We need Guile-RSVG and Guile-Cairo. Load them lazily, at run time, to
|
||||
;; allow compilation to proceed. See also <http://bugs.gnu.org/12202>.
|
||||
(module-autoload! (current-module)
|
||||
'(rsvg) '(rsvg-handle-new-from-file))
|
||||
(module-autoload! (current-module)
|
||||
'(cairo) '(cairo-image-surface-create))
|
||||
|
||||
(define* (downscaled-surface surface
|
||||
#:key
|
||||
source-width source-height
|
||||
width height)
|
||||
"Return a new rendering context where SURFACE is scaled to WIDTH x HEIGHT."
|
||||
(let ((cr (cairo-create (cairo-image-surface-create 'argb32
|
||||
width height))))
|
||||
(cairo-scale cr (/ width source-width) (/ height source-height))
|
||||
(cairo-set-source-surface cr surface 0 0)
|
||||
(cairo-pattern-set-filter (cairo-get-source cr) 'best)
|
||||
(cairo-rectangle cr 0 0 source-width source-height)
|
||||
(cairo-fill cr)
|
||||
cr))
|
||||
|
||||
(define* (svg->png in-svg out-png
|
||||
#:key width height)
|
||||
"Render the file at IN-SVG as a PNG file in OUT-PNG. When WIDTH and HEIGHT
|
||||
are provided, use them as the dimensions of OUT-PNG; otherwise preserve the
|
||||
dimensions of IN-SVG."
|
||||
(define svg
|
||||
(rsvg-handle-new-from-file in-svg))
|
||||
|
||||
(let-values (((origin-width origin-height em ex)
|
||||
(rsvg-handle-get-dimensions svg)))
|
||||
(let* ((surf (cairo-image-surface-create 'argb32
|
||||
origin-width origin-height))
|
||||
(cr (cairo-create surf)))
|
||||
(rsvg-handle-render-cairo svg cr)
|
||||
(cairo-surface-flush surf)
|
||||
(let ((cr (if (and width height
|
||||
(not (= width origin-width))
|
||||
(not (= height origin-height)))
|
||||
(downscaled-surface surf
|
||||
#:source-width origin-width
|
||||
#:source-height origin-height
|
||||
#:width width
|
||||
#:height height)
|
||||
cr)))
|
||||
(cairo-surface-write-to-png (cairo-get-target cr) out-png)))))
|
||||
|
||||
;;; svg.scm ends here
|
||||
+55
-230
@@ -1,9 +1,5 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2016 Christopher Allan Webber <cwebber@dustycloud.org>
|
||||
;;; Copyright © 2016 Leo Famulari <leo@famulari.name>
|
||||
;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
|
||||
;;; Copyright © 2017 Marius Bakke <mbakke@fastmail.com>
|
||||
;;; Copyright © 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
@@ -23,13 +19,9 @@
|
||||
(define-module (gnu build vm)
|
||||
#:use-module (guix build utils)
|
||||
#:use-module (guix build store-copy)
|
||||
#:use-module (guix build syscalls)
|
||||
#: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 match)
|
||||
#:use-module (ice-9 regex)
|
||||
#:use-module (srfi srfi-1)
|
||||
@@ -45,14 +37,12 @@
|
||||
partition-size
|
||||
partition-file-system
|
||||
partition-label
|
||||
partition-flags
|
||||
partition-bootable?
|
||||
partition-initializer
|
||||
|
||||
estimated-partition-size
|
||||
root-partition-initializer
|
||||
initialize-partition-table
|
||||
initialize-hard-disk
|
||||
make-iso9660-image))
|
||||
initialize-hard-disk))
|
||||
|
||||
;;; Commentary:
|
||||
;;;
|
||||
@@ -63,8 +53,8 @@
|
||||
|
||||
(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 #\-))))
|
||||
(let ((cpu (substring %host-type 0
|
||||
(string-index %host-type #\-))))
|
||||
(string-append "qemu-system-"
|
||||
(if (string-match "^i[3456]86$" cpu)
|
||||
"i386"
|
||||
@@ -75,28 +65,24 @@
|
||||
output
|
||||
(qemu (qemu-command)) (memory-size 512)
|
||||
linux initrd
|
||||
make-disk-image?
|
||||
single-file-output?
|
||||
(disk-image-size (* 100 (expt 2 20)))
|
||||
make-disk-image? (disk-image-size 100)
|
||||
(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.
|
||||
the result to 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.
|
||||
DISK-IMAGE-SIZE MiB 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 image-file
|
||||
(string-append "image." disk-image-format))
|
||||
|
||||
(when make-disk-image?
|
||||
(format #t "creating ~a image of ~,2f MiB...~%"
|
||||
disk-image-format (/ disk-image-size (expt 2 20)))
|
||||
(force-output)
|
||||
(unless (zero? (system* "qemu-img" "create" "-f" disk-image-format
|
||||
output
|
||||
image-file
|
||||
(number->string disk-image-size)))
|
||||
(error "qemu-img failed")))
|
||||
|
||||
@@ -111,7 +97,7 @@ the #:references-graphs parameter of 'derivation'."
|
||||
(_ #f))
|
||||
|
||||
(unless (zero?
|
||||
(apply system* qemu "-nographic" "-no-reboot"
|
||||
(apply system* qemu "-enable-kvm" "-nographic" "-no-reboot"
|
||||
"-m" (number->string memory-size)
|
||||
"-net" "nic,model=virtio"
|
||||
"-virtfs"
|
||||
@@ -125,32 +111,17 @@ the #:references-graphs parameter of 'derivation'."
|
||||
"-initrd" initrd
|
||||
"-append" (string-append "console=ttyS0 --load="
|
||||
builder)
|
||||
(append
|
||||
(if make-disk-image?
|
||||
`("-drive" ,(string-append "file=" output
|
||||
",if=virtio"))
|
||||
'())
|
||||
;; Only enable kvm if we see /dev/kvm exists.
|
||||
;; This allows users without hardware virtualization to still
|
||||
;; use these commands.
|
||||
(if (file-exists? "/dev/kvm")
|
||||
'("-enable-kvm")
|
||||
'()))))
|
||||
(if make-disk-image?
|
||||
`("-drive" ,(string-append "file=" image-file
|
||||
",if=virtio"))
|
||||
'())))
|
||||
(error "qemu failed" qemu))
|
||||
|
||||
;; 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)))))
|
||||
(if make-disk-image?
|
||||
(copy-file image-file output)
|
||||
(begin
|
||||
(mkdir output)
|
||||
(copy-recursively "xchg" output))))
|
||||
|
||||
|
||||
;;;
|
||||
@@ -163,15 +134,20 @@ the #:references-graphs parameter of 'derivation'."
|
||||
(size partition-size)
|
||||
(file-system partition-file-system (default "ext4"))
|
||||
(label partition-label (default #f))
|
||||
(uuid partition-uuid (default #f))
|
||||
(flags partition-flags (default '()))
|
||||
(bootable? partition-bootable? (default #f))
|
||||
(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 (fold2 proc seed1 seed2 lst) ;TODO: factorize
|
||||
"Like `fold', but with a single list and two seeds."
|
||||
(let loop ((result1 seed1)
|
||||
(result2 seed2)
|
||||
(lst lst))
|
||||
(if (null? lst)
|
||||
(values result1 result2)
|
||||
(call-with-values
|
||||
(lambda () (proc (car lst) result1 result2))
|
||||
(lambda (result1 result2)
|
||||
(loop result1 result2 (cdr lst)))))))
|
||||
|
||||
(define* (initialize-partition-table device partitions
|
||||
#:key
|
||||
@@ -185,10 +161,9 @@ actual /dev name based on DEVICE."
|
||||
(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))))
|
||||
(if (partition-bootable? part)
|
||||
`("set" ,(number->string index) "boot" "on")
|
||||
'())))
|
||||
|
||||
(define (options partitions offset)
|
||||
(let loop ((partitions partitions)
|
||||
@@ -207,15 +182,8 @@ actual /dev name based on DEVICE."
|
||||
(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)
|
||||
", "))
|
||||
(format #t "creating partition table with ~a partitions...\n"
|
||||
(length partitions))
|
||||
(unless (zero? (apply system* "parted" "--script"
|
||||
device "mklabel" label-type
|
||||
(options partitions offset)))
|
||||
@@ -236,43 +204,17 @@ actual /dev name based on DEVICE."
|
||||
|
||||
(define MS_BIND 4096) ; <sys/mounts.h> again!
|
||||
|
||||
(define* (create-ext-file-system partition type
|
||||
#:key label uuid)
|
||||
"Create an ext-family filesystem of TYPE on PARTITION. If LABEL is true,
|
||||
use that as the volume name. If UUID is true, use it as the partition UUID."
|
||||
(define* (format-partition partition type
|
||||
#:key label)
|
||||
"Create a file system TYPE on PARTITION. If LABEL is true, use that as the
|
||||
volume name."
|
||||
(format #t "creating ~a partition...\n" type)
|
||||
(unless (zero? (apply system* (string-append "mkfs." type)
|
||||
"-F" partition
|
||||
`(,@(if label
|
||||
`("-L" ,label)
|
||||
'())
|
||||
,@(if uuid
|
||||
`("-U" ,(uuid->string uuid))
|
||||
'()))))
|
||||
(error "failed to create partition")))
|
||||
|
||||
(define* (create-fat-file-system partition
|
||||
#:key label uuid)
|
||||
"Create a FAT filesystem on PARTITION. The number of File Allocation Tables
|
||||
will be determined based on filesystem size. If LABEL is true, use that as the
|
||||
volume name."
|
||||
;; FIXME: UUID is ignored!
|
||||
(format #t "creating FAT partition...\n")
|
||||
(unless (zero? (apply system* "mkfs.fat" partition
|
||||
(if label
|
||||
`("-n" ,label)
|
||||
`("-L" ,label)
|
||||
'())))
|
||||
(error "failed to create FAT partition")))
|
||||
|
||||
(define* (format-partition partition type
|
||||
#:key label uuid)
|
||||
"Create a file system TYPE on PARTITION. If LABEL is true, use that as the
|
||||
volume name."
|
||||
(cond ((string-prefix? "ext" type)
|
||||
(create-ext-file-system partition type #:label label #:uuid uuid))
|
||||
((or (string-prefix? "fat" type) (string= "vfat" type))
|
||||
(create-fat-file-system partition #:label label #:uuid uuid))
|
||||
(else (error "Unsupported file system."))))
|
||||
(error "failed to create partition")))
|
||||
|
||||
(define (initialize-partition partition)
|
||||
"Format PARTITION, a <partition> object with a non-#f 'device' field, mount
|
||||
@@ -280,8 +222,7 @@ 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))
|
||||
#:label (partition-label partition))
|
||||
(mkdir-p target)
|
||||
(mount (partition-device partition) target
|
||||
(partition-file-system partition))
|
||||
@@ -337,108 +278,23 @@ SYSTEM-DIRECTORY is the name of the directory of the 'system' derivation."
|
||||
(unless register-closures?
|
||||
(reset-timestamps target))))
|
||||
|
||||
(define (register-bootcfg-root target bootcfg)
|
||||
"On file system TARGET, register BOOTCFG as a GC root."
|
||||
(define (register-grub.cfg-root target grub.cfg)
|
||||
"On file system TARGET, register GRUB.CFG as a GC root."
|
||||
(let ((directory (string-append target "/var/guix/gcroots")))
|
||||
(mkdir-p directory)
|
||||
(symlink bootcfg (string-append directory "/bootcfg"))))
|
||||
|
||||
(define (install-efi grub esp config-file)
|
||||
"Write a self-contained GRUB EFI loader to the mounted ESP using CONFIG-FILE."
|
||||
(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":
|
||||
;; http://www.uefi.org/sites/default/files/resources/UEFI%20Spec%202_6.pdf
|
||||
(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 (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)
|
||||
|
||||
(mkdir-p efi-directory)
|
||||
(unless (zero? (system* grub-mkstandalone "-O" (car efi-targets)
|
||||
"-o" (string-append efi-directory "/"
|
||||
(cdr efi-targets))
|
||||
;; Graft the configuration file onto the image.
|
||||
(string-append "boot/grub/grub.cfg=" config-file)))
|
||||
(error "failed to create GRUB EFI image"))))
|
||||
|
||||
(define* (make-iso9660-image grub config-file os-drv target
|
||||
#:key (volume-id "GuixSD_image") (volume-uuid #f)
|
||||
register-closures? (closures '()))
|
||||
"Given a GRUB package, creates an iso image as TARGET, using CONFIG-FILE as
|
||||
GRUB configuration and OS-DRV as the stuff in it."
|
||||
(let ((grub-mkrescue (string-append grub "/bin/grub-mkrescue"))
|
||||
(target-store (string-append "/tmp/root" (%store-directory))))
|
||||
(populate-root-file-system os-drv "/tmp/root")
|
||||
|
||||
(mount (%store-directory) target-store "" MS_BIND)
|
||||
|
||||
(when register-closures?
|
||||
(display "registering closures...\n")
|
||||
(for-each (lambda (closure)
|
||||
(register-closure
|
||||
"/tmp/root"
|
||||
(string-append "/xchg/" closure)
|
||||
;; XXX: Using deduplication causes cross device link errors.
|
||||
#:deduplicate? #f))
|
||||
closures))
|
||||
|
||||
(unless (zero? (apply system*
|
||||
`(,grub-mkrescue "-o" ,target
|
||||
,(string-append "boot/grub/grub.cfg=" config-file)
|
||||
,(string-append "gnu/store=" os-drv "/..")
|
||||
"etc=/tmp/root/etc"
|
||||
"var=/tmp/root/var"
|
||||
"run=/tmp/root/run"
|
||||
;; /mnt is used as part of the installation
|
||||
;; process, as the mount point for the target
|
||||
;; filesystem, so create it.
|
||||
"mnt=/tmp/root/mnt"
|
||||
"--"
|
||||
"-volid" ,(string-upcase volume-id)
|
||||
,@(if volume-uuid
|
||||
`("-volume_date" "uuid"
|
||||
,(string-filter (lambda (value)
|
||||
(not (char=? #\- value)))
|
||||
(iso9660-uuid->string
|
||||
volume-uuid)))
|
||||
`()))))
|
||||
(error "failed to create ISO9660 image"))))
|
||||
(symlink grub.cfg (string-append directory "/grub.cfg"))))
|
||||
|
||||
(define* (initialize-hard-disk device
|
||||
#:key
|
||||
bootloader-package
|
||||
bootcfg
|
||||
bootcfg-location
|
||||
bootloader-installer
|
||||
(grub-efi #f)
|
||||
grub.cfg
|
||||
(partitions '()))
|
||||
"Initialize DEVICE as a disk containing all the <partition> objects listed
|
||||
in PARTITIONS, and using BOOTCFG as its bootloader configuration file.
|
||||
in PARTITIONS, and using GRUB.CFG 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))
|
||||
@@ -448,41 +304,10 @@ passing it a directory name where it is mounted."
|
||||
(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))
|
||||
(install-grub grub.cfg device target)
|
||||
|
||||
(when esp
|
||||
;; Mount the ESP somewhere and install GRUB UEFI image.
|
||||
(let ((mount-point (string-append target "/boot/efi"))
|
||||
(grub-config (string-append target "/tmp/grub-standalone.cfg")))
|
||||
(display "mounting EFI system partition...\n")
|
||||
(mkdir-p mount-point)
|
||||
(mount (partition-device esp) mount-point
|
||||
(partition-file-system esp))
|
||||
|
||||
;; Create a tiny configuration file telling the embedded grub
|
||||
;; where to load the real thing.
|
||||
;; XXX This is quite fragile, and can prevent the image from booting
|
||||
;; when there's more than one volume with this label present.
|
||||
;; Reproducible almost-UUIDs could reduce the risk (not eliminate it).
|
||||
(call-with-output-file grub-config
|
||||
(lambda (port)
|
||||
(format port
|
||||
"insmod part_msdos~@
|
||||
search --set=root --label GuixSD_image~@
|
||||
configfile /boot/grub/grub.cfg~%")))
|
||||
|
||||
(display "creating EFI firmware image...")
|
||||
(install-efi grub-efi mount-point grub-config)
|
||||
(display "done.\n")
|
||||
|
||||
(delete-file grub-config)
|
||||
(umount mount-point)))
|
||||
|
||||
;; Register BOOTCFG as a GC root.
|
||||
(register-bootcfg-root target bootcfg)
|
||||
;; Register GRUB.CFG as a GC root.
|
||||
(register-grub.cfg-root target grub.cfg)
|
||||
|
||||
(umount target)))
|
||||
|
||||
|
||||
-1266
File diff suppressed because it is too large
Load Diff
+276
-109
@@ -1,9 +1,7 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2012, 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2013 Mark H Weaver <mhw@netris.org>
|
||||
;;; Copyright © 2014 Eric Bavier <bavier@member.fsf.org>
|
||||
;;; Copyright © 2016, 2017 Alex Kost <alezost@gmail.com>
|
||||
;;; Copyright © 2016 Mathieu Lirzin <mthl@gnu.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
@@ -24,12 +22,10 @@
|
||||
#:use-module (guix packages)
|
||||
#:use-module (guix ui)
|
||||
#:use-module (guix utils)
|
||||
#:use-module (guix discovery)
|
||||
#:use-module (guix memoization)
|
||||
#:use-module ((guix build utils)
|
||||
#:select ((package-name->name+version
|
||||
. hyphen-separated-name->name+version)))
|
||||
#:autoload (guix profiles) (packages->manifest)
|
||||
#:use-module ((guix ftp-client) #:select (ftp-open))
|
||||
#:use-module (guix gnu-maintenance)
|
||||
#:use-module (guix upstream)
|
||||
#:use-module (ice-9 ftw)
|
||||
#:use-module (ice-9 vlist)
|
||||
#:use-module (ice-9 match)
|
||||
#:use-module (srfi srfi-1)
|
||||
@@ -39,11 +35,8 @@
|
||||
#:use-module (srfi srfi-35)
|
||||
#:use-module (srfi srfi-39)
|
||||
#:export (search-patch
|
||||
search-patches
|
||||
search-auxiliary-file
|
||||
search-bootstrap-binary
|
||||
%patch-path
|
||||
%auxiliary-files-path
|
||||
%bootstrap-binaries-path
|
||||
%package-module-path
|
||||
|
||||
@@ -53,9 +46,14 @@
|
||||
find-best-packages-by-name
|
||||
find-newest-available-packages
|
||||
|
||||
package-direct-dependents
|
||||
package-transitive-dependents
|
||||
package-covering-dependents
|
||||
|
||||
check-package-freshness
|
||||
|
||||
specification->package
|
||||
specification->package+output
|
||||
specifications->manifest))
|
||||
specification->package+output))
|
||||
|
||||
;;; Commentary:
|
||||
;;;
|
||||
@@ -64,39 +62,24 @@
|
||||
;;;
|
||||
;;; Code:
|
||||
|
||||
;; By default, we store patches, auxiliary files and bootstrap binaries
|
||||
;; alongside Guile modules. This is so that these extra files can be
|
||||
;; found without requiring a special setup, such as a specific
|
||||
;; installation directory and an extra environment variable. One
|
||||
;; advantage of this setup is that everything just works in an
|
||||
;; auto-compilation setting.
|
||||
;; By default, we store patches and bootstrap binaries alongside Guile
|
||||
;; modules. This is so that these extra files can be found without
|
||||
;; requiring a special setup, such as a specific installation directory
|
||||
;; and an extra environment variable. One advantage of this setup is
|
||||
;; that everything just works in an auto-compilation setting.
|
||||
|
||||
(define %bootstrap-binaries-path
|
||||
(make-parameter
|
||||
(map (cut string-append <> "/gnu/packages/bootstrap")
|
||||
%load-path)))
|
||||
|
||||
(define %auxiliary-files-path
|
||||
(make-parameter
|
||||
(map (cut string-append <> "/gnu/packages/aux-files")
|
||||
%load-path)))
|
||||
|
||||
(define (search-auxiliary-file file-name)
|
||||
"Search the auxiliary FILE-NAME. Return #f if not found."
|
||||
(search-path (%auxiliary-files-path) file-name))
|
||||
|
||||
(define (search-patch file-name)
|
||||
"Search the patch FILE-NAME. Raise an error if not found."
|
||||
(or (search-path (%patch-path) file-name)
|
||||
(raise (condition
|
||||
(&message (message (format #f (G_ "~a: patch not found")
|
||||
(&message (message (format #f (_ "~a: patch not found")
|
||||
file-name)))))))
|
||||
|
||||
(define-syntax-rule (search-patches file-name ...)
|
||||
"Return the list of absolute file names corresponding to each
|
||||
FILE-NAME found in %PATCH-PATH."
|
||||
(list (search-patch file-name) ...))
|
||||
|
||||
(define (search-bootstrap-binary file-name system)
|
||||
"Search the bootstrap binary FILE-NAME for SYSTEM. Raise an error if not
|
||||
found."
|
||||
@@ -105,7 +88,7 @@ found."
|
||||
(raise (condition
|
||||
(&message
|
||||
(message
|
||||
(format #f (G_ "could not find bootstrap binary '~a' \
|
||||
(format #f (_ "could not find bootstrap binary '~a' \
|
||||
for system '~a'")
|
||||
file-name system)))))))
|
||||
|
||||
@@ -140,19 +123,91 @@ for system '~a'")
|
||||
directory))
|
||||
%load-path)))
|
||||
|
||||
(define* (fold-packages proc init
|
||||
#:optional
|
||||
(modules (all-modules (%package-module-path)))
|
||||
#:key (select? (negate hidden-package?)))
|
||||
"Call (PROC PACKAGE RESULT) for each available package defined in one of
|
||||
MODULES that matches SELECT?, using INIT as the initial value of RESULT. It
|
||||
is guaranteed to never traverse the same package twice."
|
||||
(fold-module-public-variables (lambda (object result)
|
||||
(if (and (package? object) (select? object))
|
||||
(proc object result)
|
||||
result))
|
||||
init
|
||||
modules))
|
||||
(define* (scheme-files directory)
|
||||
"Return the list of Scheme files found under DIRECTORY, recursively. The
|
||||
returned list is sorted in alphabetical order."
|
||||
|
||||
;; Sort entries so that 'fold-packages' works in a deterministic fashion
|
||||
;; regardless of details of the underlying file system.
|
||||
(sort (file-system-fold (const #t) ; enter?
|
||||
(lambda (path stat result) ; leaf
|
||||
(if (string-suffix? ".scm" path)
|
||||
(cons path result)
|
||||
result))
|
||||
(lambda (path stat result) ; down
|
||||
result)
|
||||
(lambda (path stat result) ; up
|
||||
result)
|
||||
(const #f) ; skip
|
||||
(lambda (path stat errno result)
|
||||
(warning (_ "cannot access `~a': ~a~%")
|
||||
path (strerror errno))
|
||||
result)
|
||||
'()
|
||||
directory
|
||||
stat)
|
||||
string<?))
|
||||
|
||||
(define file-name->module-name
|
||||
(let ((not-slash (char-set-complement (char-set #\/))))
|
||||
(lambda (file)
|
||||
"Return the module name (a list of symbols) corresponding to FILE."
|
||||
(map string->symbol
|
||||
(string-tokenize (string-drop-right file 4) not-slash)))))
|
||||
|
||||
(define* (package-modules directory #:optional sub-directory)
|
||||
"Return the list of modules that provide packages for the distribution.
|
||||
Optionally, narrow the search to SUB-DIRECTORY."
|
||||
(define prefix-len
|
||||
(string-length directory))
|
||||
|
||||
(filter-map (lambda (file)
|
||||
(let* ((file (substring file prefix-len))
|
||||
(module (file-name->module-name file)))
|
||||
(catch #t
|
||||
(lambda ()
|
||||
(resolve-interface module))
|
||||
(lambda args
|
||||
;; Report the error, but keep going.
|
||||
(warn-about-load-error module args)
|
||||
#f))))
|
||||
(scheme-files (if sub-directory
|
||||
(string-append directory "/" sub-directory)
|
||||
directory))))
|
||||
|
||||
(define* (all-package-modules #:optional (path (%package-module-path)))
|
||||
"Return the list of package modules found in PATH, a list of directories to
|
||||
search."
|
||||
(fold-right (lambda (spec result)
|
||||
(match spec
|
||||
((? string? directory)
|
||||
(append (package-modules directory) result))
|
||||
((directory . sub-directory)
|
||||
(append (package-modules directory sub-directory)
|
||||
result))))
|
||||
'()
|
||||
path))
|
||||
|
||||
(define (fold-packages proc init)
|
||||
"Call (PROC PACKAGE RESULT) for each available package, using INIT as
|
||||
the initial value of RESULT. It is guaranteed to never traverse the
|
||||
same package twice."
|
||||
(identity ; discard second return value
|
||||
(fold2 (lambda (module result seen)
|
||||
(fold2 (lambda (var result seen)
|
||||
(if (and (package? var)
|
||||
(not (vhash-assq var seen)))
|
||||
(values (proc var result)
|
||||
(vhash-consq var #t seen))
|
||||
(values result seen)))
|
||||
result
|
||||
seen
|
||||
(module-map (lambda (sym var)
|
||||
(false-if-exception (variable-ref var)))
|
||||
module)))
|
||||
init
|
||||
vlist-null
|
||||
(all-package-modules))))
|
||||
|
||||
(define find-packages-by-name
|
||||
(let ((packages (delay
|
||||
@@ -174,27 +229,28 @@ decreasing version order."
|
||||
matching)))))
|
||||
|
||||
(define find-newest-available-packages
|
||||
(mlambda ()
|
||||
"Return a vhash keyed by package names, and with
|
||||
(memoize
|
||||
(lambda ()
|
||||
"Return a vhash keyed by package names, and with
|
||||
associated values of the form
|
||||
|
||||
(newest-version newest-package ...)
|
||||
|
||||
where the preferred package is listed first."
|
||||
|
||||
;; FIXME: Currently, the preferred package is whichever one
|
||||
;; was found last by 'fold-packages'. Find a better solution.
|
||||
(fold-packages (lambda (p r)
|
||||
(let ((name (package-name p))
|
||||
(version (package-version p)))
|
||||
(match (vhash-assoc name r)
|
||||
((_ newest-so-far . pkgs)
|
||||
(case (version-compare version newest-so-far)
|
||||
((>) (vhash-cons name `(,version ,p) r))
|
||||
((=) (vhash-cons name `(,version ,p ,@pkgs) r))
|
||||
((<) r)))
|
||||
(#f (vhash-cons name `(,version ,p) r)))))
|
||||
vlist-null)))
|
||||
;; FIXME: Currently, the preferred package is whichever one
|
||||
;; was found last by 'fold-packages'. Find a better solution.
|
||||
(fold-packages (lambda (p r)
|
||||
(let ((name (package-name p))
|
||||
(version (package-version p)))
|
||||
(match (vhash-assoc name r)
|
||||
((_ newest-so-far . pkgs)
|
||||
(case (version-compare version newest-so-far)
|
||||
((>) (vhash-cons name `(,version ,p) r))
|
||||
((=) (vhash-cons name `(,version ,p ,@pkgs) r))
|
||||
((<) r)))
|
||||
(#f (vhash-cons name `(,version ,p) r)))))
|
||||
vlist-null))))
|
||||
|
||||
(define (find-best-packages-by-name name version)
|
||||
"If version is #f, return the list of packages named NAME with the highest
|
||||
@@ -206,6 +262,63 @@ VERSION."
|
||||
((_ version pkgs ...) pkgs)
|
||||
(#f '()))))
|
||||
|
||||
|
||||
(define* (vhash-refq vhash key #:optional (dflt #f))
|
||||
"Look up KEY in the vhash VHASH, and return the value (if any) associated
|
||||
with it. If KEY is not found, return DFLT (or `#f' if no DFLT argument is
|
||||
supplied). Uses `eq?' for equality testing."
|
||||
(or (and=> (vhash-assq key vhash) cdr)
|
||||
dflt))
|
||||
|
||||
(define package-dependencies
|
||||
(memoize
|
||||
(lambda ()
|
||||
"Return a vhash keyed by package, and with associated values that are a
|
||||
list of packages that depend on that package."
|
||||
(fold-packages
|
||||
(lambda (package dag)
|
||||
(fold
|
||||
(lambda (in d)
|
||||
;; Insert a graph edge from each of package's inputs to package.
|
||||
(vhash-consq in
|
||||
(cons package (vhash-refq d in '()))
|
||||
(vhash-delq in d)))
|
||||
dag
|
||||
(match (package-direct-inputs package)
|
||||
(((labels packages . _) ...)
|
||||
packages) )))
|
||||
vlist-null))))
|
||||
|
||||
(define (package-direct-dependents packages)
|
||||
"Return a list of packages from the distribution that directly depend on the
|
||||
packages in PACKAGES."
|
||||
(delete-duplicates
|
||||
(concatenate
|
||||
(map (lambda (p)
|
||||
(vhash-refq (package-dependencies) p '()))
|
||||
packages))))
|
||||
|
||||
(define (package-transitive-dependents packages)
|
||||
"Return the transitive dependent packages of the distribution packages in
|
||||
PACKAGES---i.e. the dependents of those packages, plus their dependents,
|
||||
recursively."
|
||||
(let ((dependency-dag (package-dependencies)))
|
||||
(fold-tree
|
||||
cons '()
|
||||
(lambda (node) (vhash-refq dependency-dag node))
|
||||
;; Start with the dependents to avoid including PACKAGES in the result.
|
||||
(package-direct-dependents packages))))
|
||||
|
||||
(define (package-covering-dependents packages)
|
||||
"Return a minimal list of packages from the distribution whose dependencies
|
||||
include all of PACKAGES and all packages that depend on PACKAGES."
|
||||
(let ((dependency-dag (package-dependencies)))
|
||||
(fold-tree-leaves
|
||||
cons '()
|
||||
(lambda (node) (vhash-refq dependency-dag node))
|
||||
;; Start with the dependents to avoid including PACKAGES in the result.
|
||||
(package-direct-dependents packages))))
|
||||
|
||||
|
||||
(define %sigint-prompt
|
||||
;; The prompt to jump to upon SIGINT.
|
||||
@@ -228,65 +341,119 @@ return its return value."
|
||||
(lambda (k signum)
|
||||
(handler signum))))
|
||||
|
||||
|
||||
;;;
|
||||
;;; Package specification.
|
||||
;;;
|
||||
(define-syntax-rule (waiting exp fmt rest ...)
|
||||
"Display the given message while EXP is being evaluated."
|
||||
(let* ((message (format #f fmt rest ...))
|
||||
(blank (make-string (string-length message) #\space)))
|
||||
(display message (current-error-port))
|
||||
(force-output (current-error-port))
|
||||
(call-with-sigint-handler
|
||||
(lambda ()
|
||||
(dynamic-wind
|
||||
(const #f)
|
||||
(lambda () exp)
|
||||
(lambda ()
|
||||
;; Clear the line.
|
||||
(display #\cr (current-error-port))
|
||||
(display blank (current-error-port))
|
||||
(display #\cr (current-error-port))
|
||||
(force-output (current-error-port)))))
|
||||
(lambda (signum)
|
||||
(format (current-error-port) " interrupted by signal ~a~%" SIGINT)
|
||||
#f))))
|
||||
|
||||
(define* (%find-package spec name version)
|
||||
(match (find-best-packages-by-name name version)
|
||||
((pkg . pkg*)
|
||||
(unless (null? pkg*)
|
||||
(warning (G_ "ambiguous package specification `~a'~%") spec)
|
||||
(warning (G_ "choosing ~a@~a from ~a~%")
|
||||
(package-name pkg) (package-version pkg)
|
||||
(location->string (package-location pkg))))
|
||||
(match (package-superseded pkg)
|
||||
((? package? new)
|
||||
(info (G_ "package '~a' has been superseded by '~a'~%")
|
||||
(package-name pkg) (package-name new))
|
||||
new)
|
||||
(#f
|
||||
pkg)))
|
||||
(x
|
||||
(if version
|
||||
(leave (G_ "~A: package not found for version ~a~%") name version)
|
||||
(leave (G_ "~A: unknown package~%") name)))))
|
||||
(define ftp-open*
|
||||
;; Memoizing version of `ftp-open'. The goal is to avoid initiating a new
|
||||
;; FTP connection for each package, esp. since most of them are to the same
|
||||
;; server. This has a noticeable impact when doing "guix upgrade -u".
|
||||
(memoize ftp-open))
|
||||
|
||||
(define (check-package-freshness package)
|
||||
"Check whether PACKAGE has a newer version available upstream, and report
|
||||
it."
|
||||
;; TODO: Automatically inject the upstream version when desired.
|
||||
|
||||
(catch #t
|
||||
(lambda ()
|
||||
(when (false-if-exception (gnu-package? package))
|
||||
(let ((name (package-name package))
|
||||
(full-name (package-full-name package)))
|
||||
;; XXX: This could work with non-GNU packages as well. However,
|
||||
;; GNU's FTP-based updater would be too slow if it weren't memoized,
|
||||
;; and the generic interface in (guix upstream) doesn't support
|
||||
;; that.
|
||||
(match (waiting (latest-release name
|
||||
#:ftp-open ftp-open*
|
||||
#:ftp-close (const #f))
|
||||
(_ "looking for the latest release of GNU ~a...") name)
|
||||
((? upstream-source? source)
|
||||
(let ((latest-version
|
||||
(string-append (upstream-source-package source) "-"
|
||||
(upstream-source-version source))))
|
||||
(when (version>? latest-version full-name)
|
||||
(format (current-error-port)
|
||||
(_ "~a: note: using ~a \
|
||||
but ~a is available upstream~%")
|
||||
(location->string (package-location package))
|
||||
full-name latest-version))))
|
||||
(_ #t)))))
|
||||
(lambda (key . args)
|
||||
;; Silently ignore networking errors rather than preventing
|
||||
;; installation.
|
||||
(case key
|
||||
((getaddrinfo-error ftp-error) #f)
|
||||
(else (apply throw key args))))))
|
||||
|
||||
(define (specification->package spec)
|
||||
"Return a package matching SPEC. SPEC may be a package name, or a package
|
||||
name followed by an at-sign and a version number. If the version number is not
|
||||
name followed by a hyphen and a version number. If the version number is not
|
||||
present, return the preferred newest version."
|
||||
(let-values (((name version) (package-name->name+version spec)))
|
||||
(%find-package spec name version)))
|
||||
(let-values (((name version)
|
||||
(package-name->name+version spec)))
|
||||
(match (find-best-packages-by-name name version)
|
||||
((p) ; one match
|
||||
p)
|
||||
((p x ...) ; several matches
|
||||
(warning (_ "ambiguous package specification `~a'~%") spec)
|
||||
(warning (_ "choosing ~a from ~a~%")
|
||||
(package-full-name p)
|
||||
(location->string (package-location p)))
|
||||
p)
|
||||
(_ ; no matches
|
||||
(if version
|
||||
(leave (_ "~A: package not found for version ~a~%")
|
||||
name version)
|
||||
(leave (_ "~A: unknown package~%") name))))))
|
||||
|
||||
(define* (specification->package+output spec #:optional (output "out"))
|
||||
"Return the package and output specified by SPEC, or #f and #f; SPEC may
|
||||
optionally contain a version number and an output name, as in these examples:
|
||||
|
||||
guile
|
||||
guile@2.0.9
|
||||
guile-2.0.9
|
||||
guile:debug
|
||||
guile@2.0.9:debug
|
||||
guile-2.0.9:debug
|
||||
|
||||
If SPEC does not specify a version number, return the preferred newest
|
||||
version; if SPEC does not specify an output, return OUTPUT."
|
||||
(define (ensure-output p sub-drv)
|
||||
(if (member sub-drv (package-outputs p))
|
||||
sub-drv
|
||||
(leave (_ "package `~a' lacks output `~a'~%")
|
||||
(package-full-name p)
|
||||
sub-drv)))
|
||||
|
||||
(let-values (((name version sub-drv)
|
||||
(package-specification->name+version+output spec output)))
|
||||
(match (%find-package spec name version)
|
||||
(#f
|
||||
(values #f #f))
|
||||
(package
|
||||
(if (member sub-drv (package-outputs package))
|
||||
(values package sub-drv)
|
||||
(leave (G_ "package `~a' lacks output `~a'~%")
|
||||
(package-full-name package)
|
||||
sub-drv))))))
|
||||
|
||||
(define (specifications->manifest specs)
|
||||
"Given SPECS, a list of specifications such as \"emacs@25.2\" or
|
||||
\"guile:debug\", return a profile manifest."
|
||||
;; This procedure exists mostly so users of 'guix package -m' don't have to
|
||||
;; fiddle with multiple-value returns.
|
||||
(packages->manifest
|
||||
(map (compose list specification->package+output) specs)))
|
||||
(match (find-best-packages-by-name name version)
|
||||
((p)
|
||||
(values p (ensure-output p sub-drv)))
|
||||
((p p* ...)
|
||||
(warning (_ "ambiguous package specification `~a'~%")
|
||||
spec)
|
||||
(warning (_ "choosing ~a from ~a~%")
|
||||
(package-full-name p)
|
||||
(location->string (package-location p)))
|
||||
(values p (ensure-output p sub-drv)))
|
||||
(()
|
||||
(leave (_ "~a: package not found~%") spec)))))
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2015 Andreas Enge <andreas@enge.fr>
|
||||
;;;
|
||||
;;; 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 packages aarddict)
|
||||
#:use-module ((guix licenses) #:select (gpl3))
|
||||
#:use-module (guix packages)
|
||||
#:use-module (guix download)
|
||||
#:use-module (guix build-system python)
|
||||
#:use-module (gnu packages python)
|
||||
#:use-module (gnu packages qt))
|
||||
|
||||
(define-public aarddict
|
||||
(package
|
||||
(name "aarddict")
|
||||
(version "0.9.3")
|
||||
(source
|
||||
(origin
|
||||
(method url-fetch)
|
||||
(uri (string-append "https://github.com/aarddict/desktop/archive/"
|
||||
version ".tar.gz"))
|
||||
(file-name (string-append name "-" version ".tar.gz"))
|
||||
(sha256
|
||||
(base32
|
||||
"12h7m0z7nd7rg8avpi9syd265k0rhh4vbdh464nq0jzdg8m9p28c"))))
|
||||
(build-system python-build-system)
|
||||
(inputs
|
||||
`(("python2-pyicu" ,python2-pyicu)
|
||||
("python2-pyqt-4" ,python2-pyqt-4)
|
||||
("python2-setuptools" ,python2-setuptools)
|
||||
("python2-simplejson" ,python2-simplejson)
|
||||
("python2-sip" ,python2-sip)))
|
||||
(arguments
|
||||
`(#:python ,python-2 ; incompatible with Python 3
|
||||
#:phases
|
||||
(alist-cons-before
|
||||
'build 'configure
|
||||
;; Force data into the output instead of the python package.
|
||||
(lambda* (#:key outputs #:allow-other-keys)
|
||||
(let ((out (assoc-ref outputs "out")))
|
||||
(substitute* "setup.py"
|
||||
(("sys.prefix") (string-append "'" out "'")))))
|
||||
%standard-phases)))
|
||||
(home-page "http://aarddict.org/index.html")
|
||||
(synopsis
|
||||
"Dictionary program and offline Wikipedia reader")
|
||||
(description
|
||||
"Aard Dictionary is a free, fast, easy to use word lookup program that
|
||||
looks up words fast even with huge dictionaries like English Wikipedia;
|
||||
looks up words in multiple dictionaries in multiple languages without
|
||||
switching;
|
||||
works great as offline Wikipedia reader;
|
||||
is keyboard navigation friendly;
|
||||
has efficient, highly compressed dictionary data storage format with
|
||||
ability to verify data integrity built-in.")
|
||||
(license gpl3)))
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user