Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
;;; GNU Guix --- Functional package management for GNU
|
2019-02-01 19:25:38 +01:00
|
|
|
|
;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019 Ludovic Courtès <ludo@gnu.org>
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
;;; Copyright © 2013 Nikita Karetnikov <nikita@karetnikov.org>
|
2016-06-30 21:01:06 +02:00
|
|
|
|
;;; Copyright © 2014, 2016 Alex Kost <alezost@gmail.com>
|
2015-03-03 08:09:30 +01:00
|
|
|
|
;;; Copyright © 2015 Mark H Weaver <mhw@netris.org>
|
2015-05-27 14:58:27 +02:00
|
|
|
|
;;; Copyright © 2015 Sou Bunnbu <iyzsong@gmail.com>
|
2019-01-15 13:03:48 +01:00
|
|
|
|
;;; Copyright © 2016, 2018, 2019 Ricardo Wurmus <rekado@elephly.net>
|
2016-11-02 06:48:11 +01:00
|
|
|
|
;;; Copyright © 2016 Chris Marusich <cmmarusich@gmail.com>
|
2017-03-12 12:53:59 +01:00
|
|
|
|
;;; Copyright © 2017 Huang Ying <huang.ying.caritas@gmail.com>
|
2017-04-05 10:09:22 +02:00
|
|
|
|
;;; Copyright © 2017 Maxim Cournoyer <maxim.cournoyer@gmail.com>
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
;;;
|
|
|
|
|
;;; 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 (guix profiles)
|
2018-05-13 16:08:24 +02:00
|
|
|
|
#:use-module ((guix config) #:select (%state-directory))
|
2016-03-31 15:47:18 +02:00
|
|
|
|
#:use-module ((guix utils) #:hide (package-name->name+version))
|
|
|
|
|
#:use-module ((guix build utils)
|
2018-10-11 18:04:51 +02:00
|
|
|
|
#:select (package-name->name+version mkdir-p))
|
|
|
|
|
#:use-module (guix i18n)
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
#:use-module (guix records)
|
|
|
|
|
#:use-module (guix packages)
|
Move search path specifications to (guix search-paths).
* guix/packages.scm (<search-path-specification>,
search-path-specification->sexp, sexp->search-path-specification):
Move to...
* guix/search-paths.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
* guix/build-system/cmake.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/ruby.scm, guix/build-system/waf.scm,
guix/profiles.scm, guix/scripts/package.scm: Use it.
2015-05-04 22:11:37 +02:00
|
|
|
|
#:use-module (guix derivations)
|
|
|
|
|
#:use-module (guix search-paths)
|
2014-07-26 22:08:10 +02:00
|
|
|
|
#:use-module (guix gexp)
|
2017-12-15 22:16:18 +01:00
|
|
|
|
#:use-module (guix modules)
|
2014-08-23 18:41:14 +02:00
|
|
|
|
#:use-module (guix monads)
|
monads: Move '%store-monad' and related procedures where they belong.
This turns (guix monads) into a generic module for monads, and moves the
store monad and related monadic procedures in their corresponding
module.
* guix/monads.scm (store-return, store-bind, %store-monad, store-lift,
text-file, interned-file, package-file, package->derivation,
package->cross-derivation, origin->derivation, imported-modules,
compiled, modules, built-derivations, run-with-store): Move to...
* guix/store.scm (store-return, store-bind, %store-monad, store-lift,
text-file, interned-file): ... here.
(%guile-for-build): New variable.
(run-with-store): Moved from monads.scm. Remove default value for
#:guile-for-build.
* guix/packages.scm (default-guile): Export.
(set-guile-for-build): New procedure.
(package-file, package->derivation, package->cross-derivation,
origin->derivation): Moved from monads.scm.
* guix/derivations.scm (%guile-for-build): Remove.
(imported-modules): Rename to...
(%imported-modules): ... this.
(compiled-modules): Rename to...
(%compiled-modules): ... this.
(built-derivations, imported-modules, compiled-modules): New
procedures.
* gnu/services/avahi.scm, gnu/services/base.scm, gnu/services/dbus.scm,
gnu/services/dmd.scm, gnu/services/networking.scm,
gnu/services/ssh.scm, gnu/services/xorg.scm, gnu/system/install.scm,
gnu/system/linux-initrd.scm, gnu/system/shadow.scm, guix/download.scm,
guix/gexp.scm, guix/git-download.scm, guix/profiles.scm,
guix/svn-download.scm, tests/monads.scm: Adjust imports accordingly.
* guix/monad-repl.scm (default-guile-derivation): New procedure.
(store-monad-language, run-in-store): Use it.
* build-aux/hydra/gnu-system.scm (qemu-jobs): Add explicit
'set-guile-for-build' call.
* guix/scripts/archive.scm (derivation-from-expression): Likewise.
* guix/scripts/build.scm (options/resolve-packages): Likewise.
* guix/scripts/environment.scm (guix-environment): Likewise.
* guix/scripts/system.scm (guix-system): Likewise.
* doc/guix.texi (The Store Monad): Adjust module names accordingly.
2015-01-14 13:34:52 +01:00
|
|
|
|
#:use-module (guix store)
|
2017-06-07 09:51:55 +02:00
|
|
|
|
#:use-module (guix sets)
|
|
|
|
|
#:use-module (ice-9 vlist)
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
#:use-module (ice-9 match)
|
|
|
|
|
#:use-module (ice-9 regex)
|
|
|
|
|
#:use-module (ice-9 ftw)
|
2014-08-13 22:03:53 +02:00
|
|
|
|
#:use-module (ice-9 format)
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
#:use-module (srfi srfi-1)
|
|
|
|
|
#:use-module (srfi srfi-9)
|
2014-08-30 21:52:32 +02:00
|
|
|
|
#:use-module (srfi srfi-11)
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
#:use-module (srfi srfi-19)
|
|
|
|
|
#:use-module (srfi srfi-26)
|
2014-10-08 15:29:01 +02:00
|
|
|
|
#:use-module (srfi srfi-34)
|
|
|
|
|
#:use-module (srfi srfi-35)
|
|
|
|
|
#:export (&profile-error
|
|
|
|
|
profile-error?
|
|
|
|
|
profile-error-profile
|
|
|
|
|
&profile-not-found-error
|
|
|
|
|
profile-not-found-error?
|
2018-10-26 20:04:49 +02:00
|
|
|
|
&profile-collision-error
|
2017-06-07 09:51:55 +02:00
|
|
|
|
profile-collision-error?
|
|
|
|
|
profile-collision-error-entry
|
|
|
|
|
profile-collision-error-conflict
|
2014-10-08 15:29:01 +02:00
|
|
|
|
&missing-generation-error
|
|
|
|
|
missing-generation-error?
|
|
|
|
|
missing-generation-error-generation
|
2019-02-07 14:54:43 +01:00
|
|
|
|
&unmatched-pattern-error
|
|
|
|
|
unmatched-pattern-error?
|
|
|
|
|
unmatched-pattern-error-pattern
|
|
|
|
|
unmatched-pattern-error-manifest
|
2014-10-08 15:29:01 +02:00
|
|
|
|
|
|
|
|
|
manifest make-manifest
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
manifest?
|
|
|
|
|
manifest-entries
|
2017-06-07 09:51:55 +02:00
|
|
|
|
manifest-transitive-entries
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
|
|
|
|
|
<manifest-entry> ; FIXME: eventually make it internal
|
|
|
|
|
manifest-entry
|
|
|
|
|
manifest-entry?
|
|
|
|
|
manifest-entry-name
|
|
|
|
|
manifest-entry-version
|
|
|
|
|
manifest-entry-output
|
2014-07-26 22:08:10 +02:00
|
|
|
|
manifest-entry-item
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
manifest-entry-dependencies
|
2015-05-02 23:55:24 +02:00
|
|
|
|
manifest-entry-search-paths
|
2017-06-06 15:29:50 +02:00
|
|
|
|
manifest-entry-parent
|
2018-05-13 18:48:22 +02:00
|
|
|
|
manifest-entry-properties
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
|
2013-11-01 23:11:17 +01:00
|
|
|
|
manifest-pattern
|
|
|
|
|
manifest-pattern?
|
2016-09-06 23:05:26 +02:00
|
|
|
|
manifest-pattern-name
|
|
|
|
|
manifest-pattern-version
|
|
|
|
|
manifest-pattern-output
|
2013-11-01 23:11:17 +01:00
|
|
|
|
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
manifest-remove
|
2014-08-12 10:32:16 +02:00
|
|
|
|
manifest-add
|
2014-09-02 21:12:59 +02:00
|
|
|
|
manifest-lookup
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
manifest-installed?
|
2013-11-01 23:11:17 +01:00
|
|
|
|
manifest-matching-entries
|
2018-07-09 10:44:36 +02:00
|
|
|
|
manifest-search-paths
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
|
2014-08-13 22:03:53 +02:00
|
|
|
|
manifest-transaction
|
|
|
|
|
manifest-transaction?
|
|
|
|
|
manifest-transaction-install
|
|
|
|
|
manifest-transaction-remove
|
2016-09-06 20:19:21 +02:00
|
|
|
|
manifest-transaction-install-entry
|
|
|
|
|
manifest-transaction-remove-pattern
|
|
|
|
|
manifest-transaction-null?
|
2017-06-26 22:23:11 +02:00
|
|
|
|
manifest-transaction-removal-candidate?
|
2014-08-13 22:03:53 +02:00
|
|
|
|
manifest-perform-transaction
|
2014-08-30 21:52:32 +02:00
|
|
|
|
manifest-transaction-effects
|
2014-08-13 22:03:53 +02:00
|
|
|
|
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
profile-manifest
|
2014-07-26 22:54:40 +02:00
|
|
|
|
package->manifest-entry
|
2015-05-18 13:51:56 +02:00
|
|
|
|
packages->manifest
|
2017-01-15 10:25:52 +01:00
|
|
|
|
ca-certificate-bundle
|
2015-04-15 22:44:51 +02:00
|
|
|
|
%default-profile-hooks
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
profile-derivation
|
2018-07-09 13:22:29 +02:00
|
|
|
|
profile-search-paths
|
2015-10-26 23:01:06 +01:00
|
|
|
|
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
generation-number
|
2019-04-06 23:05:27 +02:00
|
|
|
|
generation-profile
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
generation-numbers
|
2014-09-21 12:24:09 +02:00
|
|
|
|
profile-generations
|
2016-11-02 06:48:11 +01:00
|
|
|
|
relative-generation-spec->number
|
2014-10-10 15:56:59 +02:00
|
|
|
|
relative-generation
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
previous-generation-number
|
|
|
|
|
generation-time
|
2015-10-26 23:01:06 +01:00
|
|
|
|
generation-file-name
|
|
|
|
|
switch-to-generation
|
|
|
|
|
roll-back
|
2018-05-13 16:08:24 +02:00
|
|
|
|
delete-generation
|
|
|
|
|
|
|
|
|
|
%user-profile-directory
|
|
|
|
|
%profile-directory
|
|
|
|
|
%current-profile
|
2018-10-11 18:04:51 +02:00
|
|
|
|
ensure-profile-directory
|
2018-05-13 16:08:24 +02:00
|
|
|
|
canonicalize-profile
|
|
|
|
|
user-friendly-profile))
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
|
|
|
|
|
;;; Commentary:
|
|
|
|
|
;;;
|
|
|
|
|
;;; Tools to create and manipulate profiles---i.e., the representation of a
|
|
|
|
|
;;; set of installed packages.
|
|
|
|
|
;;;
|
|
|
|
|
;;; Code:
|
|
|
|
|
|
2014-10-08 15:29:01 +02:00
|
|
|
|
|
|
|
|
|
;;;
|
|
|
|
|
;;; Condition types.
|
|
|
|
|
;;;
|
|
|
|
|
|
|
|
|
|
(define-condition-type &profile-error &error
|
|
|
|
|
profile-error?
|
|
|
|
|
(profile profile-error-profile))
|
|
|
|
|
|
|
|
|
|
(define-condition-type &profile-not-found-error &profile-error
|
|
|
|
|
profile-not-found-error?)
|
|
|
|
|
|
2017-06-07 09:51:55 +02:00
|
|
|
|
(define-condition-type &profile-collision-error &error
|
|
|
|
|
profile-collision-error?
|
|
|
|
|
(entry profile-collision-error-entry) ;<manifest-entry>
|
|
|
|
|
(conflict profile-collision-error-conflict)) ;<manifest-entry>
|
|
|
|
|
|
2019-02-07 14:54:43 +01:00
|
|
|
|
(define-condition-type &unmatched-pattern-error &error
|
|
|
|
|
unmatched-pattern-error?
|
|
|
|
|
(pattern unmatched-pattern-error-pattern) ;<manifest-pattern>
|
|
|
|
|
(manifest unmatched-pattern-error-manifest)) ;<manifest>
|
|
|
|
|
|
2014-10-08 15:29:01 +02:00
|
|
|
|
(define-condition-type &missing-generation-error &profile-error
|
|
|
|
|
missing-generation-error?
|
|
|
|
|
(generation missing-generation-error-generation))
|
|
|
|
|
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
|
|
|
|
|
;;;
|
|
|
|
|
;;; Manifests.
|
|
|
|
|
;;;
|
|
|
|
|
|
|
|
|
|
(define-record-type <manifest>
|
|
|
|
|
(manifest entries)
|
|
|
|
|
manifest?
|
|
|
|
|
(entries manifest-entries)) ; list of <manifest-entry>
|
|
|
|
|
|
|
|
|
|
;; Convenient alias, to avoid name clashes.
|
|
|
|
|
(define make-manifest manifest)
|
|
|
|
|
|
|
|
|
|
(define-record-type* <manifest-entry> manifest-entry
|
|
|
|
|
make-manifest-entry
|
|
|
|
|
manifest-entry?
|
|
|
|
|
(name manifest-entry-name) ; string
|
|
|
|
|
(version manifest-entry-version) ; string
|
|
|
|
|
(output manifest-entry-output ; string
|
|
|
|
|
(default "out"))
|
2018-05-02 11:01:56 +02:00
|
|
|
|
(item manifest-entry-item) ; package | file-like | store path
|
2017-06-06 14:01:12 +02:00
|
|
|
|
(dependencies manifest-entry-dependencies ; <manifest-entry>*
|
2015-05-02 23:55:24 +02:00
|
|
|
|
(default '()))
|
|
|
|
|
(search-paths manifest-entry-search-paths ; search-path-specification*
|
2017-06-06 15:29:50 +02:00
|
|
|
|
(default '()))
|
|
|
|
|
(parent manifest-entry-parent ; promise (#f | <manifest-entry>)
|
2018-05-13 18:48:22 +02:00
|
|
|
|
(default (delay #f)))
|
|
|
|
|
(properties manifest-entry-properties ; list of symbol/value pairs
|
|
|
|
|
(default '())))
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
|
2013-11-01 23:11:17 +01:00
|
|
|
|
(define-record-type* <manifest-pattern> manifest-pattern
|
|
|
|
|
make-manifest-pattern
|
|
|
|
|
manifest-pattern?
|
|
|
|
|
(name manifest-pattern-name) ; string
|
|
|
|
|
(version manifest-pattern-version ; string | #f
|
|
|
|
|
(default #f))
|
|
|
|
|
(output manifest-pattern-output ; string | #f
|
|
|
|
|
(default "out")))
|
|
|
|
|
|
2017-06-21 11:58:39 +02:00
|
|
|
|
(define (manifest-transitive-entries manifest)
|
|
|
|
|
"Return the entries of MANIFEST along with their propagated inputs,
|
|
|
|
|
recursively."
|
|
|
|
|
(let loop ((entries (manifest-entries manifest))
|
|
|
|
|
(result '())
|
|
|
|
|
(visited (set))) ;compare with 'equal?'
|
|
|
|
|
(match entries
|
|
|
|
|
(()
|
|
|
|
|
(reverse result))
|
|
|
|
|
((head . tail)
|
|
|
|
|
(if (set-contains? visited head)
|
|
|
|
|
(loop tail result visited)
|
|
|
|
|
(loop (append (manifest-entry-dependencies head)
|
|
|
|
|
tail)
|
|
|
|
|
(cons head result)
|
|
|
|
|
(set-insert head visited)))))))
|
|
|
|
|
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
(define (profile-manifest profile)
|
|
|
|
|
"Return the PROFILE's manifest."
|
|
|
|
|
(let ((file (string-append profile "/manifest")))
|
|
|
|
|
(if (file-exists? file)
|
|
|
|
|
(call-with-input-file file read-manifest)
|
|
|
|
|
(manifest '()))))
|
|
|
|
|
|
2017-06-07 09:51:55 +02:00
|
|
|
|
(define (manifest-entry-lookup manifest)
|
|
|
|
|
"Return a lookup procedure for the entries of MANIFEST. The lookup
|
|
|
|
|
procedure takes two arguments: the entry name and output."
|
|
|
|
|
(define mapping
|
|
|
|
|
(let loop ((entries (manifest-entries manifest))
|
|
|
|
|
(mapping vlist-null))
|
|
|
|
|
(fold (lambda (entry result)
|
|
|
|
|
(vhash-cons (cons (manifest-entry-name entry)
|
|
|
|
|
(manifest-entry-output entry))
|
|
|
|
|
entry
|
|
|
|
|
(loop (manifest-entry-dependencies entry)
|
|
|
|
|
result)))
|
|
|
|
|
mapping
|
|
|
|
|
entries)))
|
|
|
|
|
|
|
|
|
|
(lambda (name output)
|
|
|
|
|
(match (vhash-assoc (cons name output) mapping)
|
|
|
|
|
((_ . entry) entry)
|
|
|
|
|
(#f #f))))
|
|
|
|
|
|
|
|
|
|
(define* (lower-manifest-entry entry system #:key target)
|
|
|
|
|
"Lower ENTRY for SYSTEM and TARGET such that its 'item' field is a store
|
|
|
|
|
file name."
|
|
|
|
|
(let ((item (manifest-entry-item entry)))
|
|
|
|
|
(if (string? item)
|
|
|
|
|
(with-monad %store-monad
|
|
|
|
|
(return entry))
|
|
|
|
|
(mlet %store-monad ((drv (lower-object item system
|
|
|
|
|
#:target target))
|
|
|
|
|
(output -> (manifest-entry-output entry)))
|
|
|
|
|
(return (manifest-entry
|
|
|
|
|
(inherit entry)
|
|
|
|
|
(item (derivation->output-path drv output))))))))
|
|
|
|
|
|
|
|
|
|
(define* (check-for-collisions manifest system #:key target)
|
|
|
|
|
"Check whether the entries of MANIFEST conflict with one another; raise a
|
|
|
|
|
'&profile-collision-error' when a conflict is encountered."
|
|
|
|
|
(define lookup
|
|
|
|
|
(manifest-entry-lookup manifest))
|
|
|
|
|
|
|
|
|
|
(with-monad %store-monad
|
|
|
|
|
(foldm %store-monad
|
|
|
|
|
(lambda (entry result)
|
|
|
|
|
(match (lookup (manifest-entry-name entry)
|
|
|
|
|
(manifest-entry-output entry))
|
|
|
|
|
((? manifest-entry? second) ;potential conflict
|
|
|
|
|
(mlet %store-monad ((first (lower-manifest-entry entry system
|
|
|
|
|
#:target
|
|
|
|
|
target))
|
|
|
|
|
(second (lower-manifest-entry second system
|
|
|
|
|
#:target
|
|
|
|
|
target)))
|
|
|
|
|
(if (string=? (manifest-entry-item first)
|
|
|
|
|
(manifest-entry-item second))
|
|
|
|
|
(return result)
|
|
|
|
|
(raise (condition
|
|
|
|
|
(&profile-collision-error
|
|
|
|
|
(entry first)
|
|
|
|
|
(conflict second)))))))
|
|
|
|
|
(#f ;no conflict
|
|
|
|
|
(return result))))
|
|
|
|
|
#t
|
|
|
|
|
(manifest-transitive-entries manifest))))
|
|
|
|
|
|
2017-06-06 15:29:50 +02:00
|
|
|
|
(define* (package->manifest-entry package #:optional (output "out")
|
2018-09-04 10:56:14 +02:00
|
|
|
|
#:key (parent (delay #f))
|
|
|
|
|
(properties '()))
|
2016-07-26 18:18:53 +02:00
|
|
|
|
"Return a manifest entry for the OUTPUT of package PACKAGE."
|
2017-06-06 15:29:50 +02:00
|
|
|
|
;; For each dependency, keep a promise pointing to its "parent" entry.
|
|
|
|
|
(letrec* ((deps (map (match-lambda
|
|
|
|
|
((label package)
|
|
|
|
|
(package->manifest-entry package
|
|
|
|
|
#:parent (delay entry)))
|
|
|
|
|
((label package output)
|
|
|
|
|
(package->manifest-entry package output
|
|
|
|
|
#:parent (delay entry))))
|
|
|
|
|
(package-propagated-inputs package)))
|
|
|
|
|
(entry (manifest-entry
|
|
|
|
|
(name (package-name package))
|
|
|
|
|
(version (package-version package))
|
|
|
|
|
(output output)
|
|
|
|
|
(item package)
|
|
|
|
|
(dependencies (delete-duplicates deps))
|
|
|
|
|
(search-paths
|
|
|
|
|
(package-transitive-native-search-paths package))
|
2018-09-04 10:56:14 +02:00
|
|
|
|
(parent parent)
|
|
|
|
|
(properties properties))))
|
2017-06-06 15:29:50 +02:00
|
|
|
|
entry))
|
2014-07-26 22:54:40 +02:00
|
|
|
|
|
2015-05-18 13:51:56 +02:00
|
|
|
|
(define (packages->manifest packages)
|
|
|
|
|
"Return a list of manifest entries, one for each item listed in PACKAGES.
|
|
|
|
|
Elements of PACKAGES can be either package objects or package/string tuples
|
|
|
|
|
denoting a specific output of a package."
|
2018-09-18 10:21:28 +02:00
|
|
|
|
(define inferiors-loaded?
|
|
|
|
|
;; This hack allows us to provide seamless integration for inferior
|
|
|
|
|
;; packages while not having a hard dependency on (guix inferior).
|
|
|
|
|
(resolve-module '(guix inferior) #f #f #:ensure #f))
|
|
|
|
|
|
|
|
|
|
(define (inferior->entry)
|
|
|
|
|
(module-ref (resolve-interface '(guix inferior))
|
|
|
|
|
'inferior-package->manifest-entry))
|
|
|
|
|
|
2015-05-18 13:51:56 +02:00
|
|
|
|
(manifest
|
|
|
|
|
(map (match-lambda
|
2018-09-18 10:21:28 +02:00
|
|
|
|
((package output)
|
|
|
|
|
(package->manifest-entry package output))
|
|
|
|
|
((? package? package)
|
|
|
|
|
(package->manifest-entry package))
|
|
|
|
|
((thing output)
|
|
|
|
|
(if inferiors-loaded?
|
|
|
|
|
((inferior->entry) thing output)
|
|
|
|
|
(throw 'wrong-type-arg 'packages->manifest
|
|
|
|
|
"Wrong package object: ~S" (list thing) (list thing))))
|
|
|
|
|
(thing
|
|
|
|
|
(if inferiors-loaded?
|
|
|
|
|
((inferior->entry) thing)
|
|
|
|
|
(throw 'wrong-type-arg 'packages->manifest
|
|
|
|
|
"Wrong package object: ~S" (list thing) (list thing)))))
|
2015-05-18 13:51:56 +02:00
|
|
|
|
packages)))
|
|
|
|
|
|
2014-07-26 22:08:10 +02:00
|
|
|
|
(define (manifest->gexp manifest)
|
|
|
|
|
"Return a representation of MANIFEST as a gexp."
|
|
|
|
|
(define (entry->gexp entry)
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
(match entry
|
2015-05-02 23:55:24 +02:00
|
|
|
|
(($ <manifest-entry> name version output (? string? path)
|
2018-05-13 18:48:22 +02:00
|
|
|
|
(deps ...) (search-paths ...) _ (properties ...))
|
2015-05-02 23:55:24 +02:00
|
|
|
|
#~(#$name #$version #$output #$path
|
2017-06-06 14:01:12 +02:00
|
|
|
|
(propagated-inputs #$(map entry->gexp deps))
|
2015-05-02 23:55:24 +02:00
|
|
|
|
(search-paths #$(map search-path-specification->sexp
|
2018-05-13 18:48:22 +02:00
|
|
|
|
search-paths))
|
|
|
|
|
(properties . #$properties)))
|
2018-05-02 11:01:56 +02:00
|
|
|
|
(($ <manifest-entry> name version output package
|
2018-05-13 18:48:22 +02:00
|
|
|
|
(deps ...) (search-paths ...) _ (properties ...))
|
2014-07-26 22:08:10 +02:00
|
|
|
|
#~(#$name #$version #$output
|
2015-05-02 23:55:24 +02:00
|
|
|
|
(ungexp package (or output "out"))
|
2017-06-06 14:01:12 +02:00
|
|
|
|
(propagated-inputs #$(map entry->gexp deps))
|
2015-05-02 23:55:24 +02:00
|
|
|
|
(search-paths #$(map search-path-specification->sexp
|
2018-05-13 18:48:22 +02:00
|
|
|
|
search-paths))
|
|
|
|
|
(properties . #$properties)))))
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
|
|
|
|
|
(match manifest
|
|
|
|
|
(($ <manifest> (entries ...))
|
2017-06-06 14:01:12 +02:00
|
|
|
|
#~(manifest (version 3)
|
2014-07-26 22:08:10 +02:00
|
|
|
|
(packages #$(map entry->gexp entries))))))
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
|
2015-05-02 23:55:24 +02:00
|
|
|
|
(define (find-package name version)
|
|
|
|
|
"Return a package from the distro matching NAME and possibly VERSION. This
|
|
|
|
|
procedure is here for backward-compatibility and will eventually vanish."
|
|
|
|
|
(define find-best-packages-by-name ;break abstractions
|
|
|
|
|
(module-ref (resolve-interface '(gnu packages))
|
|
|
|
|
'find-best-packages-by-name))
|
|
|
|
|
|
|
|
|
|
;; Use 'find-best-packages-by-name' and not 'find-packages-by-name'; the
|
|
|
|
|
;; former traverses the module tree only once and then allows for efficient
|
|
|
|
|
;; access via a vhash.
|
|
|
|
|
(match (find-best-packages-by-name name version)
|
|
|
|
|
((p _ ...) p)
|
|
|
|
|
(_
|
|
|
|
|
(match (find-best-packages-by-name name #f)
|
|
|
|
|
((p _ ...) p)
|
|
|
|
|
(_ #f)))))
|
|
|
|
|
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
(define (sexp->manifest sexp)
|
|
|
|
|
"Parse SEXP as a manifest."
|
2015-05-02 23:55:24 +02:00
|
|
|
|
(define (infer-search-paths name version)
|
|
|
|
|
;; Infer the search path specifications for NAME-VERSION by looking up a
|
|
|
|
|
;; same-named package in the distro. Useful for the old manifest formats
|
|
|
|
|
;; that did not store search path info.
|
|
|
|
|
(let ((package (find-package name version)))
|
|
|
|
|
(if package
|
|
|
|
|
(package-native-search-paths package)
|
|
|
|
|
'())))
|
|
|
|
|
|
2017-06-06 15:29:50 +02:00
|
|
|
|
(define (infer-dependency item parent)
|
2017-06-06 14:01:12 +02:00
|
|
|
|
;; Return a <manifest-entry> for ITEM.
|
|
|
|
|
(let-values (((name version)
|
|
|
|
|
(package-name->name+version
|
|
|
|
|
(store-path-package-name item))))
|
|
|
|
|
(manifest-entry
|
|
|
|
|
(name name)
|
|
|
|
|
(version version)
|
2017-06-06 15:29:50 +02:00
|
|
|
|
(item item)
|
|
|
|
|
(parent parent))))
|
|
|
|
|
|
|
|
|
|
(define* (sexp->manifest-entry sexp #:optional (parent (delay #f)))
|
|
|
|
|
(match sexp
|
|
|
|
|
((name version output path
|
|
|
|
|
('propagated-inputs deps)
|
|
|
|
|
('search-paths search-paths)
|
|
|
|
|
extra-stuff ...)
|
|
|
|
|
;; For each of DEPS, keep a promise pointing to ENTRY.
|
|
|
|
|
(letrec* ((deps* (map (cut sexp->manifest-entry <> (delay entry))
|
|
|
|
|
deps))
|
|
|
|
|
(entry (manifest-entry
|
|
|
|
|
(name name)
|
|
|
|
|
(version version)
|
|
|
|
|
(output output)
|
|
|
|
|
(item path)
|
|
|
|
|
(dependencies deps*)
|
|
|
|
|
(search-paths (map sexp->search-path-specification
|
|
|
|
|
search-paths))
|
2018-05-13 18:48:22 +02:00
|
|
|
|
(parent parent)
|
|
|
|
|
(properties (or (assoc-ref extra-stuff 'properties)
|
|
|
|
|
'())))))
|
2017-06-06 15:29:50 +02:00
|
|
|
|
entry))))
|
2017-06-06 14:01:12 +02:00
|
|
|
|
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
(match sexp
|
|
|
|
|
(('manifest ('version 0)
|
|
|
|
|
('packages ((name version output path) ...)))
|
|
|
|
|
(manifest
|
|
|
|
|
(map (lambda (name version output path)
|
|
|
|
|
(manifest-entry
|
2017-06-06 14:01:12 +02:00
|
|
|
|
(name name)
|
|
|
|
|
(version version)
|
|
|
|
|
(output output)
|
|
|
|
|
(item path)
|
|
|
|
|
(search-paths (infer-search-paths name version))))
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
name version output path)))
|
|
|
|
|
|
|
|
|
|
;; Version 1 adds a list of propagated inputs to the
|
|
|
|
|
;; name/version/output/path tuples.
|
|
|
|
|
(('manifest ('version 1)
|
|
|
|
|
('packages ((name version output path deps) ...)))
|
|
|
|
|
(manifest
|
|
|
|
|
(map (lambda (name version output path deps)
|
2014-08-12 22:09:42 +02:00
|
|
|
|
;; Up to Guix 0.7 included, dependencies were listed as ("gmp"
|
|
|
|
|
;; "/gnu/store/...-gmp") for instance. Discard the 'label' in
|
|
|
|
|
;; such lists.
|
|
|
|
|
(let ((deps (match deps
|
|
|
|
|
(((labels directories) ...)
|
|
|
|
|
directories)
|
|
|
|
|
((directories ...)
|
|
|
|
|
directories))))
|
2017-06-06 15:29:50 +02:00
|
|
|
|
(letrec* ((deps* (map (cute infer-dependency <> (delay entry))
|
|
|
|
|
deps))
|
|
|
|
|
(entry (manifest-entry
|
|
|
|
|
(name name)
|
|
|
|
|
(version version)
|
|
|
|
|
(output output)
|
|
|
|
|
(item path)
|
|
|
|
|
(dependencies deps*)
|
|
|
|
|
(search-paths
|
|
|
|
|
(infer-search-paths name version)))))
|
|
|
|
|
entry)))
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
name version output path deps)))
|
|
|
|
|
|
2015-05-02 23:55:24 +02:00
|
|
|
|
;; Version 2 adds search paths and is slightly more verbose.
|
|
|
|
|
(('manifest ('version 2 minor-version ...)
|
|
|
|
|
('packages ((name version output path
|
|
|
|
|
('propagated-inputs deps)
|
|
|
|
|
('search-paths search-paths)
|
|
|
|
|
extra-stuff ...)
|
|
|
|
|
...)))
|
|
|
|
|
(manifest
|
|
|
|
|
(map (lambda (name version output path deps search-paths)
|
2017-06-06 15:29:50 +02:00
|
|
|
|
(letrec* ((deps* (map (cute infer-dependency <> (delay entry))
|
|
|
|
|
deps))
|
|
|
|
|
(entry (manifest-entry
|
|
|
|
|
(name name)
|
|
|
|
|
(version version)
|
|
|
|
|
(output output)
|
|
|
|
|
(item path)
|
|
|
|
|
(dependencies deps*)
|
|
|
|
|
(search-paths
|
|
|
|
|
(map sexp->search-path-specification
|
|
|
|
|
search-paths)))))
|
|
|
|
|
entry))
|
2015-05-02 23:55:24 +02:00
|
|
|
|
name version output path deps search-paths)))
|
2017-06-06 14:01:12 +02:00
|
|
|
|
|
|
|
|
|
;; Version 3 represents DEPS as full-blown manifest entries.
|
|
|
|
|
(('manifest ('version 3 minor-version ...)
|
|
|
|
|
('packages (entries ...)))
|
2017-06-06 15:29:50 +02:00
|
|
|
|
(manifest (map sexp->manifest-entry entries)))
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
(_
|
2015-05-04 22:41:31 +02:00
|
|
|
|
(raise (condition
|
|
|
|
|
(&message (message "unsupported manifest format")))))))
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
|
|
|
|
|
(define (read-manifest port)
|
|
|
|
|
"Return the packages listed in MANIFEST."
|
|
|
|
|
(sexp->manifest (read port)))
|
|
|
|
|
|
2013-11-01 23:11:17 +01:00
|
|
|
|
(define (entry-predicate pattern)
|
|
|
|
|
"Return a procedure that returns #t when passed a manifest entry that
|
|
|
|
|
matches NAME/OUTPUT/VERSION. OUTPUT and VERSION may be #f, in which case they
|
|
|
|
|
are ignored."
|
|
|
|
|
(match pattern
|
|
|
|
|
(($ <manifest-pattern> name version output)
|
|
|
|
|
(match-lambda
|
|
|
|
|
(($ <manifest-entry> entry-name entry-version entry-output)
|
|
|
|
|
(and (string=? entry-name name)
|
|
|
|
|
(or (not entry-output) (not output)
|
|
|
|
|
(string=? entry-output output))
|
|
|
|
|
(or (not version)
|
|
|
|
|
(string=? entry-version version))))))))
|
|
|
|
|
|
|
|
|
|
(define (manifest-remove manifest patterns)
|
|
|
|
|
"Remove entries for each of PATTERNS from MANIFEST. Each item in PATTERNS
|
|
|
|
|
must be a manifest-pattern."
|
|
|
|
|
(define (remove-entry pattern lst)
|
|
|
|
|
(remove (entry-predicate pattern) lst))
|
|
|
|
|
|
|
|
|
|
(make-manifest (fold remove-entry
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
(manifest-entries manifest)
|
2013-11-01 23:11:17 +01:00
|
|
|
|
patterns)))
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
|
2014-08-12 10:32:16 +02:00
|
|
|
|
(define (manifest-add manifest entries)
|
|
|
|
|
"Add a list of manifest ENTRIES to MANIFEST and return new manifest.
|
|
|
|
|
Remove MANIFEST entries that have the same name and output as ENTRIES."
|
|
|
|
|
(define (same-entry? entry name output)
|
|
|
|
|
(match entry
|
2018-03-01 11:37:36 +01:00
|
|
|
|
(($ <manifest-entry> entry-name _ entry-output _)
|
2014-08-12 10:32:16 +02:00
|
|
|
|
(and (equal? name entry-name)
|
|
|
|
|
(equal? output entry-output)))))
|
|
|
|
|
|
|
|
|
|
(make-manifest
|
2018-03-01 11:37:36 +01:00
|
|
|
|
(fold (lambda (entry result) ;XXX: quadratic
|
|
|
|
|
(match entry
|
|
|
|
|
(($ <manifest-entry> name _ out _)
|
|
|
|
|
(cons entry
|
|
|
|
|
(remove (cut same-entry? <> name out)
|
|
|
|
|
result)))))
|
|
|
|
|
(manifest-entries manifest)
|
|
|
|
|
entries)))
|
2014-08-12 10:32:16 +02:00
|
|
|
|
|
2014-09-02 21:12:59 +02:00
|
|
|
|
(define (manifest-lookup manifest pattern)
|
|
|
|
|
"Return the first item of MANIFEST that matches PATTERN, or #f if there is
|
|
|
|
|
no match.."
|
|
|
|
|
(find (entry-predicate pattern)
|
|
|
|
|
(manifest-entries manifest)))
|
|
|
|
|
|
2013-11-01 23:11:17 +01:00
|
|
|
|
(define (manifest-installed? manifest pattern)
|
|
|
|
|
"Return #t if MANIFEST has an entry matching PATTERN (a manifest-pattern),
|
|
|
|
|
#f otherwise."
|
2014-09-02 21:12:59 +02:00
|
|
|
|
(->bool (manifest-lookup manifest pattern)))
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
|
2013-11-01 23:11:17 +01:00
|
|
|
|
(define (manifest-matching-entries manifest patterns)
|
2019-02-07 14:54:43 +01:00
|
|
|
|
"Return all the entries of MANIFEST that match one of the PATTERNS. Raise
|
|
|
|
|
an '&unmatched-pattern-error' if none of the entries of MANIFEST matches one
|
|
|
|
|
of PATTERNS."
|
|
|
|
|
(fold-right (lambda (pattern matches)
|
|
|
|
|
(match (filter (entry-predicate pattern)
|
|
|
|
|
(manifest-entries manifest))
|
|
|
|
|
(()
|
|
|
|
|
(raise (condition
|
|
|
|
|
(&unmatched-pattern-error
|
|
|
|
|
(pattern pattern)
|
|
|
|
|
(manifest manifest)))))
|
|
|
|
|
(lst
|
|
|
|
|
(append lst matches))))
|
|
|
|
|
'()
|
|
|
|
|
patterns))
|
2013-11-01 23:11:17 +01:00
|
|
|
|
|
2018-07-09 10:44:36 +02:00
|
|
|
|
(define (manifest-search-paths manifest)
|
|
|
|
|
"Return the list of search path specifications that apply to MANIFEST,
|
|
|
|
|
including the search path specification for $PATH."
|
|
|
|
|
(delete-duplicates
|
|
|
|
|
(cons $PATH
|
|
|
|
|
(append-map manifest-entry-search-paths
|
|
|
|
|
(manifest-entries manifest)))))
|
|
|
|
|
|
2014-08-13 22:03:53 +02:00
|
|
|
|
|
|
|
|
|
;;;
|
|
|
|
|
;;; Manifest transactions.
|
|
|
|
|
;;;
|
|
|
|
|
|
|
|
|
|
(define-record-type* <manifest-transaction> manifest-transaction
|
|
|
|
|
make-manifest-transaction
|
|
|
|
|
manifest-transaction?
|
|
|
|
|
(install manifest-transaction-install ; list of <manifest-entry>
|
|
|
|
|
(default '()))
|
|
|
|
|
(remove manifest-transaction-remove ; list of <manifest-pattern>
|
|
|
|
|
(default '())))
|
|
|
|
|
|
2016-09-06 20:19:21 +02:00
|
|
|
|
(define (manifest-transaction-install-entry entry transaction)
|
|
|
|
|
"Augment TRANSACTION's set of installed packages with ENTRY, a
|
|
|
|
|
<manifest-entry>."
|
|
|
|
|
(manifest-transaction
|
|
|
|
|
(inherit transaction)
|
|
|
|
|
(install
|
|
|
|
|
(cons entry (manifest-transaction-install transaction)))))
|
|
|
|
|
|
|
|
|
|
(define (manifest-transaction-remove-pattern pattern transaction)
|
|
|
|
|
"Add PATTERN to TRANSACTION's list of packages to remove."
|
|
|
|
|
(manifest-transaction
|
|
|
|
|
(inherit transaction)
|
|
|
|
|
(remove
|
|
|
|
|
(cons pattern (manifest-transaction-remove transaction)))))
|
|
|
|
|
|
|
|
|
|
(define (manifest-transaction-null? transaction)
|
|
|
|
|
"Return true if TRANSACTION has no effect---i.e., it neither installs nor
|
|
|
|
|
remove software."
|
|
|
|
|
(match transaction
|
|
|
|
|
(($ <manifest-transaction> () ()) #t)
|
|
|
|
|
(($ <manifest-transaction> _ _) #f)))
|
|
|
|
|
|
2017-06-26 22:23:11 +02:00
|
|
|
|
(define (manifest-transaction-removal-candidate? entry transaction)
|
|
|
|
|
"Return true if ENTRY is a candidate for removal in TRANSACTION."
|
|
|
|
|
(any (lambda (pattern)
|
|
|
|
|
((entry-predicate pattern) entry))
|
|
|
|
|
(manifest-transaction-remove transaction)))
|
|
|
|
|
|
2014-08-30 21:52:32 +02:00
|
|
|
|
(define (manifest-transaction-effects manifest transaction)
|
2015-02-08 18:52:00 +01:00
|
|
|
|
"Compute the effect of applying TRANSACTION to MANIFEST. Return 4 values:
|
|
|
|
|
the list of packages that would be removed, installed, upgraded, or downgraded
|
|
|
|
|
when applying TRANSACTION to MANIFEST. Upgrades are represented as pairs
|
|
|
|
|
where the head is the entry being upgraded and the tail is the entry that will
|
|
|
|
|
replace it."
|
2014-08-30 21:52:32 +02:00
|
|
|
|
(define (manifest-entry->pattern entry)
|
|
|
|
|
(manifest-pattern
|
|
|
|
|
(name (manifest-entry-name entry))
|
|
|
|
|
(output (manifest-entry-output entry))))
|
|
|
|
|
|
2015-02-08 18:52:00 +01:00
|
|
|
|
(let loop ((input (manifest-transaction-install transaction))
|
|
|
|
|
(install '())
|
|
|
|
|
(upgrade '())
|
|
|
|
|
(downgrade '()))
|
2014-08-30 21:52:32 +02:00
|
|
|
|
(match input
|
|
|
|
|
(()
|
|
|
|
|
(let ((remove (manifest-transaction-remove transaction)))
|
|
|
|
|
(values (manifest-matching-entries manifest remove)
|
2015-02-08 18:52:00 +01:00
|
|
|
|
(reverse install) (reverse upgrade) (reverse downgrade))))
|
2014-08-30 21:52:32 +02:00
|
|
|
|
((entry rest ...)
|
|
|
|
|
;; Check whether installing ENTRY corresponds to the installation of a
|
|
|
|
|
;; new package or to an upgrade.
|
|
|
|
|
|
|
|
|
|
;; XXX: When the exact same output directory is installed, we're not
|
|
|
|
|
;; really upgrading anything. Add a check for that case.
|
|
|
|
|
(let* ((pattern (manifest-entry->pattern entry))
|
2015-02-08 18:52:00 +01:00
|
|
|
|
(previous (manifest-lookup manifest pattern))
|
|
|
|
|
(newer? (and previous
|
2015-02-09 17:18:48 +01:00
|
|
|
|
(version>=? (manifest-entry-version entry)
|
|
|
|
|
(manifest-entry-version previous)))))
|
2014-08-30 21:52:32 +02:00
|
|
|
|
(loop rest
|
2014-09-02 21:12:59 +02:00
|
|
|
|
(if previous install (cons entry install))
|
2015-02-08 18:52:00 +01:00
|
|
|
|
(if (and previous newer?)
|
2014-09-02 21:12:59 +02:00
|
|
|
|
(alist-cons previous entry upgrade)
|
2015-02-08 18:52:00 +01:00
|
|
|
|
upgrade)
|
|
|
|
|
(if (and previous (not newer?))
|
|
|
|
|
(alist-cons previous entry downgrade)
|
|
|
|
|
downgrade)))))))
|
2014-08-30 21:52:32 +02:00
|
|
|
|
|
2014-08-13 22:03:53 +02:00
|
|
|
|
(define (manifest-perform-transaction manifest transaction)
|
2016-09-06 20:19:21 +02:00
|
|
|
|
"Perform TRANSACTION on MANIFEST and return the new manifest."
|
2014-08-13 22:03:53 +02:00
|
|
|
|
(let ((install (manifest-transaction-install transaction))
|
|
|
|
|
(remove (manifest-transaction-remove transaction)))
|
|
|
|
|
(manifest-add (manifest-remove manifest remove)
|
|
|
|
|
install)))
|
|
|
|
|
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
|
|
|
|
|
;;;
|
|
|
|
|
;;; Profiles.
|
|
|
|
|
;;;
|
|
|
|
|
|
2014-08-23 18:41:14 +02:00
|
|
|
|
(define (manifest-inputs manifest)
|
2015-03-15 21:51:34 +01:00
|
|
|
|
"Return a list of <gexp-input> objects for MANIFEST."
|
2017-06-06 14:01:12 +02:00
|
|
|
|
(define entry->input
|
|
|
|
|
(match-lambda
|
|
|
|
|
(($ <manifest-entry> name version output thing deps)
|
|
|
|
|
;; THING may be a package or a file name. In the latter case, assume
|
|
|
|
|
;; it's already valid.
|
|
|
|
|
(cons (gexp-input thing output)
|
|
|
|
|
(append-map entry->input deps)))))
|
|
|
|
|
|
|
|
|
|
(append-map entry->input (manifest-entries manifest)))
|
2014-08-23 18:41:14 +02:00
|
|
|
|
|
2016-09-22 22:25:12 +02:00
|
|
|
|
(define* (manifest-lookup-package manifest name #:optional version)
|
2016-04-30 08:52:30 +02:00
|
|
|
|
"Return as a monadic value the first package or store path referenced by
|
2016-09-22 22:25:12 +02:00
|
|
|
|
MANIFEST that is named NAME and optionally has the given VERSION prefix, or #f
|
|
|
|
|
if not found."
|
2016-04-30 08:52:30 +02:00
|
|
|
|
;; Return as a monadic value the package or store path referenced by the
|
|
|
|
|
;; manifest ENTRY, or #f if not referenced.
|
|
|
|
|
(define (entry-lookup-package entry)
|
|
|
|
|
(define (find-among-inputs inputs)
|
|
|
|
|
(find (lambda (input)
|
|
|
|
|
(and (package? input)
|
2016-09-22 22:25:12 +02:00
|
|
|
|
(equal? name (package-name input))
|
|
|
|
|
(if version
|
|
|
|
|
(string-prefix? version (package-version input))
|
|
|
|
|
#t)))
|
2016-04-30 08:52:30 +02:00
|
|
|
|
inputs))
|
|
|
|
|
(define (find-among-store-items items)
|
|
|
|
|
(find (lambda (item)
|
2016-10-30 07:21:15 +01:00
|
|
|
|
(let-values (((name* version*)
|
2016-09-22 22:25:12 +02:00
|
|
|
|
(package-name->name+version
|
|
|
|
|
(store-path-package-name item))))
|
2016-10-30 07:21:15 +01:00
|
|
|
|
(and (string=? name name*)
|
2016-09-22 22:25:12 +02:00
|
|
|
|
(if version
|
2016-10-30 07:21:15 +01:00
|
|
|
|
(string-prefix? version version*)
|
2016-09-22 22:25:12 +02:00
|
|
|
|
#t))))
|
2016-04-30 08:52:30 +02:00
|
|
|
|
items))
|
|
|
|
|
|
|
|
|
|
(with-monad %store-monad
|
|
|
|
|
(match (manifest-entry-item entry)
|
|
|
|
|
((? package? package)
|
2016-06-11 04:29:45 +02:00
|
|
|
|
(match (cons (list (package-name package) package)
|
|
|
|
|
(package-transitive-inputs package))
|
2016-04-30 08:52:30 +02:00
|
|
|
|
(((labels inputs . _) ...)
|
|
|
|
|
(return (find-among-inputs inputs)))))
|
|
|
|
|
((? string? item)
|
|
|
|
|
(mlet %store-monad ((refs (references* item)))
|
2018-05-02 11:01:56 +02:00
|
|
|
|
(return (find-among-store-items refs))))
|
|
|
|
|
(item
|
|
|
|
|
;; XXX: ITEM might be a 'computed-file' or anything like that, in
|
|
|
|
|
;; which case we don't know what to do. The fix may be to check
|
|
|
|
|
;; references once ITEM is compiled, as proposed at
|
|
|
|
|
;; <https://bugs.gnu.org/29927>.
|
|
|
|
|
(return #f)))))
|
2016-04-30 08:52:30 +02:00
|
|
|
|
|
|
|
|
|
(anym %store-monad
|
|
|
|
|
entry-lookup-package (manifest-entries manifest)))
|
|
|
|
|
|
2014-08-23 18:41:14 +02:00
|
|
|
|
(define (info-dir-file manifest)
|
|
|
|
|
"Return a derivation that builds the 'dir' file for all the entries of
|
|
|
|
|
MANIFEST."
|
2014-08-27 11:00:11 +02:00
|
|
|
|
(define texinfo ;lazy reference
|
|
|
|
|
(module-ref (resolve-interface '(gnu packages texinfo)) 'texinfo))
|
|
|
|
|
(define gzip ;lazy reference
|
|
|
|
|
(module-ref (resolve-interface '(gnu packages compression)) 'gzip))
|
2018-07-04 10:52:59 +02:00
|
|
|
|
(define glibc-utf8-locales ;lazy reference
|
|
|
|
|
(module-ref (resolve-interface '(gnu packages base)) 'glibc-utf8-locales))
|
2014-08-27 11:00:11 +02:00
|
|
|
|
|
2014-08-23 18:41:14 +02:00
|
|
|
|
(define build
|
2016-07-12 00:54:22 +02:00
|
|
|
|
(with-imported-modules '((guix build utils))
|
|
|
|
|
#~(begin
|
|
|
|
|
(use-modules (guix build utils)
|
|
|
|
|
(srfi srfi-1) (srfi srfi-26)
|
|
|
|
|
(ice-9 ftw))
|
|
|
|
|
|
|
|
|
|
(define (info-file? file)
|
|
|
|
|
(or (string-suffix? ".info" file)
|
|
|
|
|
(string-suffix? ".info.gz" file)))
|
|
|
|
|
|
|
|
|
|
(define (info-files top)
|
|
|
|
|
(let ((infodir (string-append top "/share/info")))
|
|
|
|
|
(map (cut string-append infodir "/" <>)
|
|
|
|
|
(or (scandir infodir info-file?) '()))))
|
|
|
|
|
|
2018-07-04 10:52:59 +02:00
|
|
|
|
(define (info-file-language file)
|
|
|
|
|
(let* ((base (if (string-suffix? ".gz" file)
|
|
|
|
|
(basename file ".info.gz")
|
|
|
|
|
(basename file ".info")))
|
|
|
|
|
(dot (string-rindex base #\.)))
|
|
|
|
|
(if dot
|
|
|
|
|
(string-drop base (+ 1 dot))
|
|
|
|
|
"en")))
|
|
|
|
|
|
2016-07-12 00:54:22 +02:00
|
|
|
|
(define (install-info info)
|
2018-07-04 10:52:59 +02:00
|
|
|
|
(let ((language (info-file-language info)))
|
|
|
|
|
;; We need to choose a valid locale for $LANGUAGE to be honored.
|
|
|
|
|
(setenv "LC_ALL" "en_US.utf8")
|
|
|
|
|
(setenv "LANGUAGE" language)
|
|
|
|
|
(zero?
|
|
|
|
|
(system* #+(file-append texinfo "/bin/install-info")
|
|
|
|
|
"--silent" info
|
|
|
|
|
(apply string-append #$output "/share/info/dir"
|
|
|
|
|
(if (string=? "en" language)
|
|
|
|
|
'("")
|
|
|
|
|
`("." ,language)))))))
|
|
|
|
|
|
|
|
|
|
(setenv "PATH" (string-append #+gzip "/bin")) ;for info.gz files
|
|
|
|
|
(setenv "GUIX_LOCPATH"
|
|
|
|
|
#+(file-append glibc-utf8-locales "/lib/locale"))
|
2016-07-12 00:54:22 +02:00
|
|
|
|
|
|
|
|
|
(mkdir-p (string-append #$output "/share/info"))
|
|
|
|
|
(exit (every install-info
|
|
|
|
|
(append-map info-files
|
|
|
|
|
'#$(manifest-inputs manifest)))))))
|
2014-08-23 18:41:14 +02:00
|
|
|
|
|
2015-04-15 22:44:51 +02:00
|
|
|
|
(gexp->derivation "info-dir" build
|
2015-09-24 22:13:11 +02:00
|
|
|
|
#:local-build? #t
|
2018-12-19 14:36:29 +01:00
|
|
|
|
#:substitutable? #f
|
|
|
|
|
#:properties
|
|
|
|
|
`((type . profile-hook)
|
|
|
|
|
(hook . info-dir))))
|
2014-08-23 18:41:14 +02:00
|
|
|
|
|
2015-04-04 22:51:13 +02:00
|
|
|
|
(define (ghc-package-cache-file manifest)
|
|
|
|
|
"Return a derivation that builds the GHC 'package.cache' file for all the
|
2015-04-15 22:44:51 +02:00
|
|
|
|
entries of MANIFEST, or #f if MANIFEST does not have any GHC packages."
|
2016-07-12 00:54:22 +02:00
|
|
|
|
(define ghc ;lazy reference
|
2015-04-04 22:51:13 +02:00
|
|
|
|
(module-ref (resolve-interface '(gnu packages haskell)) 'ghc))
|
|
|
|
|
|
|
|
|
|
(define build
|
2016-07-12 00:54:22 +02:00
|
|
|
|
(with-imported-modules '((guix build utils))
|
|
|
|
|
#~(begin
|
|
|
|
|
(use-modules (guix build utils)
|
|
|
|
|
(srfi srfi-1) (srfi srfi-26)
|
|
|
|
|
(ice-9 ftw))
|
|
|
|
|
|
|
|
|
|
(define ghc-name-version
|
|
|
|
|
(let* ((base (basename #+ghc)))
|
|
|
|
|
(string-drop base
|
|
|
|
|
(+ 1 (string-index base #\-)))))
|
|
|
|
|
|
|
|
|
|
(define db-subdir
|
|
|
|
|
(string-append "lib/" ghc-name-version "/package.conf.d"))
|
|
|
|
|
|
|
|
|
|
(define db-dir
|
|
|
|
|
(string-append #$output "/" db-subdir))
|
|
|
|
|
|
|
|
|
|
(define (conf-files top)
|
|
|
|
|
(let ((db (string-append top "/" db-subdir)))
|
|
|
|
|
(if (file-exists? db)
|
|
|
|
|
(find-files db "\\.conf$")
|
|
|
|
|
'())))
|
|
|
|
|
|
|
|
|
|
(define (copy-conf-file conf)
|
|
|
|
|
(let ((base (basename conf)))
|
|
|
|
|
(copy-file conf (string-append db-dir "/" base))))
|
|
|
|
|
|
|
|
|
|
(system* (string-append #+ghc "/bin/ghc-pkg") "init" db-dir)
|
|
|
|
|
(for-each copy-conf-file
|
|
|
|
|
(append-map conf-files
|
|
|
|
|
(delete-duplicates
|
|
|
|
|
'#$(manifest-inputs manifest))))
|
|
|
|
|
(let ((success
|
|
|
|
|
(zero?
|
|
|
|
|
(system* (string-append #+ghc "/bin/ghc-pkg") "recache"
|
|
|
|
|
(string-append "--package-db=" db-dir)))))
|
|
|
|
|
(for-each delete-file (find-files db-dir "\\.conf$"))
|
|
|
|
|
(exit success)))))
|
2015-04-04 22:51:13 +02:00
|
|
|
|
|
2015-05-26 23:38:27 +02:00
|
|
|
|
(with-monad %store-monad
|
|
|
|
|
;; Don't depend on GHC when there's nothing to do.
|
|
|
|
|
(if (any (cut string-prefix? "ghc" <>)
|
|
|
|
|
(map manifest-entry-name (manifest-entries manifest)))
|
|
|
|
|
(gexp->derivation "ghc-package-cache" build
|
2015-09-24 22:13:11 +02:00
|
|
|
|
#:local-build? #t
|
2018-12-19 14:36:29 +01:00
|
|
|
|
#:substitutable? #f
|
|
|
|
|
#:properties
|
|
|
|
|
`((type . profile-hook)
|
|
|
|
|
(hook . ghc-package-cache)))
|
2015-05-26 23:38:27 +02:00
|
|
|
|
(return #f))))
|
2015-04-04 22:51:13 +02:00
|
|
|
|
|
2015-03-03 08:09:30 +01:00
|
|
|
|
(define (ca-certificate-bundle manifest)
|
|
|
|
|
"Return a derivation that builds a single-file bundle containing the CA
|
|
|
|
|
certificates in the /etc/ssl/certs sub-directories of the packages in
|
|
|
|
|
MANIFEST. Single-file bundles are required by programs such as Git and Lynx."
|
|
|
|
|
;; See <http://lists.gnu.org/archive/html/guix-devel/2015-02/msg00429.html>
|
|
|
|
|
;; for a discussion.
|
|
|
|
|
|
|
|
|
|
(define glibc-utf8-locales ;lazy reference
|
|
|
|
|
(module-ref (resolve-interface '(gnu packages base)) 'glibc-utf8-locales))
|
|
|
|
|
|
|
|
|
|
(define build
|
2016-07-12 00:54:22 +02:00
|
|
|
|
(with-imported-modules '((guix build utils))
|
|
|
|
|
#~(begin
|
|
|
|
|
(use-modules (guix build utils)
|
|
|
|
|
(rnrs io ports)
|
|
|
|
|
(srfi srfi-1)
|
|
|
|
|
(srfi srfi-26)
|
|
|
|
|
(ice-9 ftw)
|
|
|
|
|
(ice-9 match))
|
|
|
|
|
|
|
|
|
|
(define (pem-file? file)
|
|
|
|
|
(string-suffix? ".pem" file))
|
|
|
|
|
|
|
|
|
|
(define (ca-files top)
|
|
|
|
|
(let ((cert-dir (string-append top "/etc/ssl/certs")))
|
|
|
|
|
(map (cut string-append cert-dir "/" <>)
|
|
|
|
|
(or (scandir cert-dir pem-file?) '()))))
|
|
|
|
|
|
|
|
|
|
(define (concatenate-files files result)
|
|
|
|
|
"Make RESULT the concatenation of all of FILES."
|
|
|
|
|
(define (dump file port)
|
|
|
|
|
(display (call-with-input-file file get-string-all)
|
|
|
|
|
port)
|
|
|
|
|
(newline port)) ;required, see <https://bugs.debian.org/635570>
|
|
|
|
|
|
|
|
|
|
(call-with-output-file result
|
|
|
|
|
(lambda (port)
|
|
|
|
|
(for-each (cut dump <> port) files))))
|
|
|
|
|
|
|
|
|
|
;; Some file names in the NSS certificates are UTF-8 encoded so
|
|
|
|
|
;; install a UTF-8 locale.
|
|
|
|
|
(setenv "LOCPATH"
|
|
|
|
|
(string-append #+glibc-utf8-locales "/lib/locale/"
|
2017-12-03 02:32:16 +01:00
|
|
|
|
#+(version-major+minor
|
|
|
|
|
(package-version glibc-utf8-locales))))
|
2016-07-12 00:54:22 +02:00
|
|
|
|
(setlocale LC_ALL "en_US.utf8")
|
|
|
|
|
|
|
|
|
|
(match (append-map ca-files '#$(manifest-inputs manifest))
|
|
|
|
|
(()
|
|
|
|
|
;; Since there are no CA files, just create an empty directory. Do
|
|
|
|
|
;; not create the etc/ssl/certs sub-directory, since that would
|
|
|
|
|
;; wrongfully lead to a message about 'SSL_CERT_DIR' needing to be
|
|
|
|
|
;; defined.
|
|
|
|
|
(mkdir #$output)
|
|
|
|
|
#t)
|
|
|
|
|
((ca-files ...)
|
|
|
|
|
(let ((result (string-append #$output "/etc/ssl/certs")))
|
|
|
|
|
(mkdir-p result)
|
|
|
|
|
(concatenate-files ca-files
|
|
|
|
|
(string-append result
|
|
|
|
|
"/ca-certificates.crt"))
|
|
|
|
|
#t))))))
|
2015-03-03 08:09:30 +01:00
|
|
|
|
|
2015-04-15 22:44:51 +02:00
|
|
|
|
(gexp->derivation "ca-certificate-bundle" build
|
2015-09-24 22:13:11 +02:00
|
|
|
|
#:local-build? #t
|
2018-12-19 14:36:29 +01:00
|
|
|
|
#:substitutable? #f
|
|
|
|
|
#:properties
|
|
|
|
|
`((type . profile-hook)
|
|
|
|
|
(hook . ca-certificate-bundle))))
|
2015-04-15 22:44:51 +02:00
|
|
|
|
|
2018-05-15 14:49:17 +02:00
|
|
|
|
(define (glib-schemas manifest)
|
|
|
|
|
"Return a derivation that unions all schemas from manifest entries and
|
|
|
|
|
creates the Glib 'gschemas.compiled' file."
|
|
|
|
|
(define glib ; lazy reference
|
|
|
|
|
(module-ref (resolve-interface '(gnu packages glib)) 'glib))
|
|
|
|
|
|
|
|
|
|
(mlet %store-monad ((%glib (manifest-lookup-package manifest "glib"))
|
|
|
|
|
;; XXX: Can't use glib-compile-schemas corresponding
|
|
|
|
|
;; to the glib referenced by 'manifest'. Because
|
|
|
|
|
;; '%glib' can be either a package or store path, and
|
|
|
|
|
;; there's no way to get the "bin" output for the later.
|
|
|
|
|
(glib-compile-schemas
|
|
|
|
|
-> #~(string-append #+glib:bin
|
|
|
|
|
"/bin/glib-compile-schemas")))
|
|
|
|
|
|
|
|
|
|
(define build
|
|
|
|
|
(with-imported-modules '((guix build utils)
|
|
|
|
|
(guix build union)
|
|
|
|
|
(guix build profiles)
|
|
|
|
|
(guix search-paths)
|
|
|
|
|
(guix records))
|
|
|
|
|
#~(begin
|
|
|
|
|
(use-modules (guix build utils)
|
|
|
|
|
(guix build union)
|
|
|
|
|
(guix build profiles)
|
|
|
|
|
(srfi srfi-26))
|
|
|
|
|
|
|
|
|
|
(let* ((destdir (string-append #$output "/share/glib-2.0/schemas"))
|
|
|
|
|
(schemadirs (filter file-exists?
|
|
|
|
|
(map (cut string-append <> "/share/glib-2.0/schemas")
|
|
|
|
|
'#$(manifest-inputs manifest)))))
|
|
|
|
|
|
|
|
|
|
;; Union all the schemas.
|
|
|
|
|
(mkdir-p (string-append #$output "/share/glib-2.0"))
|
|
|
|
|
(union-build destdir schemadirs
|
|
|
|
|
#:log-port (%make-void-port "w"))
|
|
|
|
|
|
|
|
|
|
(let ((dir destdir))
|
|
|
|
|
(when (file-is-directory? dir)
|
|
|
|
|
(ensure-writable-directory dir)
|
|
|
|
|
(invoke #+glib-compile-schemas
|
|
|
|
|
(string-append "--targetdir=" dir)
|
|
|
|
|
dir)))))))
|
|
|
|
|
|
|
|
|
|
;; Don't run the hook when there's nothing to do.
|
|
|
|
|
(if %glib
|
|
|
|
|
(gexp->derivation "glib-schemas" build
|
|
|
|
|
#:local-build? #t
|
2018-12-19 14:36:29 +01:00
|
|
|
|
#:substitutable? #f
|
|
|
|
|
#:properties
|
|
|
|
|
`((type . profile-hook)
|
|
|
|
|
(hook . glib-schemas)))
|
2018-05-15 14:49:17 +02:00
|
|
|
|
(return #f))))
|
|
|
|
|
|
2015-05-27 14:58:27 +02:00
|
|
|
|
(define (gtk-icon-themes manifest)
|
|
|
|
|
"Return a derivation that unions all icon themes from manifest entries and
|
|
|
|
|
creates the GTK+ 'icon-theme.cache' file for each theme."
|
2016-08-06 12:28:57 +02:00
|
|
|
|
(define gtk+ ; lazy reference
|
|
|
|
|
(module-ref (resolve-interface '(gnu packages gtk)) 'gtk+))
|
|
|
|
|
|
|
|
|
|
(mlet %store-monad ((%gtk+ (manifest-lookup-package manifest "gtk+"))
|
|
|
|
|
;; XXX: Can't use gtk-update-icon-cache corresponding
|
|
|
|
|
;; to the gtk+ referenced by 'manifest'. Because
|
|
|
|
|
;; '%gtk+' can be either a package or store path, and
|
|
|
|
|
;; there's no way to get the "bin" output for the later.
|
|
|
|
|
(gtk-update-icon-cache
|
|
|
|
|
-> #~(string-append #+gtk+:bin
|
|
|
|
|
"/bin/gtk-update-icon-cache")))
|
|
|
|
|
|
2015-05-27 14:58:27 +02:00
|
|
|
|
(define build
|
2016-07-12 00:54:22 +02:00
|
|
|
|
(with-imported-modules '((guix build utils)
|
|
|
|
|
(guix build union)
|
|
|
|
|
(guix build profiles)
|
|
|
|
|
(guix search-paths)
|
|
|
|
|
(guix records))
|
|
|
|
|
#~(begin
|
|
|
|
|
(use-modules (guix build utils)
|
|
|
|
|
(guix build union)
|
|
|
|
|
(guix build profiles)
|
|
|
|
|
(srfi srfi-26)
|
|
|
|
|
(ice-9 ftw))
|
|
|
|
|
|
|
|
|
|
(let* ((destdir (string-append #$output "/share/icons"))
|
|
|
|
|
(icondirs (filter file-exists?
|
|
|
|
|
(map (cut string-append <> "/share/icons")
|
2016-08-06 12:28:57 +02:00
|
|
|
|
'#$(manifest-inputs manifest)))))
|
2016-07-12 00:54:22 +02:00
|
|
|
|
|
|
|
|
|
;; Union all the icons.
|
|
|
|
|
(mkdir-p (string-append #$output "/share"))
|
|
|
|
|
(union-build destdir icondirs
|
|
|
|
|
#:log-port (%make-void-port "w"))
|
|
|
|
|
|
|
|
|
|
;; Update the 'icon-theme.cache' file for each icon theme.
|
|
|
|
|
(for-each
|
|
|
|
|
(lambda (theme)
|
|
|
|
|
(let ((dir (string-append destdir "/" theme)))
|
|
|
|
|
;; Occasionally DESTDIR contains plain files, such as
|
|
|
|
|
;; "abiword_48.png". Ignore these.
|
|
|
|
|
(when (file-is-directory? dir)
|
|
|
|
|
(ensure-writable-directory dir)
|
2016-08-06 12:28:57 +02:00
|
|
|
|
(system* #+gtk-update-icon-cache "-t" dir "--quiet"))))
|
2016-07-12 00:54:22 +02:00
|
|
|
|
(scandir destdir (negate (cut member <> '("." "..")))))))))
|
2015-05-27 14:58:27 +02:00
|
|
|
|
|
|
|
|
|
;; Don't run the hook when there's nothing to do.
|
2016-08-06 12:28:57 +02:00
|
|
|
|
(if %gtk+
|
2015-05-27 14:58:27 +02:00
|
|
|
|
(gexp->derivation "gtk-icon-themes" build
|
2015-09-24 22:13:11 +02:00
|
|
|
|
#:local-build? #t
|
2018-12-19 14:36:29 +01:00
|
|
|
|
#:substitutable? #f
|
|
|
|
|
#:properties
|
|
|
|
|
`((type . profile-hook)
|
|
|
|
|
(hook . gtk-icon-themes)))
|
2015-05-27 14:58:27 +02:00
|
|
|
|
(return #f))))
|
|
|
|
|
|
2016-09-22 22:27:06 +02:00
|
|
|
|
(define (gtk-im-modules manifest)
|
|
|
|
|
"Return a derivation that builds the cache files for input method modules
|
|
|
|
|
for both major versions of GTK+."
|
|
|
|
|
|
|
|
|
|
(mlet %store-monad ((gtk+ (manifest-lookup-package manifest "gtk+" "3"))
|
|
|
|
|
(gtk+-2 (manifest-lookup-package manifest "gtk+" "2")))
|
|
|
|
|
|
2017-02-08 13:10:46 +01:00
|
|
|
|
(define (build gtk gtk-version query)
|
2016-09-22 22:27:06 +02:00
|
|
|
|
(let ((major (string-take gtk-version 1)))
|
|
|
|
|
(with-imported-modules '((guix build utils)
|
|
|
|
|
(guix build union)
|
|
|
|
|
(guix build profiles)
|
|
|
|
|
(guix search-paths)
|
|
|
|
|
(guix records))
|
|
|
|
|
#~(begin
|
|
|
|
|
(use-modules (guix build utils)
|
|
|
|
|
(guix build union)
|
|
|
|
|
(guix build profiles)
|
|
|
|
|
(ice-9 popen)
|
|
|
|
|
(srfi srfi-1)
|
|
|
|
|
(srfi srfi-26))
|
|
|
|
|
|
|
|
|
|
(let* ((prefix (string-append "/lib/gtk-" #$major ".0/"
|
|
|
|
|
#$gtk-version))
|
|
|
|
|
(destdir (string-append #$output prefix))
|
|
|
|
|
(moddirs (cons (string-append #$gtk prefix "/immodules")
|
|
|
|
|
(filter file-exists?
|
|
|
|
|
(map (cut string-append <> prefix "/immodules")
|
|
|
|
|
'#$(manifest-inputs manifest)))))
|
|
|
|
|
(modules (append-map (cut find-files <> "\\.so$")
|
|
|
|
|
moddirs)))
|
|
|
|
|
|
|
|
|
|
;; Generate a new immodules cache file.
|
|
|
|
|
(mkdir-p (string-append #$output prefix))
|
2017-02-08 13:10:46 +01:00
|
|
|
|
(let ((pipe (apply open-pipe* OPEN_READ #$query modules))
|
2016-09-22 22:27:06 +02:00
|
|
|
|
(outfile (string-append #$output prefix
|
|
|
|
|
"/immodules-gtk" #$major ".cache")))
|
|
|
|
|
(dynamic-wind
|
|
|
|
|
(const #t)
|
|
|
|
|
(lambda ()
|
|
|
|
|
(call-with-output-file outfile
|
|
|
|
|
(lambda (out)
|
|
|
|
|
(while (not (eof-object? (peek-char pipe)))
|
|
|
|
|
(write-char (read-char pipe) out))))
|
|
|
|
|
#t)
|
|
|
|
|
(lambda ()
|
|
|
|
|
(close-pipe pipe)))))))))
|
|
|
|
|
|
|
|
|
|
;; Don't run the hook when there's nothing to do.
|
2017-02-08 13:10:46 +01:00
|
|
|
|
(let* ((pkg-gtk+ (module-ref ; lazy reference
|
|
|
|
|
(resolve-interface '(gnu packages gtk)) 'gtk+))
|
|
|
|
|
(gexp #~(begin
|
|
|
|
|
#$(if gtk+
|
|
|
|
|
(build
|
|
|
|
|
gtk+ "3.0.0"
|
|
|
|
|
;; Use 'gtk-query-immodules-3.0' from the 'bin'
|
|
|
|
|
;; output of latest gtk+ package.
|
|
|
|
|
#~(string-append
|
|
|
|
|
#$pkg-gtk+:bin "/bin/gtk-query-immodules-3.0"))
|
|
|
|
|
#t)
|
|
|
|
|
#$(if gtk+-2
|
|
|
|
|
(build
|
|
|
|
|
gtk+-2 "2.10.0"
|
|
|
|
|
#~(string-append
|
|
|
|
|
#$gtk+-2 "/bin/gtk-query-immodules-2.0"))
|
|
|
|
|
#t))))
|
2016-09-22 22:27:06 +02:00
|
|
|
|
(if (or gtk+ gtk+-2)
|
|
|
|
|
(gexp->derivation "gtk-im-modules" gexp
|
|
|
|
|
#:local-build? #t
|
2018-12-19 14:36:29 +01:00
|
|
|
|
#:substitutable? #f
|
|
|
|
|
#:properties
|
|
|
|
|
`((type . profile-hook)
|
|
|
|
|
(hook . gtk-im-modules)))
|
2016-09-22 22:27:06 +02:00
|
|
|
|
(return #f)))))
|
|
|
|
|
|
2016-02-04 08:33:07 +01:00
|
|
|
|
(define (xdg-desktop-database manifest)
|
|
|
|
|
"Return a derivation that builds the @file{mimeinfo.cache} database from
|
|
|
|
|
desktop files. It's used to query what applications can handle a given
|
|
|
|
|
MIME type."
|
2017-07-03 17:11:13 +02:00
|
|
|
|
(define desktop-file-utils ; lazy reference
|
|
|
|
|
(module-ref (resolve-interface '(gnu packages freedesktop))
|
|
|
|
|
'desktop-file-utils))
|
|
|
|
|
|
|
|
|
|
(mlet %store-monad ((glib
|
2016-04-30 08:52:30 +02:00
|
|
|
|
(manifest-lookup-package
|
2017-07-03 17:11:13 +02:00
|
|
|
|
manifest "glib")))
|
2016-04-30 08:52:30 +02:00
|
|
|
|
(define build
|
2016-07-12 00:54:22 +02:00
|
|
|
|
(with-imported-modules '((guix build utils)
|
|
|
|
|
(guix build union))
|
|
|
|
|
#~(begin
|
|
|
|
|
(use-modules (srfi srfi-26)
|
|
|
|
|
(guix build utils)
|
|
|
|
|
(guix build union))
|
|
|
|
|
(let* ((destdir (string-append #$output "/share/applications"))
|
|
|
|
|
(appdirs (filter file-exists?
|
|
|
|
|
(map (cut string-append <>
|
|
|
|
|
"/share/applications")
|
|
|
|
|
'#$(manifest-inputs manifest))))
|
|
|
|
|
(update-desktop-database (string-append
|
|
|
|
|
#+desktop-file-utils
|
|
|
|
|
"/bin/update-desktop-database")))
|
|
|
|
|
(mkdir-p (string-append #$output "/share"))
|
|
|
|
|
(union-build destdir appdirs
|
|
|
|
|
#:log-port (%make-void-port "w"))
|
|
|
|
|
(exit (zero? (system* update-desktop-database destdir)))))))
|
2016-02-04 08:33:07 +01:00
|
|
|
|
|
2017-07-03 17:11:13 +02:00
|
|
|
|
;; Don't run the hook when 'glib' is not referenced.
|
|
|
|
|
(if glib
|
2016-04-30 08:52:30 +02:00
|
|
|
|
(gexp->derivation "xdg-desktop-database" build
|
|
|
|
|
#:local-build? #t
|
2018-12-19 14:36:29 +01:00
|
|
|
|
#:substitutable? #f
|
|
|
|
|
#:properties
|
|
|
|
|
`((type . profile-hook)
|
|
|
|
|
(hook . xdg-desktop-database)))
|
2016-04-30 08:52:30 +02:00
|
|
|
|
(return #f))))
|
2016-02-04 08:33:07 +01:00
|
|
|
|
|
2016-02-04 08:35:03 +01:00
|
|
|
|
(define (xdg-mime-database manifest)
|
|
|
|
|
"Return a derivation that builds the @file{mime.cache} database from manifest
|
|
|
|
|
entries. It's used to query the MIME type of a given file."
|
2016-08-11 14:59:16 +02:00
|
|
|
|
(define shared-mime-info ; lazy reference
|
|
|
|
|
(module-ref (resolve-interface '(gnu packages gnome)) 'shared-mime-info))
|
|
|
|
|
|
|
|
|
|
(mlet %store-monad ((glib
|
2016-04-30 08:52:30 +02:00
|
|
|
|
(manifest-lookup-package
|
2016-08-11 14:59:16 +02:00
|
|
|
|
manifest "glib")))
|
2016-04-30 08:52:30 +02:00
|
|
|
|
(define build
|
2016-07-12 00:54:22 +02:00
|
|
|
|
(with-imported-modules '((guix build utils)
|
|
|
|
|
(guix build union))
|
|
|
|
|
#~(begin
|
|
|
|
|
(use-modules (srfi srfi-26)
|
|
|
|
|
(guix build utils)
|
|
|
|
|
(guix build union))
|
|
|
|
|
(let* ((datadir (string-append #$output "/share"))
|
|
|
|
|
(destdir (string-append datadir "/mime"))
|
|
|
|
|
(pkgdirs (filter file-exists?
|
|
|
|
|
(map (cut string-append <>
|
|
|
|
|
"/share/mime/packages")
|
2016-08-11 14:59:16 +02:00
|
|
|
|
(cons #+shared-mime-info
|
|
|
|
|
'#$(manifest-inputs manifest)))))
|
2016-07-12 00:54:22 +02:00
|
|
|
|
(update-mime-database (string-append
|
|
|
|
|
#+shared-mime-info
|
|
|
|
|
"/bin/update-mime-database")))
|
|
|
|
|
(mkdir-p destdir)
|
|
|
|
|
(union-build (string-append destdir "/packages") pkgdirs
|
|
|
|
|
#:log-port (%make-void-port "w"))
|
|
|
|
|
(setenv "XDG_DATA_HOME" datadir)
|
|
|
|
|
(exit (zero? (system* update-mime-database destdir)))))))
|
2016-04-30 08:52:30 +02:00
|
|
|
|
|
2016-08-11 14:59:16 +02:00
|
|
|
|
;; Don't run the hook when there are no GLib based applications.
|
|
|
|
|
(if glib
|
2016-04-30 08:52:30 +02:00
|
|
|
|
(gexp->derivation "xdg-mime-database" build
|
|
|
|
|
#:local-build? #t
|
2018-12-19 14:36:29 +01:00
|
|
|
|
#:substitutable? #f
|
|
|
|
|
#:properties
|
|
|
|
|
`((type . profile-hook)
|
|
|
|
|
(hook . xdg-mime-database)))
|
2016-04-30 08:52:30 +02:00
|
|
|
|
(return #f))))
|
2016-02-04 08:35:03 +01:00
|
|
|
|
|
2017-03-12 12:53:59 +01:00
|
|
|
|
;; Several font packages may install font files into same directory, so
|
|
|
|
|
;; fonts.dir and fonts.scale file should be generated here, instead of in
|
|
|
|
|
;; packages.
|
2016-06-30 21:01:06 +02:00
|
|
|
|
(define (fonts-dir-file manifest)
|
|
|
|
|
"Return a derivation that builds the @file{fonts.dir} and @file{fonts.scale}
|
2017-03-12 12:53:59 +01:00
|
|
|
|
files for the fonts of the @var{manifest} entries."
|
2016-06-30 21:01:06 +02:00
|
|
|
|
(define mkfontscale
|
|
|
|
|
(module-ref (resolve-interface '(gnu packages xorg)) 'mkfontscale))
|
|
|
|
|
|
|
|
|
|
(define mkfontdir
|
|
|
|
|
(module-ref (resolve-interface '(gnu packages xorg)) 'mkfontdir))
|
|
|
|
|
|
|
|
|
|
(define build
|
|
|
|
|
#~(begin
|
|
|
|
|
(use-modules (srfi srfi-26)
|
|
|
|
|
(guix build utils)
|
|
|
|
|
(guix build union))
|
2017-03-12 12:53:59 +01:00
|
|
|
|
(let ((fonts-dirs (filter file-exists?
|
|
|
|
|
(map (cut string-append <>
|
|
|
|
|
"/share/fonts")
|
|
|
|
|
'#$(manifest-inputs manifest)))))
|
2016-06-30 21:01:06 +02:00
|
|
|
|
(mkdir #$output)
|
2017-03-12 12:53:59 +01:00
|
|
|
|
(if (null? fonts-dirs)
|
2016-06-30 21:01:06 +02:00
|
|
|
|
(exit #t)
|
2017-03-12 12:53:59 +01:00
|
|
|
|
(let* ((share-dir (string-append #$output "/share"))
|
|
|
|
|
(fonts-dir (string-append share-dir "/fonts"))
|
2016-06-30 21:01:06 +02:00
|
|
|
|
(mkfontscale (string-append #+mkfontscale
|
|
|
|
|
"/bin/mkfontscale"))
|
|
|
|
|
(mkfontdir (string-append #+mkfontdir
|
2017-03-12 12:53:59 +01:00
|
|
|
|
"/bin/mkfontdir"))
|
|
|
|
|
(empty-file? (lambda (filename)
|
|
|
|
|
(call-with-ascii-input-file filename
|
|
|
|
|
(lambda (p)
|
|
|
|
|
(eqv? #\0 (read-char p))))))
|
|
|
|
|
(fonts-dir-file "fonts.dir")
|
|
|
|
|
(fonts-scale-file "fonts.scale"))
|
|
|
|
|
(mkdir-p share-dir)
|
|
|
|
|
;; Create all sub-directories, because we may create fonts.dir
|
|
|
|
|
;; and fonts.scale files in the sub-directories.
|
|
|
|
|
(union-build fonts-dir fonts-dirs
|
|
|
|
|
#:log-port (%make-void-port "w")
|
|
|
|
|
#:create-all-directories? #t)
|
|
|
|
|
(let ((directories (find-files fonts-dir
|
|
|
|
|
(lambda (file stat)
|
|
|
|
|
(eq? 'directory (stat:type stat)))
|
|
|
|
|
#:directories? #t)))
|
|
|
|
|
(for-each (lambda (dir)
|
|
|
|
|
(with-directory-excursion dir
|
|
|
|
|
(when (file-exists? fonts-scale-file)
|
|
|
|
|
(delete-file fonts-scale-file))
|
|
|
|
|
(when (file-exists? fonts-dir-file)
|
|
|
|
|
(delete-file fonts-dir-file))
|
|
|
|
|
(unless (and (zero? (system* mkfontscale))
|
|
|
|
|
(zero? (system* mkfontdir)))
|
|
|
|
|
(exit #f))
|
2017-08-08 16:05:58 +02:00
|
|
|
|
(when (and (file-exists? fonts-scale-file)
|
|
|
|
|
(empty-file? fonts-scale-file))
|
2017-03-12 12:53:59 +01:00
|
|
|
|
(delete-file fonts-scale-file))
|
2017-08-08 16:05:58 +02:00
|
|
|
|
(when (and (file-exists? fonts-dir-file)
|
|
|
|
|
(empty-file? fonts-dir-file))
|
2017-03-12 12:53:59 +01:00
|
|
|
|
(delete-file fonts-dir-file))))
|
|
|
|
|
directories)))))))
|
2016-06-30 21:01:06 +02:00
|
|
|
|
|
|
|
|
|
(gexp->derivation "fonts-dir" build
|
|
|
|
|
#:modules '((guix build utils)
|
2017-03-12 12:53:59 +01:00
|
|
|
|
(guix build union)
|
|
|
|
|
(srfi srfi-26))
|
2016-06-30 21:01:06 +02:00
|
|
|
|
#:local-build? #t
|
2018-12-19 14:36:29 +01:00
|
|
|
|
#:substitutable? #f
|
|
|
|
|
#:properties
|
|
|
|
|
`((type . profile-hook)
|
|
|
|
|
(hook . fonts-dir))))
|
2016-06-30 21:01:06 +02:00
|
|
|
|
|
2017-04-05 10:09:22 +02:00
|
|
|
|
(define (manual-database manifest)
|
|
|
|
|
"Return a derivation that builds the manual page database (\"mandb\") for
|
|
|
|
|
the entries in MANIFEST."
|
2017-12-15 22:16:18 +01:00
|
|
|
|
(define gdbm-ffi
|
|
|
|
|
(module-ref (resolve-interface '(gnu packages guile))
|
|
|
|
|
'guile-gdbm-ffi))
|
|
|
|
|
|
|
|
|
|
(define zlib
|
|
|
|
|
(module-ref (resolve-interface '(gnu packages compression)) 'zlib))
|
|
|
|
|
|
|
|
|
|
(define config.scm
|
|
|
|
|
(scheme-file "config.scm"
|
|
|
|
|
#~(begin
|
2018-10-09 11:49:26 +02:00
|
|
|
|
(define-module #$'(guix config) ;placate Geiser
|
2017-12-15 22:16:18 +01:00
|
|
|
|
#:export (%libz))
|
|
|
|
|
|
|
|
|
|
(define %libz
|
|
|
|
|
#+(file-append zlib "/lib/libz")))))
|
|
|
|
|
|
|
|
|
|
(define modules
|
|
|
|
|
(cons `((guix config) => ,config.scm)
|
|
|
|
|
(delete '(guix config)
|
|
|
|
|
(source-module-closure `((guix build utils)
|
|
|
|
|
(guix man-db))))))
|
2017-04-05 10:09:22 +02:00
|
|
|
|
|
|
|
|
|
(define build
|
2017-12-15 22:16:18 +01:00
|
|
|
|
(with-imported-modules modules
|
2018-05-28 22:00:11 +02:00
|
|
|
|
(with-extensions (list gdbm-ffi) ;for (guix man-db)
|
|
|
|
|
#~(begin
|
|
|
|
|
(use-modules (guix man-db)
|
|
|
|
|
(guix build utils)
|
|
|
|
|
(srfi srfi-1)
|
|
|
|
|
(srfi srfi-19))
|
|
|
|
|
|
|
|
|
|
(define (compute-entries)
|
2019-02-01 19:25:38 +01:00
|
|
|
|
;; This is the most expensive part (I/O and CPU, due to
|
|
|
|
|
;; decompression), so report progress as we traverse INPUTS.
|
|
|
|
|
(let* ((inputs '#$(manifest-inputs manifest))
|
|
|
|
|
(total (length inputs)))
|
|
|
|
|
(append-map (lambda (directory count)
|
|
|
|
|
(format #t "\r[~3d/~3d] building list of \
|
|
|
|
|
man-db entries..."
|
|
|
|
|
count total)
|
|
|
|
|
(force-output)
|
|
|
|
|
(let ((man (string-append directory
|
|
|
|
|
"/share/man")))
|
|
|
|
|
(if (directory-exists? man)
|
|
|
|
|
(mandb-entries man)
|
|
|
|
|
'())))
|
|
|
|
|
inputs
|
|
|
|
|
(iota total 1))))
|
2018-05-28 22:00:11 +02:00
|
|
|
|
|
|
|
|
|
(define man-directory
|
|
|
|
|
(string-append #$output "/share/man"))
|
|
|
|
|
|
|
|
|
|
(mkdir-p man-directory)
|
|
|
|
|
|
|
|
|
|
(format #t "Creating manual page database...~%")
|
|
|
|
|
(force-output)
|
|
|
|
|
(let* ((start (current-time))
|
|
|
|
|
(entries (compute-entries))
|
|
|
|
|
(_ (write-mandb-database (string-append man-directory
|
|
|
|
|
"/index.db")
|
|
|
|
|
entries))
|
|
|
|
|
(duration (time-difference (current-time) start)))
|
2019-02-01 19:25:38 +01:00
|
|
|
|
(newline)
|
2018-05-28 22:00:11 +02:00
|
|
|
|
(format #t "~a entries processed in ~,1f s~%"
|
|
|
|
|
(length entries)
|
|
|
|
|
(+ (time-second duration)
|
|
|
|
|
(* (time-nanosecond duration) (expt 10 -9))))
|
|
|
|
|
(force-output))))))
|
2017-04-05 10:09:22 +02:00
|
|
|
|
|
|
|
|
|
(gexp->derivation "manual-database" build
|
2017-12-15 22:16:18 +01:00
|
|
|
|
|
|
|
|
|
;; Work around GDBM 1.13 issue whereby uninitialized bytes
|
|
|
|
|
;; get written to disk:
|
|
|
|
|
;; <https://debbugs.gnu.org/cgi/bugreport.cgi?bug=29654#23>.
|
|
|
|
|
#:env-vars `(("MALLOC_PERTURB_" . "1"))
|
|
|
|
|
|
2018-12-19 14:36:29 +01:00
|
|
|
|
#:local-build? #t
|
|
|
|
|
#:properties
|
|
|
|
|
`((type . profile-hook)
|
|
|
|
|
(hook . manual-database))))
|
2017-04-05 10:09:22 +02:00
|
|
|
|
|
2019-01-15 13:03:48 +01:00
|
|
|
|
(define (texlive-configuration manifest)
|
|
|
|
|
"Return a derivation that builds a TeXlive configuration for the entries in
|
|
|
|
|
MANIFEST."
|
|
|
|
|
(define entry->texlive-input
|
|
|
|
|
(match-lambda
|
|
|
|
|
(($ <manifest-entry> name version output thing deps)
|
|
|
|
|
(if (string-prefix? "texlive-" name)
|
|
|
|
|
(cons (gexp-input thing output)
|
|
|
|
|
(append-map entry->texlive-input deps))
|
|
|
|
|
'()))))
|
|
|
|
|
(define build
|
|
|
|
|
(with-imported-modules '((guix build utils)
|
|
|
|
|
(guix build union))
|
|
|
|
|
#~(begin
|
|
|
|
|
(use-modules (guix build utils)
|
|
|
|
|
(guix build union))
|
|
|
|
|
|
|
|
|
|
;; Build a modifiable union of all texlive inputs. We do this so
|
|
|
|
|
;; that TeX live can resolve the parent and grandparent directories
|
|
|
|
|
;; correctly. There might be a more elegant way to accomplish this.
|
|
|
|
|
(union-build #$output
|
|
|
|
|
'#$(append-map entry->texlive-input
|
|
|
|
|
(manifest-entries manifest))
|
|
|
|
|
#:create-all-directories? #t
|
|
|
|
|
#:log-port (%make-void-port "w"))
|
2019-01-17 22:00:19 +01:00
|
|
|
|
(let ((texmf.cnf (string-append
|
|
|
|
|
#$output
|
|
|
|
|
"/share/texmf-dist/web2c/texmf.cnf")))
|
|
|
|
|
(when (file-exists? texmf.cnf)
|
|
|
|
|
(substitute* texmf.cnf
|
|
|
|
|
(("^TEXMFROOT = .*")
|
|
|
|
|
(string-append "TEXMFROOT = " #$output "/share\n"))
|
|
|
|
|
(("^TEXMF = .*")
|
|
|
|
|
"TEXMF = $TEXMFROOT/share/texmf-dist\n"))))
|
2019-01-15 13:03:48 +01:00
|
|
|
|
#t)))
|
|
|
|
|
|
|
|
|
|
(with-monad %store-monad
|
|
|
|
|
(if (any (cut string-prefix? "texlive-" <>)
|
|
|
|
|
(map manifest-entry-name (manifest-entries manifest)))
|
|
|
|
|
(gexp->derivation "texlive-configuration" build
|
|
|
|
|
#:substitutable? #f
|
|
|
|
|
#:local-build? #t
|
|
|
|
|
#:properties
|
|
|
|
|
`((type . profile-hook)
|
|
|
|
|
(hook . texlive-configuration)))
|
|
|
|
|
(return #f))))
|
|
|
|
|
|
2015-04-15 22:44:51 +02:00
|
|
|
|
(define %default-profile-hooks
|
|
|
|
|
;; This is the list of derivation-returning procedures that are called by
|
|
|
|
|
;; default when making a non-empty profile.
|
|
|
|
|
(list info-dir-file
|
2017-04-05 10:09:22 +02:00
|
|
|
|
manual-database
|
2016-06-30 21:01:06 +02:00
|
|
|
|
fonts-dir-file
|
2015-04-15 22:44:51 +02:00
|
|
|
|
ghc-package-cache-file
|
2015-05-27 14:58:27 +02:00
|
|
|
|
ca-certificate-bundle
|
2018-05-15 14:49:17 +02:00
|
|
|
|
glib-schemas
|
2016-02-04 08:33:07 +01:00
|
|
|
|
gtk-icon-themes
|
2016-09-22 22:27:06 +02:00
|
|
|
|
gtk-im-modules
|
2019-01-15 13:03:48 +01:00
|
|
|
|
texlive-configuration
|
2016-02-04 08:35:03 +01:00
|
|
|
|
xdg-desktop-database
|
|
|
|
|
xdg-mime-database))
|
2015-03-03 08:09:30 +01:00
|
|
|
|
|
|
|
|
|
(define* (profile-derivation manifest
|
|
|
|
|
#:key
|
2016-02-12 19:12:18 +01:00
|
|
|
|
(hooks %default-profile-hooks)
|
2016-12-17 12:43:10 +01:00
|
|
|
|
(locales? #t)
|
2017-06-21 16:50:59 +02:00
|
|
|
|
(allow-collisions? #f)
|
2018-04-28 22:20:36 +02:00
|
|
|
|
(relative-symlinks? #f)
|
2017-03-17 21:48:40 +01:00
|
|
|
|
system target)
|
2014-08-23 18:41:14 +02:00
|
|
|
|
"Return a derivation that builds a profile (aka. 'user environment') with
|
2015-04-15 22:44:51 +02:00
|
|
|
|
the given MANIFEST. The profile includes additional derivations returned by
|
2016-12-17 12:43:10 +01:00
|
|
|
|
the monadic procedures listed in HOOKS--such as an Info 'dir' file, etc.
|
2017-06-21 16:50:59 +02:00
|
|
|
|
Unless ALLOW-COLLISIONS? is true, a '&profile-collision-error' is raised if
|
|
|
|
|
entries in MANIFEST collide (for instance if there are two same-name packages
|
|
|
|
|
with a different version number.)
|
2016-12-17 12:43:10 +01:00
|
|
|
|
|
|
|
|
|
When LOCALES? is true, the build is performed under a UTF-8 locale; this adds
|
2017-03-17 21:48:40 +01:00
|
|
|
|
a dependency on the 'glibc-utf8-locales' package.
|
|
|
|
|
|
2018-04-28 22:20:36 +02:00
|
|
|
|
When RELATIVE-SYMLINKS? is true, use relative file names for symlink targets.
|
|
|
|
|
This is one of the things to do for the result to be relocatable.
|
|
|
|
|
|
2017-03-17 21:48:40 +01:00
|
|
|
|
When TARGET is true, it must be a GNU triplet, and the packages in MANIFEST
|
|
|
|
|
are cross-built for TARGET."
|
2017-06-07 09:51:55 +02:00
|
|
|
|
(mlet* %store-monad ((system (if system
|
|
|
|
|
(return system)
|
|
|
|
|
(current-system)))
|
2017-06-21 16:50:59 +02:00
|
|
|
|
(ok? (if allow-collisions?
|
|
|
|
|
(return #t)
|
|
|
|
|
(check-for-collisions manifest system
|
|
|
|
|
#:target target)))
|
2017-06-07 09:51:55 +02:00
|
|
|
|
(extras (if (null? (manifest-entries manifest))
|
|
|
|
|
(return '())
|
2017-06-25 15:33:58 +02:00
|
|
|
|
(mapm %store-monad
|
|
|
|
|
(lambda (hook)
|
|
|
|
|
(hook manifest))
|
|
|
|
|
hooks))))
|
2014-08-23 18:41:14 +02:00
|
|
|
|
(define inputs
|
2015-05-27 15:03:21 +02:00
|
|
|
|
(append (filter-map (lambda (drv)
|
|
|
|
|
(and (derivation? drv)
|
|
|
|
|
(gexp-input drv)))
|
2015-05-26 23:38:27 +02:00
|
|
|
|
extras)
|
2015-03-03 08:09:30 +01:00
|
|
|
|
(manifest-inputs manifest)))
|
2014-08-23 18:41:14 +02:00
|
|
|
|
|
2016-12-16 18:01:08 +01:00
|
|
|
|
(define glibc-utf8-locales ;lazy reference
|
|
|
|
|
(module-ref (resolve-interface '(gnu packages base))
|
|
|
|
|
'glibc-utf8-locales))
|
|
|
|
|
|
2016-12-17 12:43:10 +01:00
|
|
|
|
(define set-utf8-locale
|
|
|
|
|
;; Some file names (e.g., in 'nss-certs') are UTF-8 encoded so
|
|
|
|
|
;; install a UTF-8 locale.
|
|
|
|
|
#~(begin
|
|
|
|
|
(setenv "LOCPATH"
|
|
|
|
|
#$(file-append glibc-utf8-locales "/lib/locale/"
|
2017-12-03 02:32:16 +01:00
|
|
|
|
(version-major+minor
|
|
|
|
|
(package-version glibc-utf8-locales))))
|
2016-12-17 12:43:10 +01:00
|
|
|
|
(setlocale LC_ALL "en_US.utf8")))
|
|
|
|
|
|
2014-08-23 18:41:14 +02:00
|
|
|
|
(define builder
|
2016-07-12 00:54:22 +02:00
|
|
|
|
(with-imported-modules '((guix build profiles)
|
|
|
|
|
(guix build union)
|
|
|
|
|
(guix build utils)
|
|
|
|
|
(guix search-paths)
|
|
|
|
|
(guix records))
|
|
|
|
|
#~(begin
|
|
|
|
|
(use-modules (guix build profiles)
|
|
|
|
|
(guix search-paths)
|
|
|
|
|
(srfi srfi-1))
|
|
|
|
|
|
|
|
|
|
(setvbuf (current-output-port) _IOLBF)
|
|
|
|
|
(setvbuf (current-error-port) _IOLBF)
|
|
|
|
|
|
2016-12-17 12:43:10 +01:00
|
|
|
|
#+(if locales? set-utf8-locale #t)
|
2016-12-16 18:01:08 +01:00
|
|
|
|
|
2016-07-12 00:54:22 +02:00
|
|
|
|
(define search-paths
|
|
|
|
|
;; Search paths of MANIFEST's packages, converted back to their
|
|
|
|
|
;; record form.
|
|
|
|
|
(map sexp->search-path-specification
|
|
|
|
|
(delete-duplicates
|
|
|
|
|
'#$(map search-path-specification->sexp
|
2018-07-09 10:44:36 +02:00
|
|
|
|
(manifest-search-paths manifest)))))
|
2016-07-12 00:54:22 +02:00
|
|
|
|
|
|
|
|
|
(build-profile #$output '#$inputs
|
2018-04-28 22:20:36 +02:00
|
|
|
|
#:symlink #$(if relative-symlinks?
|
|
|
|
|
#~symlink-relative
|
|
|
|
|
#~symlink)
|
2016-07-12 00:54:22 +02:00
|
|
|
|
#:manifest '#$(manifest->gexp manifest)
|
|
|
|
|
#:search-paths search-paths))))
|
2014-08-23 18:41:14 +02:00
|
|
|
|
|
|
|
|
|
(gexp->derivation "profile" builder
|
2016-06-05 00:04:05 +02:00
|
|
|
|
#:system system
|
2017-03-17 21:48:40 +01:00
|
|
|
|
#:target target
|
2015-09-24 22:13:11 +02:00
|
|
|
|
|
2017-12-03 22:14:50 +01:00
|
|
|
|
;; Don't complain about _IO* on Guile 2.2.
|
|
|
|
|
#:env-vars '(("GUILE_WARN_DEPRECATED" . "no"))
|
|
|
|
|
|
2015-09-24 22:13:11 +02:00
|
|
|
|
;; Not worth offloading.
|
|
|
|
|
#:local-build? #t
|
|
|
|
|
|
|
|
|
|
;; Disable substitution because it would trigger a
|
|
|
|
|
;; connection to the substitute server, which is likely
|
|
|
|
|
;; to have no substitute to offer.
|
|
|
|
|
#:substitutable? #f)))
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
|
2018-07-09 13:22:29 +02:00
|
|
|
|
(define* (profile-search-paths profile
|
|
|
|
|
#:optional (manifest (profile-manifest profile))
|
|
|
|
|
#:key (getenv (const #f)))
|
|
|
|
|
"Read the manifest of PROFILE and evaluate the values of search path
|
|
|
|
|
environment variables required by PROFILE; return a list of
|
|
|
|
|
specification/value pairs. If MANIFEST is not #f, it is assumed to be the
|
|
|
|
|
manifest of PROFILE, which avoids rereading it.
|
|
|
|
|
|
|
|
|
|
Use GETENV to determine the current settings and report only settings not
|
|
|
|
|
already effective."
|
|
|
|
|
(evaluate-search-paths (manifest-search-paths manifest)
|
|
|
|
|
(list profile) getenv))
|
|
|
|
|
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
(define (profile-regexp profile)
|
|
|
|
|
"Return a regular expression that matches PROFILE's name and number."
|
|
|
|
|
(make-regexp (string-append "^" (regexp-quote (basename profile))
|
|
|
|
|
"-([0-9]+)")))
|
|
|
|
|
|
|
|
|
|
(define (generation-number profile)
|
|
|
|
|
"Return PROFILE's number or 0. An absolute file name must be used."
|
|
|
|
|
(or (and=> (false-if-exception (regexp-exec (profile-regexp profile)
|
|
|
|
|
(basename (readlink profile))))
|
|
|
|
|
(compose string->number (cut match:substring <> 1)))
|
|
|
|
|
0))
|
|
|
|
|
|
2019-04-06 23:05:27 +02:00
|
|
|
|
(define %profile-generation-rx
|
|
|
|
|
;; Regexp that matches profile generation.
|
|
|
|
|
(make-regexp "(.*)-([0-9]+)-link$"))
|
|
|
|
|
|
|
|
|
|
(define (generation-profile file)
|
|
|
|
|
"If FILE is a profile generation GC root such as \"guix-profile-42-link\",
|
|
|
|
|
return its corresponding profile---e.g., \"guix-profile\". Otherwise return
|
|
|
|
|
#f."
|
|
|
|
|
(match (regexp-exec %profile-generation-rx file)
|
|
|
|
|
(#f #f)
|
|
|
|
|
(m (let ((profile (match:substring m 1)))
|
|
|
|
|
(and (file-exists? (string-append profile "/manifest"))
|
|
|
|
|
profile)))))
|
|
|
|
|
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
(define (generation-numbers profile)
|
|
|
|
|
"Return the sorted list of generation numbers of PROFILE, or '(0) if no
|
|
|
|
|
former profiles were found."
|
|
|
|
|
(match (scandir (dirname profile)
|
|
|
|
|
(cute regexp-exec (profile-regexp profile) <>))
|
|
|
|
|
(#f ; no profile directory
|
|
|
|
|
'(0))
|
|
|
|
|
(() ; no profiles
|
|
|
|
|
'(0))
|
|
|
|
|
((profiles ...) ; former profiles around
|
|
|
|
|
(sort (map (compose string->number
|
|
|
|
|
(cut match:substring <> 1)
|
|
|
|
|
(cute regexp-exec (profile-regexp profile) <>))
|
|
|
|
|
profiles)
|
|
|
|
|
<))))
|
|
|
|
|
|
2014-09-21 12:24:09 +02:00
|
|
|
|
(define (profile-generations profile)
|
|
|
|
|
"Return a list of PROFILE's generations."
|
|
|
|
|
(let ((generations (generation-numbers profile)))
|
|
|
|
|
(if (equal? generations '(0))
|
|
|
|
|
'()
|
|
|
|
|
generations)))
|
|
|
|
|
|
2016-11-02 06:48:11 +01:00
|
|
|
|
(define (relative-generation-spec->number profile spec)
|
|
|
|
|
"Return PROFILE's generation specified by SPEC, which is a string. The SPEC
|
|
|
|
|
may be a N, -N, or +N, where N is a number. If the spec is N, then the number
|
|
|
|
|
returned is N. If it is -N, then the number returned is the profile's current
|
|
|
|
|
generation number minus N. If it is +N, then the number returned is the
|
|
|
|
|
profile's current generation number plus N. Return #f if there is no such
|
|
|
|
|
generation."
|
|
|
|
|
(let ((number (string->number spec)))
|
|
|
|
|
(and number
|
|
|
|
|
(case (string-ref spec 0)
|
|
|
|
|
((#\+ #\-)
|
|
|
|
|
(relative-generation profile number))
|
|
|
|
|
(else (if (memv number (profile-generations profile))
|
|
|
|
|
number
|
|
|
|
|
#f))))))
|
|
|
|
|
|
|
|
|
|
|
2014-10-10 15:56:59 +02:00
|
|
|
|
(define* (relative-generation profile shift #:optional
|
|
|
|
|
(current (generation-number profile)))
|
|
|
|
|
"Return PROFILE's generation shifted from the CURRENT generation by SHIFT.
|
|
|
|
|
SHIFT is a positive or negative number.
|
|
|
|
|
Return #f if there is no such generation."
|
|
|
|
|
(let* ((abs-shift (abs shift))
|
|
|
|
|
(numbers (profile-generations profile))
|
|
|
|
|
(from-current (memq current
|
|
|
|
|
(if (negative? shift)
|
|
|
|
|
(reverse numbers)
|
|
|
|
|
numbers))))
|
|
|
|
|
(and from-current
|
|
|
|
|
(< abs-shift (length from-current))
|
|
|
|
|
(list-ref from-current abs-shift))))
|
|
|
|
|
|
|
|
|
|
(define* (previous-generation-number profile #:optional
|
|
|
|
|
(number (generation-number profile)))
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
"Return the number of the generation before generation NUMBER of
|
|
|
|
|
PROFILE, or 0 if none exists. It could be NUMBER - 1, but it's not the
|
|
|
|
|
case when generations have been deleted (there are \"holes\")."
|
2014-10-10 15:56:59 +02:00
|
|
|
|
(or (relative-generation profile -1 number)
|
|
|
|
|
0))
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
|
|
|
|
|
(define (generation-file-name profile generation)
|
|
|
|
|
"Return the file name for PROFILE's GENERATION."
|
|
|
|
|
(format #f "~a-~a-link" profile generation))
|
|
|
|
|
|
|
|
|
|
(define (generation-time profile number)
|
|
|
|
|
"Return the creation time of a generation in the UTC format."
|
|
|
|
|
(make-time time-utc 0
|
|
|
|
|
(stat:ctime (stat (generation-file-name profile number)))))
|
|
|
|
|
|
2015-10-26 23:01:06 +01:00
|
|
|
|
(define (link-to-empty-profile store generation)
|
|
|
|
|
"Link GENERATION, a string, to the empty profile. An error is raised if
|
|
|
|
|
that fails."
|
|
|
|
|
(let* ((drv (run-with-store store
|
2016-12-17 12:43:10 +01:00
|
|
|
|
(profile-derivation (manifest '())
|
|
|
|
|
#:locales? #f)))
|
2015-10-26 23:01:06 +01:00
|
|
|
|
(prof (derivation->output-path drv "out")))
|
|
|
|
|
(build-derivations store (list drv))
|
|
|
|
|
(switch-symlinks generation prof)))
|
|
|
|
|
|
|
|
|
|
(define (switch-to-generation profile number)
|
|
|
|
|
"Atomically switch PROFILE to the generation NUMBER. Return the number of
|
|
|
|
|
the generation that was current before switching."
|
|
|
|
|
(let ((current (generation-number profile))
|
|
|
|
|
(generation (generation-file-name profile number)))
|
|
|
|
|
(cond ((not (file-exists? profile))
|
|
|
|
|
(raise (condition (&profile-not-found-error
|
|
|
|
|
(profile profile)))))
|
|
|
|
|
((not (file-exists? generation))
|
|
|
|
|
(raise (condition (&missing-generation-error
|
|
|
|
|
(profile profile)
|
|
|
|
|
(generation number)))))
|
|
|
|
|
(else
|
2018-07-13 14:33:11 +02:00
|
|
|
|
(switch-symlinks profile (basename generation))
|
2015-10-26 23:01:06 +01:00
|
|
|
|
current))))
|
|
|
|
|
|
|
|
|
|
(define (switch-to-previous-generation profile)
|
|
|
|
|
"Atomically switch PROFILE to the previous generation. Return the former
|
|
|
|
|
generation number and the current one."
|
|
|
|
|
(let ((previous (previous-generation-number profile)))
|
|
|
|
|
(values (switch-to-generation profile previous)
|
|
|
|
|
previous)))
|
|
|
|
|
|
|
|
|
|
(define (roll-back store profile)
|
|
|
|
|
"Roll back to the previous generation of PROFILE. Return the number of the
|
|
|
|
|
generation that was current before switching and the new generation number."
|
|
|
|
|
(let* ((number (generation-number profile))
|
|
|
|
|
(previous-number (previous-generation-number profile number))
|
|
|
|
|
(previous-generation (generation-file-name profile previous-number)))
|
|
|
|
|
(cond ((not (file-exists? profile)) ;invalid profile
|
|
|
|
|
(raise (condition (&profile-not-found-error
|
|
|
|
|
(profile profile)))))
|
|
|
|
|
((zero? number) ;empty profile
|
|
|
|
|
(values number number))
|
|
|
|
|
((or (zero? previous-number) ;going to emptiness
|
|
|
|
|
(not (file-exists? previous-generation)))
|
|
|
|
|
(link-to-empty-profile store previous-generation)
|
|
|
|
|
(switch-to-previous-generation profile))
|
|
|
|
|
(else ;anything else
|
|
|
|
|
(switch-to-previous-generation profile)))))
|
|
|
|
|
|
|
|
|
|
(define (delete-generation store profile number)
|
|
|
|
|
"Delete generation with NUMBER from PROFILE. Return the file name of the
|
|
|
|
|
generation that has been deleted, or #f if nothing was done (for instance
|
|
|
|
|
because the NUMBER is zero.)"
|
|
|
|
|
(define (delete-and-return)
|
|
|
|
|
(let ((generation (generation-file-name profile number)))
|
|
|
|
|
(delete-file generation)
|
|
|
|
|
generation))
|
|
|
|
|
|
|
|
|
|
(let* ((current-number (generation-number profile))
|
|
|
|
|
(previous-number (previous-generation-number profile number))
|
|
|
|
|
(previous-generation (generation-file-name profile previous-number)))
|
|
|
|
|
(cond ((zero? number) #f) ;do not delete generation 0
|
|
|
|
|
((and (= number current-number)
|
|
|
|
|
(not (file-exists? previous-generation)))
|
|
|
|
|
(link-to-empty-profile store previous-generation)
|
|
|
|
|
(switch-to-previous-generation profile)
|
|
|
|
|
(delete-and-return))
|
|
|
|
|
((= number current-number)
|
|
|
|
|
(roll-back store profile)
|
|
|
|
|
(delete-and-return))
|
|
|
|
|
(else
|
|
|
|
|
(delete-and-return)))))
|
|
|
|
|
|
2018-05-13 16:08:24 +02:00
|
|
|
|
(define %user-profile-directory
|
|
|
|
|
(and=> (getenv "HOME")
|
|
|
|
|
(cut string-append <> "/.guix-profile")))
|
|
|
|
|
|
|
|
|
|
(define %profile-directory
|
|
|
|
|
(string-append %state-directory "/profiles/"
|
|
|
|
|
(or (and=> (or (getenv "USER")
|
|
|
|
|
(getenv "LOGNAME"))
|
|
|
|
|
(cut string-append "per-user/" <>))
|
|
|
|
|
"default")))
|
|
|
|
|
|
|
|
|
|
(define %current-profile
|
|
|
|
|
;; Call it `guix-profile', not `profile', to allow Guix profiles to
|
|
|
|
|
;; coexist with Nix profiles.
|
|
|
|
|
(string-append %profile-directory "/guix-profile"))
|
|
|
|
|
|
2018-10-11 18:04:51 +02:00
|
|
|
|
(define (ensure-profile-directory)
|
|
|
|
|
"Attempt to create /…/profiles/per-user/$USER if needed."
|
|
|
|
|
(let ((s (stat %profile-directory #f)))
|
|
|
|
|
(unless (and s (eq? 'directory (stat:type s)))
|
|
|
|
|
(catch 'system-error
|
|
|
|
|
(lambda ()
|
|
|
|
|
(mkdir-p %profile-directory))
|
|
|
|
|
(lambda args
|
|
|
|
|
;; Often, we cannot create %PROFILE-DIRECTORY because its
|
|
|
|
|
;; parent directory is root-owned and we're running
|
|
|
|
|
;; unprivileged.
|
|
|
|
|
(raise (condition
|
|
|
|
|
(&message
|
|
|
|
|
(message
|
|
|
|
|
(format #f
|
|
|
|
|
(G_ "while creating directory `~a': ~a")
|
|
|
|
|
%profile-directory
|
|
|
|
|
(strerror (system-error-errno args)))))
|
|
|
|
|
(&fix-hint
|
|
|
|
|
(hint
|
|
|
|
|
(format #f (G_ "Please create the @file{~a} directory, \
|
|
|
|
|
with you as the owner.")
|
|
|
|
|
%profile-directory))))))))
|
|
|
|
|
|
|
|
|
|
;; Bail out if it's not owned by the user.
|
|
|
|
|
(unless (or (not s) (= (stat:uid s) (getuid)))
|
|
|
|
|
(raise (condition
|
|
|
|
|
(&message
|
|
|
|
|
(message
|
|
|
|
|
(format #f (G_ "directory `~a' is not owned by you")
|
|
|
|
|
%profile-directory)))
|
|
|
|
|
(&fix-hint
|
|
|
|
|
(hint
|
|
|
|
|
(format #f (G_ "Please change the owner of @file{~a} \
|
|
|
|
|
to user ~s.")
|
|
|
|
|
%profile-directory (or (getenv "USER")
|
|
|
|
|
(getenv "LOGNAME")
|
|
|
|
|
(getuid))))))))))
|
|
|
|
|
|
2018-05-13 16:08:24 +02:00
|
|
|
|
(define (canonicalize-profile profile)
|
2018-10-09 11:51:12 +02:00
|
|
|
|
"If PROFILE points to a profile in %PROFILE-DIRECTORY, return that.
|
|
|
|
|
Otherwise return PROFILE unchanged. The goal is to treat '-p ~/.guix-profile'
|
|
|
|
|
as if '-p' was omitted." ; see <http://bugs.gnu.org/17939>
|
|
|
|
|
;; Trim trailing slashes so 'readlink' can do its job.
|
2018-05-13 16:08:24 +02:00
|
|
|
|
(let ((profile (string-trim-right profile #\/)))
|
2018-10-09 11:51:12 +02:00
|
|
|
|
(catch 'system-error
|
|
|
|
|
(lambda ()
|
|
|
|
|
(let ((target (readlink profile)))
|
|
|
|
|
(if (string=? (dirname target) %profile-directory)
|
|
|
|
|
target
|
|
|
|
|
profile)))
|
|
|
|
|
(const profile))))
|
2018-05-13 16:08:24 +02:00
|
|
|
|
|
2018-10-12 00:12:00 +02:00
|
|
|
|
(define %known-shorthand-profiles
|
|
|
|
|
;; Known shorthand forms for profiles that the user manipulates.
|
|
|
|
|
(list (string-append (config-directory #:ensure? #f) "/current")
|
|
|
|
|
%user-profile-directory))
|
|
|
|
|
|
2018-05-13 16:08:24 +02:00
|
|
|
|
(define (user-friendly-profile profile)
|
2018-10-12 00:12:00 +02:00
|
|
|
|
"Return either ~/.guix-profile or ~/.config/guix/current if that's what
|
|
|
|
|
PROFILE refers to, directly or indirectly, or PROFILE."
|
|
|
|
|
(or (find (lambda (shorthand)
|
|
|
|
|
(and shorthand
|
|
|
|
|
(let ((target (false-if-exception
|
|
|
|
|
(readlink shorthand))))
|
|
|
|
|
(and target (string=? target profile)))))
|
|
|
|
|
%known-shorthand-profiles)
|
2018-05-13 16:08:24 +02:00
|
|
|
|
profile))
|
|
|
|
|
|
Add (guix profiles).
* guix/scripts/package.scm (show-what-to-remove/install): New procedure,
moved from...
(guix-package): ... here.
(<manifest>, make-manifest, <manifest-entry>,
profile-manifest, manifest->sexp, sexp->manifest, read-manifest,
write-manifest, remove-manifest-entry, manifest-remove,
manifest-installed?, manifest=?, profile-regexp, generation-numbers,
previous-generation-number, profile-derivation, generation-number,
generation-file-name, generation-time, lower-input): Move to...
* guix/profiles.scm: ... here. New file.
* Makefile.am (MODULES): Add it.
2013-11-01 16:31:45 +01:00
|
|
|
|
;;; profiles.scm ends here
|