maav / guix-mirror (public) (License: GPLv3+) (since 2019-11-02) (hash sha1)
Mirror of GNU Guix (https://git.savannah.gnu.org/git/guix.git) with personal branches integrated into master branch.

/guix/search-paths.scm (002e6342bbe197249fbf3897c05da3efc0d7d274) (8698 bytes) (mode 100644) (type blob)

;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2013, 2014, 2015, 2017, 2018 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.

(define-module (guix search-paths)
  #:use-module (guix records)
  #:use-module (guix build utils)
  #:use-module (srfi srfi-1)
  #:use-module (srfi srfi-26)
  #:use-module (ice-9 match)
  #:export (<search-path-specification>
            search-path-specification
            search-path-specification?
            search-path-specification-variable
            search-path-specification-files
            search-path-specification-separator
            search-path-specification-file-type
            search-path-specification-file-pattern

            $PATH

            search-path-specification->sexp
            sexp->search-path-specification
            string-tokenize*
            evaluate-search-paths
            environment-variable-definition
            search-path-definition
            set-search-paths))

;;; Commentary:
;;;
;;; This module defines "search path specifications", which allow packages to
;;; declare environment variables that they use to define search paths.  For
;;; instance, GCC has the 'CPATH' variable, Guile has the 'GUILE_LOAD_PATH'
;;; variable, etc.
;;;
;;; Code:

;; The specification of a search path.
(define-record-type* <search-path-specification>
  search-path-specification make-search-path-specification
  search-path-specification?
  (variable     search-path-specification-variable) ;string
  (files        search-path-specification-files)    ;list of strings
  (separator    search-path-specification-separator ;string | #f
                (default ":"))
  (file-type    search-path-specification-file-type ;symbol
                (default 'directory))
  (file-pattern search-path-specification-file-pattern ;#f | string
                (default #f)))

(define $PATH
  ;; The 'PATH' variable.  This variable is a bit special: it is not attached
  ;; to any package in particular.
  (search-path-specification
   (variable "PATH")
   (files '("bin" "sbin"))))

(define (search-path-specification->sexp spec)
  "Return an sexp representing SPEC, a <search-path-specification>.  The sexp
corresponds to the arguments expected by `set-path-environment-variable'."
  ;; Note that this sexp format is used both by build systems and in
  ;; (guix profiles), so think twice before you change it.
  (match spec
    (($ <search-path-specification> variable files separator type pattern)
     `(,variable ,files ,separator ,type ,pattern))))

(define (sexp->search-path-specification sexp)
  "Convert SEXP, which is as returned by 'search-path-specification->sexp', to
a <search-path-specification> object."
  (match sexp
    ((variable files separator type pattern)
     (search-path-specification
      (variable variable)
      (files files)
      (separator separator)
      (file-type type)
      (file-pattern pattern)))))

(define-syntax-rule (with-null-error-port exp)
  "Evaluate EXP with the error port pointing to the bit bucket."
  (with-error-to-port (%make-void-port "w")
    (lambda () exp)))

;; XXX: This procedure used to be in (guix utils) but since we want to be able
;; to use (guix search-paths) on the build side, we want to avoid the
;; dependency on (guix utils), and so this procedure is back here for now.
(define (string-tokenize* string separator)
  "Return the list of substrings of STRING separated by SEPARATOR.  This is
like `string-tokenize', but SEPARATOR is a string."
  (define (index string what)
    (let loop ((string string)
               (offset 0))
      (cond ((string-null? string)
             #f)
            ((string-prefix? what string)
             offset)
            (else
             (loop (string-drop string 1) (+ 1 offset))))))

  (define len
    (string-length separator))

  (let loop ((string string)
             (result  '()))
    (cond ((index string separator)
           =>
           (lambda (offset)
             (loop (string-drop string (+ offset len))
                   (cons (substring string 0 offset)
                         result))))
          (else
           (reverse (cons string result))))))

(define* (evaluate-search-paths search-paths directories
                                #:optional (getenv (const #f)))
  "Evaluate SEARCH-PATHS, a list of search-path specifications, for
DIRECTORIES, a list of directory names, and return a list of
specification/value pairs.  Use GETENV to determine the current settings and
report only settings not already effective."
  (define (search-path-definition spec)
    (match spec
      (($ <search-path-specification> variable files #f type pattern)
       ;; Separator is #f so return the first match.
       (match (with-null-error-port
               (search-path-as-list files directories
                                    #:type type
                                    #:pattern pattern))
         (()
          #f)
         ((head . _)
          (let ((value (getenv variable)))
            (if (and value (string=? value head))
                #f                         ;VARIABLE already set appropriately
                (cons spec head))))))
      (($ <search-path-specification> variable files separator
                                      type pattern)
       (let* ((values (or (and=> (getenv variable)
                                 (cut string-tokenize* <> separator))
                          '()))
              ;; XXX: Silence 'find-files' when it stumbles upon non-existent
              ;; directories (see
              ;; <http://lists.gnu.org/archive/html/guix-devel/2015-01/msg00269.html>.)
              (path   (with-null-error-port
                       (search-path-as-list files directories
                                            #:type type
                                            #:pattern pattern))))
         (if (every (cut member <> values) path)
             #f                         ;VARIABLE is already set appropriately
             (cons spec (string-join path separator)))))))

  (filter-map search-path-definition search-paths))

(define* (environment-variable-definition variable value
                                          #:key
                                          (kind 'exact)
                                          (separator ":"))
  "Return a the definition of VARIABLE to VALUE in Bash syntax.

KIND can be either 'exact (return the definition of VARIABLE=VALUE),
'prefix (return the definition where VALUE is added as a prefix to VARIABLE's
current value), or 'suffix (return the definition where VALUE is added as a
suffix to VARIABLE's current value.)  In the case of 'prefix and 'suffix,
SEPARATOR is used as the separator between VARIABLE's current value and its
prefix/suffix."
  (match (if (not separator) 'exact kind)
    ('exact
     (format #f "export ~a=\"~a\"" variable value))
    ('prefix
     (format #f "export ~a=\"~a${~a:+~a}$~a\""
             variable value variable separator variable))
    ('suffix
     (format #f "export ~a=\"$~a${~a:+~a}~a\""
             variable variable variable separator value))))

(define* (search-path-definition search-path value
                                 #:key (kind 'exact))
  "Similar to 'environment-variable-definition', but applied to a
<search-path-specification>."
  (match search-path
    (($ <search-path-specification> variable _ separator)
     (environment-variable-definition variable value
                                      #:kind kind
                                      #:separator separator))))

(define* (set-search-paths search-paths directories
                           #:key (setenv setenv))
  "Set the search path environment variables specified by SEARCH-PATHS for the
given directories."
  (for-each (match-lambda
              ((spec . value)
               (setenv (search-path-specification-variable spec)
                       value)))
            (evaluate-search-paths search-paths directories)))

;;; search-paths.scm ends here


Mode Type Size Ref File
100644 blob 6139 7f310d2612983845551d0a641b730a269a180a3f .dir-locals.el
100644 blob 2533 e2f745b42a5a1591a93a3e9a7ccfc107a6178eff .gitignore
100644 blob 6179 ee164083c8379d90c6e7ab3b38576266f458f40c .guix-authorizations
100644 blob 182 b852180cf2563ec7b74b93c954de38d77237f23f .guix-channel
100644 blob 4499 146e65184a2f987b0307d0ec7300c93e84110625 .mailmap
100644 blob 472 1e30a74a64f51ec735dcc44ff4dfe5fa4fa13c6f AUTHORS
100644 blob 3273 ef90330cdacb9ecf7dbf38a03cdb490db131a4ad CODE-OF-CONDUCT
100644 blob 35147 94a9ed024d3859793618152ea559a168bbcbb5e2 COPYING
100644 blob 163 d6ea6943261fcae51c095ad39fe59140fc62de22 ChangeLog
100644 blob 749 aaa673fc93b0bb74feca4783ae427b9ea1b604ea HACKING
100644 blob 33109 a75d9c1ffc4237c0478b62a235b9b521fd840517 Makefile.am
100644 blob 359348 bb1de1e93802064ff44392db56d05cd0a11fcc15 NEWS
100644 blob 5260 5e9069f80f58d3946cdd588f30919a177eaccb55 README
100644 blob 3237 2475cb637ceb6eb43f54d080c56e5793041b76e5 ROADMAP
100644 blob 2381 af7afd3576f2e6aa5cbafc3c6354bbab1ae00774 THANKS
100644 blob 4360 f854f7fa98e09c7b512f3efb702c290b615186a0 TODO
100755 blob 906 a47269d87f1d6fd27bbaf634ac7439b38b32cca3 bootstrap
040000 tree - b15b9ede344760715e240528bc322c7b0194bbe7 build-aux
100644 blob 4808 50ead355a81edebf5c9419bd76a1dd69e85f5adf config-daemon.ac
100644 blob 8760 6861112eafaed85e107f8976f12e0ddb795571b7 configure.ac
100644 blob 339545 d234c4ec8668cead20279d903589d29c513b4cb6 d3.v3.js
040000 tree - ad0dbfb1b2956f33070d044c3cb173030dd3c5f1 doc
040000 tree - 8cc2bd0b87d4ef774820c72703a0b3ae914e8601 etc
100644 blob 5289 f139531ef3ecf56a790ae73934e2d91016c1aba4 gnu.scm
040000 tree - 34d1107337432fed7fa3f18c9affd932681e9b6a gnu
100644 blob 4207 ad8279395d8eb1fe5a836d54ec563a4577f4d135 graph.js
100644 blob 1357 8753c21e423f880e7a6d9f7f6f6ff1139f8b7254 guix.scm
040000 tree - 9c3a3e887916002138b68277e856e1f0e6416659 guix
040000 tree - 8df9aaabfb400159e2559fd4331fb861cb0a5adc m4
040000 tree - 84cedf0076fb8362febdffa59ba83b63e8c3f9e8 nix
040000 tree - 8dac6dd305591d733ef087c35eee3b3acb1daee2 po
040000 tree - 8c4db11917d51c4d71a841813cf8951000b76687 scripts
040000 tree - 867e6957c2eed1c47764e42093bb26ae37b221e3 tests
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/maav/guix-mirror

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/maav/guix-mirror

Clone this repository using git:
git clone git://git.rocketgit.com/user/maav/guix-mirror

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main