summaryrefslogtreecommitdiff
path: root/emacs/guix-main.scm
diff options
context:
space:
mode:
Diffstat (limited to 'emacs/guix-main.scm')
-rw-r--r--emacs/guix-main.scm1163
1 files changed, 0 insertions, 1163 deletions
diff --git a/emacs/guix-main.scm b/emacs/guix-main.scm
deleted file mode 100644
index 040932f307..0000000000
--- a/emacs/guix-main.scm
+++ /dev/null
@@ -1,1163 +0,0 @@
-;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2014, 2015, 2016 Alex Kost <alezost@gmail.com>
-;;;
-;;; This file is part of GNU Guix.
-;;;
-;;; GNU Guix is free software; you can redistribute it and/or modify it
-;;; under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 3 of the License, or (at
-;;; your option) any later version.
-;;;
-;;; GNU Guix is distributed in the hope that it will be useful, but
-;;; WITHOUT ANY WARRANTY; without even the implied warranty of
-;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;;; GNU General Public License for more details.
-;;;
-;;; You should have received a copy of the GNU General Public License
-;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Information about packages and generations is passed to the elisp
-;; side in the form of alists of parameters (such as ‘name’ or
-;; ‘version’) and their values.
-
-;; ‘entries’ procedure is the “entry point” for the elisp side to get
-;; information about packages and generations.
-
-;; Since name/version pair is not necessarily unique, we use
-;; `object-address' to identify a package (for ‘id’ parameter), if
-;; possible. However for the obsolete packages (that can be found in
-;; installed manifest but not in a package directory), ‘id’ parameter is
-;; still "name-version" string. So ‘id’ package parameter in the code
-;; below is either an object-address number or a full-name string.
-
-;;; Code:
-
-(use-modules
- (ice-9 vlist)
- (ice-9 match)
- (ice-9 popen)
- (srfi srfi-1)
- (srfi srfi-2)
- (srfi srfi-11)
- (srfi srfi-19)
- (srfi srfi-26)
- (guix)
- (guix combinators)
- (guix git-download)
- (guix grafts)
- (guix packages)
- (guix profiles)
- (guix licenses)
- (guix utils)
- (guix ui)
- (guix scripts)
- (guix scripts package)
- (gnu packages)
- (gnu system))
-
-(define-syntax-rule (first-or-false lst)
- (and (not (null? lst))
- (first lst)))
-
-(define (list-maybe obj)
- (if (list? obj) obj (list obj)))
-
-(define (output+error thunk)
- "Call THUNK and return 2 values: output and error output as strings."
- (let ((output-port (open-output-string))
- (error-port (open-output-string)))
- (with-output-to-port output-port
- (lambda () (with-error-to-port error-port thunk)))
- (let ((strings (list (get-output-string output-port)
- (get-output-string error-port))))
- (close-output-port output-port)
- (close-output-port error-port)
- (apply values strings))))
-
-(define (full-name->name+version spec)
- "Given package specification SPEC with or without output,
-return two values: name and version. For example, for SPEC
-\"foo@0.9.1b:lib\", return \"foo\" and \"0.9.1b\"."
- (let-values (((name version output)
- (package-specification->name+version+output spec)))
- (values name version)))
-
-(define (name+version->full-name name version)
- (string-append name "@" version))
-
-(define* (make-package-specification name #:optional version output)
- (let ((full-name (if version
- (name+version->full-name name version)
- name)))
- (if output
- (string-append full-name ":" output)
- full-name)))
-
-(define (manifest-entry->name+version+output entry)
- (values
- (manifest-entry-name entry)
- (manifest-entry-version entry)
- (manifest-entry-output entry)))
-
-(define (manifest-entry->package-specification entry)
- (call-with-values
- (lambda () (manifest-entry->name+version+output entry))
- make-package-specification))
-
-(define (manifest-entries->package-specifications entries)
- (map manifest-entry->package-specification entries))
-
-(define (profile-package-specifications profile)
- "Return a list of package specifications for PROFILE."
- (let ((manifest (profile-manifest profile)))
- (manifest-entries->package-specifications
- (manifest-entries manifest))))
-
-(define (profile->specifications+paths profile)
- "Return a list of package specifications and paths for PROFILE.
-Each element of the list is a list of the package specification and its path."
- (let ((manifest (profile-manifest profile)))
- (map (lambda (entry)
- (list (manifest-entry->package-specification entry)
- (manifest-entry-item entry)))
- (manifest-entries manifest))))
-
-(define (profile-difference profile1 profile2)
- "Return a list of package specifications for outputs installed in PROFILE1
-and not installed in PROFILE2."
- (let ((specs1 (profile-package-specifications profile1))
- (specs2 (profile-package-specifications profile2)))
- (lset-difference string=? specs1 specs2)))
-
-(define (manifest-entries->hash-table entries)
- "Return a hash table of name keys and lists of matching manifest ENTRIES."
- (let ((table (make-hash-table (length entries))))
- (for-each (lambda (entry)
- (let* ((key (manifest-entry-name entry))
- (ref (hash-ref table key)))
- (hash-set! table key
- (if ref (cons entry ref) (list entry)))))
- entries)
- table))
-
-(define (manifest=? m1 m2)
- (or (eq? m1 m2)
- (equal? m1 m2)))
-
-(define manifest->hash-table
- (let ((current-manifest #f)
- (current-table #f))
- (lambda (manifest)
- "Return a hash table of name keys and matching MANIFEST entries."
- (unless (manifest=? manifest current-manifest)
- (set! current-manifest manifest)
- (set! current-table (manifest-entries->hash-table
- (manifest-entries manifest))))
- current-table)))
-
-(define* (manifest-entries-by-name manifest name #:optional version output)
- "Return a list of MANIFEST entries matching NAME, VERSION and OUTPUT."
- (let ((entries (or (hash-ref (manifest->hash-table manifest) name)
- '())))
- (if (or version output)
- (filter (lambda (entry)
- (and (or (not version)
- (equal? version (manifest-entry-version entry)))
- (or (not output)
- (equal? output (manifest-entry-output entry)))))
- entries)
- entries)))
-
-(define (manifest-entry-by-output entries output)
- "Return a manifest entry from ENTRIES matching OUTPUT."
- (find (lambda (entry)
- (string= output (manifest-entry-output entry)))
- entries))
-
-(define (fold-manifest-by-name manifest proc init)
- "Fold over MANIFEST entries.
-Call (PROC NAME VERSION ENTRIES RESULT), using INIT as the initial value
-of RESULT. ENTRIES is a list of manifest entries with NAME/VERSION."
- (hash-fold (lambda (name entries res)
- (proc name (manifest-entry-version (car entries))
- entries res))
- init
- (manifest->hash-table manifest)))
-
-(define* (object-transformer param-alist #:optional (params '()))
- "Return procedure transforming objects into alist of parameter/value pairs.
-
-PARAM-ALIST is alist of available parameters (symbols) and procedures
-returning values of these parameters. Each procedure is applied to
-objects.
-
-PARAMS is list of parameters from PARAM-ALIST that should be returned by
-a resulting procedure. If PARAMS is not specified or is an empty list,
-use all available parameters.
-
-Example:
-
- (let* ((alist `((plus1 . ,1+) (minus1 . ,1-) (mul2 . ,(cut * 2 <>))))
- (number->alist (object-transformer alist '(plus1 mul2))))
- (number->alist 8))
- =>
- ((plus1 . 9) (mul2 . 16))
-"
- (let* ((use-all-params (null? params))
- (alist (filter-map (match-lambda
- ((param . proc)
- (and (or use-all-params
- (memq param params))
- (cons param proc)))
- (_ #f))
- param-alist)))
- (lambda objects
- (map (match-lambda
- ((param . proc)
- (cons param (apply proc objects))))
- alist))))
-
-(define %manifest-entry-param-alist
- `((output . ,manifest-entry-output)
- (path . ,manifest-entry-item)
- (dependencies . ,manifest-entry-dependencies)))
-
-(define manifest-entry->sexp
- (object-transformer %manifest-entry-param-alist))
-
-(define (manifest-entries->sexps entries)
- (map manifest-entry->sexp entries))
-
-(define (package-inputs-names inputs)
- "Return a list of full names of the packages from package INPUTS."
- (filter-map (match-lambda
- ((_ (? package? package))
- (make-package-specification (package-name package)
- (package-version package)))
- ((_ (? package? package) output)
- (make-package-specification (package-name package)
- (package-version package)
- output))
- (_ #f))
- inputs))
-
-(define (package-license-names package)
- "Return a list of license names of the PACKAGE."
- (filter-map (lambda (license)
- (and (license? license)
- (license-name license)))
- (list-maybe (package-license package))))
-
-(define (package-source-names package)
- "Return a list of source names (URLs) of the PACKAGE."
- (let ((source (package-source package)))
- (and (origin? source)
- (filter-map (lambda (uri)
- (cond ((string? uri)
- uri)
- ((git-reference? uri)
- (git-reference-url uri))
- (else "Unknown source type")))
- (list-maybe (origin-uri source))))))
-
-(define (package-unique? package)
- "Return #t if PACKAGE is a single package with such name/version."
- (match (packages-by-name (package-name package)
- (package-version package))
- ((package) #t)
- (_ #f)))
-
-(define %package-param-alist
- `((id . ,object-address)
- (package-id . ,object-address)
- (name . ,package-name)
- (version . ,package-version)
- (license . ,package-license-names)
- (source . ,package-source-names)
- (synopsis . ,package-synopsis)
- (description . ,package-description-string)
- (home-url . ,package-home-page)
- (outputs . ,package-outputs)
- (systems . ,package-supported-systems)
- (non-unique . ,(negate package-unique?))
- (inputs . ,(lambda (pkg)
- (package-inputs-names
- (package-inputs pkg))))
- (native-inputs . ,(lambda (pkg)
- (package-inputs-names
- (package-native-inputs pkg))))
- (propagated-inputs . ,(lambda (pkg)
- (package-inputs-names
- (package-propagated-inputs pkg))))
- (location . ,(lambda (pkg)
- (location->string (package-location pkg))))))
-
-(define (package-param package param)
- "Return a value of a PACKAGE PARAM."
- (and=> (assq-ref %package-param-alist param)
- (cut <> package)))
-
-
-;;; Finding packages.
-
-(define-values (package-by-address
- register-package)
- (let ((table (delay (fold-packages
- (lambda (package table)
- (vhash-consq (object-address package)
- package table))
- vlist-null))))
- (values
- (lambda (address)
- "Return package by its object ADDRESS."
- (match (vhash-assq address (force table))
- ((_ . package) package)
- (_ #f)))
- (lambda (package)
- "Register PACKAGE by its 'object-address', so that later
-'package-by-address' can be used to access it."
- (let ((table* (force table)))
- (set! table
- (delay (vhash-consq (object-address package)
- package table*))))))))
-
-(define packages-by-name+version
- (let ((table (delay (fold-packages
- (lambda (package table)
- (let ((file (location-file
- (package-location package))))
- (vhash-cons (cons (package-name package)
- (package-version package))
- package table)))
- vlist-null))))
- (lambda (name version)
- "Return packages matching NAME and VERSION."
- (vhash-fold* cons '() (cons name version) (force table)))))
-
-(define (packages-by-full-name full-name)
- (call-with-values
- (lambda () (full-name->name+version full-name))
- packages-by-name+version))
-
-(define (packages-by-id id)
- (if (integer? id)
- (let ((pkg (package-by-address id)))
- (if pkg (list pkg) '()))
- (packages-by-full-name id)))
-
-(define (id->name+version id)
- (if (integer? id)
- (and=> (package-by-address id)
- (lambda (pkg)
- (values (package-name pkg)
- (package-version pkg))))
- (full-name->name+version id)))
-
-(define (package-by-id id)
- (first-or-false (packages-by-id id)))
-
-(define (newest-package-by-id id)
- (and=> (id->name+version id)
- (lambda (name)
- (first-or-false (find-best-packages-by-name name #f)))))
-
-(define (matching-packages predicate)
- (fold-packages (lambda (pkg res)
- (if (predicate pkg)
- (cons pkg res)
- res))
- '()))
-
-(define (filter-packages-by-output packages output)
- (filter (lambda (package)
- (member output (package-outputs package)))
- packages))
-
-(define* (packages-by-name name #:optional version output)
- "Return a list of packages matching NAME, VERSION and OUTPUT."
- (let ((packages (if version
- (packages-by-name+version name version)
- (matching-packages
- (lambda (pkg) (string=? name (package-name pkg)))))))
- (if output
- (filter-packages-by-output packages output)
- packages)))
-
-(define (manifest-entry->packages entry)
- (call-with-values
- (lambda () (manifest-entry->name+version+output entry))
- packages-by-name))
-
-(define (packages-by-regexp regexp match-params)
- "Return a list of packages matching REGEXP string.
-MATCH-PARAMS is a list of parameters that REGEXP can match."
- (define (package-match? package regexp)
- (any (lambda (param)
- (let ((val (package-param package param)))
- (and (string? val) (regexp-exec regexp val))))
- match-params))
-
- (let ((re (make-regexp regexp regexp/icase)))
- (matching-packages (cut package-match? <> re))))
-
-(define (packages-by-license license)
- "Return a list of packages with LICENSE."
- (matching-packages
- (lambda (package)
- (memq license (list-maybe (package-license package))))))
-
-(define (all-available-packages)
- "Return a list of all available packages."
- (matching-packages (const #t)))
-
-(define (newest-available-packages)
- "Return a list of the newest available packages."
- (vhash-fold (lambda (name elem res)
- (match elem
- ((_ newest pkgs ...)
- (cons newest res))))
- '()
- (find-newest-available-packages)))
-
-(define (packages-from-file file)
- "Return a list of packages from FILE."
- (let ((package (load (canonicalize-path file))))
- (if (package? package)
- (begin
- (register-package package)
- (list package))
- '())))
-
-
-;;; Making package/output patterns.
-
-(define (specification->package-pattern specification)
- (call-with-values
- (lambda ()
- (full-name->name+version specification))
- list))
-
-(define (specification->output-pattern specification)
- (call-with-values
- (lambda ()
- (package-specification->name+version+output specification #f))
- list))
-
-(define (id->package-pattern id)
- (if (integer? id)
- (package-by-address id)
- (specification->package-pattern id)))
-
-(define (id->output-pattern id)
- "Return an output pattern by output ID.
-ID should be '<package-address>:<output>' or '<name>-<version>:<output>'."
- (let-values (((name version output)
- (package-specification->name+version+output id)))
- (if version
- (list name version output)
- (list (package-by-address (string->number name))
- output))))
-
-(define (specifications->package-patterns . specifications)
- (map specification->package-pattern specifications))
-
-(define (specifications->output-patterns . specifications)
- (map specification->output-pattern specifications))
-
-(define (ids->package-patterns . ids)
- (map id->package-pattern ids))
-
-(define (ids->output-patterns . ids)
- (map id->output-pattern ids))
-
-(define* (manifest-patterns-result packages res obsolete-pattern
- #:optional installed-pattern)
- "Auxiliary procedure for 'manifest-package-patterns' and
-'manifest-output-patterns'."
- (if (null? packages)
- (cons (obsolete-pattern) res)
- (if installed-pattern
- ;; We don't need duplicates for a list of installed packages,
- ;; so just take any (car) package.
- (cons (installed-pattern (car packages)) res)
- res)))
-
-(define* (manifest-package-patterns manifest #:optional obsolete-only?)
- "Return a list of package patterns for MANIFEST entries.
-If OBSOLETE-ONLY? is #f, use all entries, otherwise make patterns only
-for obsolete packages."
- (fold-manifest-by-name
- manifest
- (lambda (name version entries res)
- (manifest-patterns-result (packages-by-name name version)
- res
- (lambda () (list name version entries))
- (and (not obsolete-only?)
- (cut list <> entries))))
- '()))
-
-(define* (manifest-output-patterns manifest #:optional obsolete-only?)
- "Return a list of output patterns for MANIFEST entries.
-If OBSOLETE-ONLY? is #f, use all entries, otherwise make patterns only
-for obsolete packages."
- (fold (lambda (entry res)
- (manifest-patterns-result (manifest-entry->packages entry)
- res
- (lambda () entry)
- (and (not obsolete-only?)
- (cut list <> entry))))
- '()
- (manifest-entries manifest)))
-
-(define (obsolete-package-patterns manifest)
- (manifest-package-patterns manifest #t))
-
-(define (obsolete-output-patterns manifest)
- (manifest-output-patterns manifest #t))
-
-
-;;; Transforming package/output patterns into alists.
-
-(define (obsolete-package-sexp name version entries)
- "Return an alist with information about obsolete package.
-ENTRIES is a list of installed manifest entries."
- `((id . ,(name+version->full-name name version))
- (name . ,name)
- (version . ,version)
- (outputs . ,(map manifest-entry-output entries))
- (obsolete . #t)
- (installed . ,(manifest-entries->sexps entries))))
-
-(define (package-pattern-transformer manifest params)
- "Return 'package-pattern->package-sexps' procedure."
- (define package->sexp
- (object-transformer %package-param-alist params))
-
- (define* (sexp-by-package package #:optional
- (entries (manifest-entries-by-name
- manifest
- (package-name package)
- (package-version package))))
- (cons (cons 'installed (manifest-entries->sexps entries))
- (package->sexp package)))
-
- (define (->sexps pattern)
- (match pattern
- ((? package? package)
- (list (sexp-by-package package)))
- (((? package? package) entries)
- (list (sexp-by-package package entries)))
- ((name version entries)
- (list (obsolete-package-sexp
- name version entries)))
- ((name version)
- (let ((packages (packages-by-name name version)))
- (if (null? packages)
- (let ((entries (manifest-entries-by-name
- manifest name version)))
- (if (null? entries)
- '()
- (list (obsolete-package-sexp
- name version entries))))
- (map sexp-by-package packages))))
- (_ '())))
-
- ->sexps)
-
-(define (output-pattern-transformer manifest params)
- "Return 'output-pattern->output-sexps' procedure."
- (define package->sexp
- (object-transformer (alist-delete 'id %package-param-alist)
- params))
-
- (define manifest-entry->sexp
- (object-transformer (alist-delete 'output %manifest-entry-param-alist)
- params))
-
- (define* (output-sexp pkg-alist pkg-address output
- #:optional entry)
- (let ((entry-alist (if entry
- (manifest-entry->sexp entry)
- '()))
- (base `((id . ,(string-append
- (number->string pkg-address)
- ":" output))
- (output . ,output)
- (installed . ,(->bool entry)))))
- (append entry-alist base pkg-alist)))
-
- (define (obsolete-output-sexp entry)
- (let-values (((name version output)
- (manifest-entry->name+version+output entry)))
- (let ((base `((id . ,(make-package-specification
- name version output))
- (package-id . ,(name+version->full-name name version))
- (name . ,name)
- (version . ,version)
- (output . ,output)
- (obsolete . #t)
- (installed . #t))))
- (append (manifest-entry->sexp entry) base))))
-
- (define* (sexps-by-package package #:optional output
- (entries (manifest-entries-by-name
- manifest
- (package-name package)
- (package-version package))))
- ;; Assuming that PACKAGE has this OUTPUT.
- (let ((pkg-alist (package->sexp package))
- (address (object-address package))
- (outputs (if output
- (list output)
- (package-outputs package))))
- (map (lambda (output)
- (output-sexp pkg-alist address output
- (manifest-entry-by-output entries output)))
- outputs)))
-
- (define* (sexps-by-manifest-entry entry #:optional
- (packages (manifest-entry->packages
- entry)))
- (if (null? packages)
- (list (obsolete-output-sexp entry))
- (map (lambda (package)
- (output-sexp (package->sexp package)
- (object-address package)
- (manifest-entry-output entry)
- entry))
- packages)))
-
- (define (->sexps pattern)
- (match pattern
- ((? package? package)
- (sexps-by-package package))
- ((package (? string? output))
- (sexps-by-package package output))
- ((? manifest-entry? entry)
- (list (obsolete-output-sexp entry)))
- ((package entry)
- (sexps-by-manifest-entry entry (list package)))
- ((name version output)
- (let ((packages (packages-by-name name version output)))
- (if (null? packages)
- (let ((entries (manifest-entries-by-name
- manifest name version output)))
- (append-map (cut sexps-by-manifest-entry <>)
- entries))
- (append-map (cut sexps-by-package <> output)
- packages))))
- (_ '())))
-
- ->sexps)
-
-(define (entry-type-error entry-type)
- (error (format #f "Wrong entry-type '~a'" entry-type)))
-
-(define (search-type-error entry-type search-type)
- (error (format #f "Wrong search type '~a' for entry-type '~a'"
- search-type entry-type)))
-
-(define %pattern-transformers
- `((package . ,package-pattern-transformer)
- (output . ,output-pattern-transformer)))
-
-(define (pattern-transformer entry-type)
- (assq-ref %pattern-transformers entry-type))
-
-;; All procedures from inner alists are called with (MANIFEST . SEARCH-VALS)
-;; as arguments; see `package/output-sexps'.
-(define %patterns-makers
- (let* ((apply-to-rest (lambda (proc)
- (lambda (_ . rest) (apply proc rest))))
- (apply-to-first (lambda (proc)
- (lambda (first . _) (proc first))))
- (manifest-package-proc (apply-to-first manifest-package-patterns))
- (manifest-output-proc (apply-to-first manifest-output-patterns))
- (regexp-proc (lambda (_ regexp params . __)
- (packages-by-regexp regexp params)))
- (license-proc (lambda (_ license-name)
- (packages-by-license
- (lookup-license license-name))))
- (location-proc (lambda (_ location)
- (packages-by-location-file location)))
- (file-proc (lambda (_ file)
- (packages-from-file file)))
- (all-proc (lambda _ (all-available-packages)))
- (newest-proc (lambda _ (newest-available-packages))))
- `((package
- (id . ,(apply-to-rest ids->package-patterns))
- (name . ,(apply-to-rest specifications->package-patterns))
- (installed . ,manifest-package-proc)
- (obsolete . ,(apply-to-first obsolete-package-patterns))
- (regexp . ,regexp-proc)
- (license . ,license-proc)
- (location . ,location-proc)
- (from-file . ,file-proc)
- (all-available . ,all-proc)
- (newest-available . ,newest-proc))
- (output
- (id . ,(apply-to-rest ids->output-patterns))
- (name . ,(apply-to-rest specifications->output-patterns))
- (installed . ,manifest-output-proc)
- (obsolete . ,(apply-to-first obsolete-output-patterns))
- (regexp . ,regexp-proc)
- (license . ,license-proc)
- (location . ,location-proc)
- (from-file . ,file-proc)
- (all-available . ,all-proc)
- (newest-available . ,newest-proc)))))
-
-(define (patterns-maker entry-type search-type)
- (or (and=> (assq-ref %patterns-makers entry-type)
- (cut assq-ref <> search-type))
- (search-type-error entry-type search-type)))
-
-(define (package/output-sexps profile params entry-type
- search-type search-vals)
- "Return information about packages or package outputs.
-See 'entry-sexps' for details."
- (let* ((manifest (profile-manifest profile))
- (patterns (if (and (eq? entry-type 'output)
- (eq? search-type 'profile-diff))
- (match search-vals
- ((p1 p2)
- (map specification->output-pattern
- (profile-difference p1 p2)))
- (_ '()))
- (apply (patterns-maker entry-type search-type)
- manifest search-vals)))
- (->sexps ((pattern-transformer entry-type) manifest params)))
- (append-map ->sexps patterns)))
-
-
-;;; Getting information about generations.
-
-(define (generation-param-alist profile)
- "Return an alist of generation parameters and procedures for PROFILE."
- (let ((current (generation-number profile)))
- `((id . ,identity)
- (number . ,identity)
- (prev-number . ,(cut previous-generation-number profile <>))
- (current . ,(cut = current <>))
- (path . ,(cut generation-file-name profile <>))
- (time . ,(lambda (gen)
- (time-second (generation-time profile gen)))))))
-
-(define (matching-generations profile predicate)
- "Return a list of PROFILE generations matching PREDICATE."
- (filter predicate (profile-generations profile)))
-
-(define (last-generations profile number)
- "Return a list of last NUMBER generations.
-If NUMBER is 0 or less, return all generations."
- (let ((generations (profile-generations profile))
- (number (if (<= number 0) +inf.0 number)))
- (if (> (length generations) number)
- (list-head (reverse generations) number)
- generations)))
-
-(define (find-generations profile search-type search-vals)
- "Find PROFILE's generations matching SEARCH-TYPE and SEARCH-VALS."
- (case search-type
- ((id)
- (matching-generations profile (cut memq <> search-vals)))
- ((last)
- (last-generations profile (car search-vals)))
- ((all)
- (last-generations profile +inf.0))
- ((time)
- (match search-vals
- ((from to)
- (matching-generations
- profile
- (lambda (gen)
- (let ((time (time-second (generation-time profile gen))))
- (< from time to)))))
- (_ '())))
- (else (search-type-error "generation" search-type))))
-
-(define (generation-sexps profile params search-type search-vals)
- "Return information about generations.
-See 'entry-sexps' for details."
- (let ((generations (find-generations profile search-type search-vals))
- (->sexp (object-transformer (generation-param-alist profile)
- params)))
- (map ->sexp generations)))
-
-(define system-generation-boot-parameters
- (memoize
- (lambda (profile generation)
- "Return boot parameters for PROFILE's system GENERATION."
- (let* ((gen-file (generation-file-name profile generation))
- (param-file (string-append gen-file "/parameters")))
- (call-with-input-file param-file read-boot-parameters)))))
-
-(define (system-generation-param-alist profile)
- "Return an alist of system generation parameters and procedures for
-PROFILE."
- (append (generation-param-alist profile)
- `((label . ,(lambda (gen)
- (boot-parameters-label
- (system-generation-boot-parameters
- profile gen))))
- (root-device . ,(lambda (gen)
- (boot-parameters-root-device
- (system-generation-boot-parameters
- profile gen))))
- (kernel . ,(lambda (gen)
- (boot-parameters-kernel
- (system-generation-boot-parameters
- profile gen)))))))
-
-(define (system-generation-sexps profile params search-type search-vals)
- "Return an alist with information about system generations."
- (let ((generations (find-generations profile search-type search-vals))
- (->sexp (object-transformer (system-generation-param-alist profile)
- params)))
- (map ->sexp generations)))
-
-
-;;; Getting package/output/generation entries (alists).
-
-(define (entries profile params entry-type search-type search-vals)
- "Return information about entries.
-
-ENTRY-TYPE is a symbol defining a type of returning information. Should
-be: 'package', 'output' or 'generation'.
-
-SEARCH-TYPE and SEARCH-VALS define how to get the information.
-SEARCH-TYPE should be one of the following symbols:
-
-- If ENTRY-TYPE is 'package' or 'output':
- 'id', 'name', 'regexp', 'all-available', 'newest-available',
- 'installed', 'obsolete', 'generation'.
-
-- If ENTRY-TYPE is 'generation':
- 'id', 'last', 'all', 'time'.
-
-PARAMS is a list of parameters for receiving. If it is an empty list,
-get information with all available parameters, which are:
-
-- If ENTRY-TYPE is 'package':
- 'id', 'name', 'version', 'outputs', 'license', 'synopsis',
- 'description', 'home-url', 'inputs', 'native-inputs',
- 'propagated-inputs', 'location', 'installed'.
-
-- If ENTRY-TYPE is 'output':
- 'id', 'package-id', 'name', 'version', 'output', 'license',
- 'synopsis', 'description', 'home-url', 'inputs', 'native-inputs',
- 'propagated-inputs', 'location', 'installed', 'path', 'dependencies'.
-
-- If ENTRY-TYPE is 'generation':
- 'id', 'number', 'prev-number', 'path', 'time'.
-
-Returning value is a list of alists. Each alist consists of
-parameter/value pairs."
- (case entry-type
- ((package output)
- (package/output-sexps profile params entry-type
- search-type search-vals))
- ((generation)
- (generation-sexps profile params
- search-type search-vals))
- ((system-generation)
- (system-generation-sexps profile params
- search-type search-vals))
- (else (entry-type-error entry-type))))
-
-
-;;; Package actions.
-
-(define* (package->manifest-entry* package #:optional output)
- (and package
- (package->manifest-entry package output)))
-
-(define* (make-install-manifest-entries id #:optional output)
- (package->manifest-entry* (package-by-id id) output))
-
-(define* (make-upgrade-manifest-entries id #:optional output)
- (package->manifest-entry* (newest-package-by-id id) output))
-
-(define* (make-manifest-pattern id #:optional output)
- "Make manifest pattern from a package ID and OUTPUT."
- (let-values (((name version)
- (id->name+version id)))
- (and name version
- (manifest-pattern
- (name name)
- (version version)
- (output output)))))
-
-(define (convert-action-pattern pattern proc)
- "Convert action PATTERN into a list of objects returned by PROC.
-PROC is called: (PROC ID) or (PROC ID OUTPUT)."
- (match pattern
- ((id . outputs)
- (if (null? outputs)
- (let ((obj (proc id)))
- (if obj (list obj) '()))
- (filter-map (cut proc id <>)
- outputs)))
- (_ '())))
-
-(define (convert-action-patterns patterns proc)
- (append-map (cut convert-action-pattern <> proc)
- patterns))
-
-(define* (process-package-actions
- profile #:key (install '()) (upgrade '()) (remove '())
- (use-substitutes? #t) dry-run?)
- "Perform package actions.
-
-INSTALL, UPGRADE, REMOVE are lists of 'package action patterns'.
-Each pattern should have the following form:
-
- (ID . OUTPUTS)
-
-ID is an object address or a full-name of a package.
-OUTPUTS is a list of package outputs (may be an empty list)."
- (format #t "The process begins ...~%")
- (let* ((install (append
- (convert-action-patterns
- install make-install-manifest-entries)
- (convert-action-patterns
- upgrade make-upgrade-manifest-entries)))
- (remove (convert-action-patterns remove make-manifest-pattern))
- (transaction (manifest-transaction (install install)
- (remove remove)))
- (manifest (profile-manifest profile))
- (new-manifest (manifest-perform-transaction
- manifest transaction)))
- (unless (and (null? install) (null? remove))
- (parameterize ((%graft? (not dry-run?)))
- (with-store store
- (set-build-options store
- #:print-build-trace #f
- #:use-substitutes? use-substitutes?)
- (show-manifest-transaction store manifest transaction
- #:dry-run? dry-run?)
- (build-and-use-profile store profile new-manifest
- #:use-substitutes? use-substitutes?
- #:dry-run? dry-run?))))))
-
-(define (delete-generations* profile generations)
- "Delete GENERATIONS from PROFILE.
-GENERATIONS is a list of generation numbers."
- (with-store store
- (delete-generations store profile generations)))
-
-(define (package-location-string id-or-name)
- "Return a location string of a package with ID-OR-NAME."
- (and=> (or (package-by-id id-or-name)
- (match (packages-by-name id-or-name)
- (() #f)
- ((package _ ...) package)))
- (compose location->string package-location)))
-
-(define (package-store-path package-id)
- "Return a list of store directories of outputs of package PACKAGE-ID."
- (match (package-by-id package-id)
- (#f '())
- (package
- (with-store store
- (map (match-lambda
- ((_ . drv)
- (derivation-output-path drv)))
- (derivation-outputs (package-derivation store package)))))))
-
-(define (package-source-derivation->store-path derivation)
- "Return a store path of the package source DERIVATION."
- (match (derivation-outputs derivation)
- ;; Source derivation is always (("out" . derivation)).
- (((_ . output-drv))
- (derivation-output-path output-drv))
- (_ #f)))
-
-(define (package-source-path package-id)
- "Return a store file path to a source of a package PACKAGE-ID."
- (and-let* ((package (package-by-id package-id))
- (source (package-source package)))
- (with-store store
- (package-source-derivation->store-path
- (package-source-derivation store source)))))
-
-(define* (package-source-build-derivation package-id #:key dry-run?
- (use-substitutes? #t))
- "Build source derivation of a package PACKAGE-ID."
- (and-let* ((package (package-by-id package-id))
- (source (package-source package)))
- (with-store store
- (let* ((derivation (package-source-derivation store source))
- (derivations (list derivation)))
- (set-build-options store
- #:print-build-trace #f
- #:use-substitutes? use-substitutes?)
- (show-what-to-build store derivations
- #:use-substitutes? use-substitutes?
- #:dry-run? dry-run?)
- (unless dry-run?
- (build-derivations store derivations))
- (format #t "The source store path: ~a~%"
- (package-source-derivation->store-path derivation))))))
-
-(define (package-build-log-file package-id)
- "Return the build log file of a package PACKAGE-ID.
-Return #f if the build log is not found."
- (and-let* ((package (package-by-id package-id)))
- (with-store store
- (let* ((derivation (package-derivation store package))
- (file (derivation-file-name derivation)))
- (or (log-file store file)
- ((@@ (guix scripts build) log-url) store file))))))
-
-
-;;; Executing guix commands
-
-(define (guix-command . args)
- "Run 'guix ARGS ...' command."
- (catch 'quit
- (lambda () (apply run-guix args))
- (const #t)))
-
-(define (guix-command-output . args)
- "Return 2 strings with 'guix ARGS ...' output and error output."
- (output+error
- (lambda ()
- (parameterize ((guix-warning-port (current-error-port)))
- (apply guix-command args)))))
-
-(define (help-string . commands)
- "Return string with 'guix COMMANDS ... --help' output."
- (apply guix-command-output `(,@commands "--help")))
-
-(define (pipe-guix-output guix-args command-args)
- "Run 'guix GUIX-ARGS ...' command and pipe its output to a shell command
-defined by COMMAND-ARGS.
-Return #t if the shell command was executed successfully."
- (let ((pipe (apply open-pipe* OPEN_WRITE command-args)))
- (with-output-to-port pipe
- (lambda () (apply guix-command guix-args)))
- (zero? (status:exit-val (close-pipe pipe)))))
-
-
-;;; Lists of packages, lint checkers, etc.
-
-(define (graph-type-names)
- "Return a list of names of available graph node types."
- (map (@ (guix graph) node-type-name)
- (@ (guix scripts graph) %node-types)))
-
-(define (refresh-updater-names)
- "Return a list of names of available refresh updater types."
- (map (@ (guix upstream) upstream-updater-name)
- (@ (guix scripts refresh) %updaters)))
-
-(define (lint-checker-names)
- "Return a list of names of available lint checkers."
- (map (lambda (checker)
- (symbol->string ((@ (guix scripts lint) lint-checker-name)
- checker)))
- (@ (guix scripts lint) %checkers)))
-
-(define (package-names)
- "Return a list of names of available packages."
- (delete-duplicates
- (fold-packages (lambda (pkg res)
- (cons (package-name pkg) res))
- '())))
-
-;; See the comment to 'guix-package-names' function in "guix-popup.el".
-(define (package-names-lists)
- (map list (package-names)))
-
-
-;;; Licenses
-
-(define %licenses
- (delay
- (filter license?
- (module-map (lambda (_ var)
- (variable-ref var))
- (resolve-interface '(guix licenses))))))
-
-(define (licenses)
- (force %licenses))
-
-(define (license-names)
- "Return a list of names of available licenses."
- (map license-name (licenses)))
-
-(define lookup-license
- (memoize
- (lambda (name)
- "Return a license by its name."
- (find (lambda (l)
- (string=? name (license-name l)))
- (licenses)))))
-
-(define (lookup-license-uri name)
- "Return a license URI by its name."
- (and=> (lookup-license name)
- license-uri))
-
-(define %license-param-alist
- `((id . ,license-name)
- (name . ,license-name)
- (url . ,license-uri)
- (comment . ,license-comment)))
-
-(define license->sexp
- (object-transformer %license-param-alist))
-
-(define (find-licenses search-type . search-values)
- "Return a list of licenses depending on SEARCH-TYPE and SEARCH-VALUES."
- (case search-type
- ((id name)
- (let ((names search-values))
- (filter-map lookup-license names)))
- ((all)
- (licenses))))
-
-(define (license-entries search-type . search-values)
- (map license->sexp
- (apply find-licenses search-type search-values)))
-
-
-;;; Package locations
-
-(define-values (packages-by-location-file
- package-location-files)
- (let* ((table (delay (fold-packages
- (lambda (package table)
- (let ((file (location-file
- (package-location package))))
- (vhash-cons file package table)))
- vlist-null)))
- (files (delay (vhash-fold
- (lambda (file _ result)
- (if (member file result)
- result
- (cons file result)))
- '()
- (force table)))))
- (values
- (lambda (file)
- "Return the (possibly empty) list of packages defined in location FILE."
- (vhash-fold* cons '() file (force table)))
- (lambda ()
- "Return the list of file names of all package locations."
- (force files)))))
-
-(define %package-location-param-alist
- `((id . ,identity)
- (location . ,identity)
- (number-of-packages . ,(lambda (location)
- (length (packages-by-location-file location))))))
-
-(define package-location->sexp
- (object-transformer %package-location-param-alist))
-
-(define (package-location-entries)
- (map package-location->sexp (package-location-files)))