summary refs log tree commit diff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2015-09-24 22:18:07 +0200
committerLudovic Courtès <ludo@gnu.org>2015-09-24 22:18:07 +0200
commit1007b6bf0bef3f662f65ffdd0d4383179dd07355 (patch)
tree4a9b2a4baa2d82434e12fe4aacc8f28e3266793e
parent12cd4dd3a9052491e3912ffeecbe8854ea9b971a (diff)
parenta7a4fd9a7cd02e4897e7b2156bd9ecc7e72e9818 (diff)
downloadguix-1007b6bf0bef3f662f65ffdd0d4383179dd07355.tar.gz
Merge branch 'master' into core-updates
-rw-r--r--doc/contributing.texi3
-rw-r--r--doc/emacs.texi49
-rw-r--r--doc/guix.texi3
-rw-r--r--emacs.am1
-rw-r--r--emacs/guix-command.el26
-rw-r--r--emacs/guix-devel.el136
-rw-r--r--emacs/guix-guile.el35
-rw-r--r--emacs/guix-init.el2
-rw-r--r--gnu/packages/audio.scm34
-rw-r--r--gnu/packages/graphics.scm40
-rw-r--r--gnu/packages/python.scm31
-rw-r--r--guix/build/download.scm36
-rw-r--r--guix/profiles.scm22
-rw-r--r--guix/ui.scm5
-rw-r--r--tests/cran.scm3
-rw-r--r--tests/ui.scm7
16 files changed, 400 insertions, 33 deletions
diff --git a/doc/contributing.texi b/doc/contributing.texi
index ded54348bc..b2d097dd62 100644
--- a/doc/contributing.texi
+++ b/doc/contributing.texi
@@ -121,6 +121,9 @@ facilities to directly operate on the syntax tree, such as raising an
 s-expression or wrapping it, swallowing or rejecting the following
 s-expression, etc.
 
+GNU Guix also comes with a minor mode that provides some additional
+functionality for Scheme buffers (@pxref{Emacs Development}).
+
 
 @node Coding Style
 @section Coding Style
diff --git a/doc/emacs.texi b/doc/emacs.texi
index 67773466a4..b6f2701bc4 100644
--- a/doc/emacs.texi
+++ b/doc/emacs.texi
@@ -12,7 +12,8 @@ Guix convenient and fun.
 * Popup Interface: Emacs Popup Interface.	Magit-like interface for guix commands.
 * Prettify Mode: Emacs Prettify.	Abbreviating @file{/gnu/store/@dots{}} file names.
 * Build Log Mode: Emacs Build Log.	Highlighting Guix build logs.
-* Completions: Emacs Completions.       Completing @command{guix} shell command.
+* Completions: Emacs Completions.	Completing @command{guix} shell command.
+* Development: Emacs Development.	Tools for Guix developers.
 @end menu
 
 
@@ -637,3 +638,49 @@ something:
 @item @code{guix lint --checkers=synopsis,des}@key{TAB}
 
 @end itemize
+
+
+@node Emacs Development
+@section Development
+
+By default, when you open a Scheme file, @code{guix-devel-mode} will be
+activated (if you don't want it, set @code{guix-devel-activate-mode} to
+nil).  This minor mode provides the following key bindings:
+
+@table @kbd
+
+@item C-c . k
+Copy the name of the current Guile module into kill ring
+(@code{guix-devel-copy-module-as-kill}).
+
+@item C-c . u
+Use the current Guile module.  Often after opening a Scheme file, you
+want to use a module it defines, so you switch to the Geiser REPL and
+write @code{,use (some module)} there.  You may just use this command
+instead (@code{guix-devel-use-module}).
+
+@item C-c . b
+Build a package defined by the current variable definition.  The
+building process is run in the current Geiser REPL.  If you modified the
+current package definition, don't forget to reevaluate it before calling
+this command---for example, with @kbd{C-M-x} (@pxref{To eval or not to
+eval,,, geiser, Geiser User Manual})
+(@code{guix-devel-build-package-definition}).
+
+@end table
+
+Unluckily, there is a limitation related to long-running REPL commands.
+When there is a running process in a Geiser REPL, you are not supposed
+to evaluate anything in a scheme buffer, because this will ``freeze''
+the REPL: it will stop producing any output (however, the evaluating
+process will continue---you will just not see any progress anymore).  Be
+aware: even moving the point in a scheme buffer may ``break'' the REPL
+if Autodoc (@pxref{Autodoc and friends,,, geiser, Geiser User Manual})
+is enabled (which is the default).
+
+So you have to postpone editing your scheme buffers until the running
+evaluation will be finished in the REPL.
+
+Alternatively, to avoid this limitation, you may just run another Geiser
+REPL, and while something is being evaluated in the previous REPL, you
+can continue editing a scheme file with the help of the current one.
diff --git a/doc/guix.texi b/doc/guix.texi
index 07c5add5aa..8608e7a49f 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -113,7 +113,8 @@ Emacs Interface
 * Popup Interface: Emacs Popup Interface.	Magit-like interface for guix commands.
 * Prettify Mode: Emacs Prettify.	Abbreviating @file{/gnu/store/@dots{}} file names.
 * Build Log Mode: Emacs Build Log.	Highlighting Guix build logs.
-* Completions: Emacs Completions.       Completing @command{guix} shell command.
+* Completions: Emacs Completions.	Completing @command{guix} shell command.
+* Development: Emacs Development.	Tools for Guix developers.
 
 Programming Interface
 
diff --git a/emacs.am b/emacs.am
index 5d403b212f..9f300bfc07 100644
--- a/emacs.am
+++ b/emacs.am
@@ -23,6 +23,7 @@ ELFILES =					\
   emacs/guix-base.el				\
   emacs/guix-build-log.el			\
   emacs/guix-command.el				\
+  emacs/guix-devel.el				\
   emacs/guix-emacs.el				\
   emacs/guix-external.el			\
   emacs/guix-geiser.el				\
diff --git a/emacs/guix-command.el b/emacs/guix-command.el
index 504d5f7ca0..b679ad9b1e 100644
--- a/emacs/guix-command.el
+++ b/emacs/guix-command.el
@@ -503,7 +503,10 @@ to be modified."
        :name "log" :char ?l :doc "View build log"))
     (("graph")
      ,(guix-command-make-argument
-       :name "view" :char ?v :doc "View graph")))
+       :name "view" :char ?v :doc "View graph"))
+    (("size")
+     ,(guix-command-make-argument
+       :name "view" :char ?v :doc "View map")))
   "Alist of guix commands and additional 'execute' action arguments.")
 
 (defun guix-command-execute-arguments (commands)
@@ -525,7 +528,9 @@ to be modified."
     (("build")
      ("log" . guix-run-view-build-log))
     (("graph")
-     ("view" . guix-run-view-graph)))
+     ("view" . guix-run-view-graph))
+    (("size")
+     ("view" . guix-run-view-size-map)))
   "Alist of guix commands and alists of special executers for them.
 See also `guix-command-default-executors'.")
 
@@ -583,6 +588,23 @@ open the log file(s)."
         (guix-find-file graph-file)
       (error "Couldn't create a graph"))))
 
+(defun guix-run-view-size-map (args)
+  "Run 'guix ARGS ...' size command, and open the map file."
+  (let* ((wished-map-file
+          (cl-some (lambda (arg)
+                     (and (string-match "--map-file=\\(.+\\)" arg)
+                          (match-string 1 arg)))
+                   args))
+         (map-file (or wished-map-file (guix-png-file-name)))
+         (args (if wished-map-file
+                   args
+                 (apply #'list
+                        (car args)
+                        (concat "--map-file=" map-file)
+                        (cdr args)))))
+    (guix-command-output args)
+    (guix-find-file map-file)))
+
 
 ;;; Generating popups, actions, etc.
 
diff --git a/emacs/guix-devel.el b/emacs/guix-devel.el
new file mode 100644
index 0000000000..6de49be3e6
--- /dev/null
+++ b/emacs/guix-devel.el
@@ -0,0 +1,136 @@
+;;; guix-devel.el --- Development tools   -*- lexical-binding: t -*-
+
+;; Copyright © 2015 Alex Kost <alezost@gmail.com>
+
+;; This file is part of GNU Guix.
+
+;; GNU Guix is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Guix is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This file provides commands useful for developing Guix (or even
+;; arbitrary Guile code) with Geiser.
+
+;;; Code:
+
+(require 'guix-guile)
+(require 'guix-geiser)
+(require 'guix-utils)
+(require 'guix-base)
+
+(defgroup guix-devel nil
+  "Settings for Guix development utils."
+  :group 'guix)
+
+(defcustom guix-devel-activate-mode t
+  "If non-nil, then `guix-devel-mode' is automatically activated
+in Scheme buffers."
+  :type 'boolean
+  :group 'guix-devel)
+
+(defun guix-devel-use-modules (&rest modules)
+  "Use guile MODULES."
+  (apply #'guix-geiser-call "use-modules" modules))
+
+(defun guix-devel-use-module (&optional module)
+  "Use guile MODULE in the current Geiser REPL.
+MODULE is a string with the module name - e.g., \"(ice-9 match)\".
+Interactively, use the module defined by the current scheme file."
+  (interactive (list (guix-guile-current-module)))
+  (guix-devel-use-modules module)
+  (message "Using %s module." module))
+
+(defun guix-devel-copy-module-as-kill ()
+  "Put the name of the current guile module into `kill-ring'."
+  (interactive)
+  (guix-copy-as-kill (guix-guile-current-module)))
+
+(defun guix-devel-setup-repl (&optional repl)
+  "Setup REPL for using `guix-devel-...' commands."
+  (guix-devel-use-modules "(guix monad-repl)"
+                          "(guix scripts)"
+                          "(guix store)")
+  ;; Without this workaround, the build output disappears.  See
+  ;; <https://github.com/jaor/geiser/issues/83> for details.
+  (guix-geiser-eval-in-repl
+   "(current-build-output-port (current-error-port))"
+   repl 'no-history 'no-display))
+
+(defvar guix-devel-repl-processes nil
+  "List of REPL processes configured by `guix-devel-setup-repl'.")
+
+(defun guix-devel-setup-repl-maybe (&optional repl)
+  "Setup (if needed) REPL for using `guix-devel-...' commands."
+  (let ((process (get-buffer-process (or repl (guix-geiser-repl)))))
+    (when (and process
+               (not (memq process guix-devel-repl-processes)))
+      (guix-devel-setup-repl repl)
+      (push process guix-devel-repl-processes))))
+
+(defun guix-devel-build-package-definition ()
+  "Build a package defined by the current top-level variable definition."
+  (interactive)
+  (let ((def (guix-guile-current-definition)))
+    (guix-devel-setup-repl-maybe)
+    (guix-devel-use-modules (guix-guile-current-module))
+    (when (or (not guix-operation-confirm)
+              (guix-operation-prompt (format "Build '%s'?" def)))
+      (guix-geiser-eval-in-repl
+       (concat ",run-in-store "
+               (guix-guile-make-call-expression
+                "build-package" def
+                "#:use-substitutes?" (guix-guile-boolean
+                                      guix-use-substitutes)
+                "#:dry-run?" (guix-guile-boolean guix-dry-run)))))))
+
+(defvar guix-devel-keys-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map (kbd "b") 'guix-devel-build-package-definition)
+    (define-key map (kbd "k") 'guix-devel-copy-module-as-kill)
+    (define-key map (kbd "u") 'guix-devel-use-module)
+    map)
+  "Keymap with subkeys for `guix-devel-mode-map'.")
+
+(defvar guix-devel-mode-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map (kbd "C-c .") guix-devel-keys-map)
+    map)
+  "Keymap for `guix-devel-mode'.")
+
+;;;###autoload
+(define-minor-mode guix-devel-mode
+  "Minor mode for `scheme-mode' buffers.
+
+With a prefix argument ARG, enable the mode if ARG is positive,
+and disable it otherwise.  If called from Lisp, enable the mode
+if ARG is omitted or nil.
+
+When Guix Devel mode is enabled, it provides the following key
+bindings:
+
+\\{guix-devel-mode-map}"
+  :init-value nil
+  :lighter " Guix"
+  :keymap guix-devel-mode-map)
+
+;;;###autoload
+(defun guix-devel-activate-mode-maybe ()
+  "Activate `guix-devel-mode' depending on
+`guix-devel-activate-mode' variable."
+  (when guix-devel-activate-mode
+    (guix-devel-mode)))
+
+(provide 'guix-devel)
+
+;;; guix-devel.el ends here
diff --git a/emacs/guix-guile.el b/emacs/guix-guile.el
index cff9bd4e9b..35a97d77a3 100644
--- a/emacs/guix-guile.el
+++ b/emacs/guix-guile.el
@@ -24,6 +24,41 @@
 
 ;;; Code:
 
+(require 'geiser-guile)
+
+(defvar guix-guile-definition-regexp
+  (rx bol "(define"
+      (zero-or-one "*")
+      (zero-or-one "-public")
+      (one-or-more space)
+      (zero-or-one "(")
+      (group (one-or-more (or word (syntax symbol)))))
+  "Regexp used to find the guile definition.")
+
+(defun guix-guile-current-definition ()
+  "Return string with name of the current top-level guile definition."
+  (save-excursion
+    (beginning-of-defun)
+    (if (looking-at guix-guile-definition-regexp)
+        (match-string-no-properties 1)
+      (error "Couldn't find the current definition"))))
+
+(defun guix-guile-current-module ()
+  "Return a string with the current guile module.
+Return nil, if current buffer does not define a module."
+  ;; Modified version of `geiser-guile--get-module'.
+  (save-excursion
+    (geiser-syntax--pop-to-top)
+    (when (or (re-search-backward geiser-guile--module-re nil t)
+              (looking-at geiser-guile--library-re)
+              (re-search-forward geiser-guile--module-re nil t))
+      (match-string-no-properties 1))))
+
+(defun guix-guile-boolean (arg)
+  "Return a string with guile boolean value.
+Transform elisp ARG (nil or non-nil) to the guile boolean (#f or #t)."
+  (concat "#" (prin1-to-string (if arg 't 'f))))
+
 (defun guix-guile-make-call-expression (proc &rest args)
   "Return \"(PROC ARGS ...)\" string.
 PROC and ARGS should be strings."
diff --git a/emacs/guix-init.el b/emacs/guix-init.el
index 3a727c7eb6..96aa0c2ffc 100644
--- a/emacs/guix-init.el
+++ b/emacs/guix-init.el
@@ -12,4 +12,6 @@ avoid loading autoloads of Emacs packages installed in
   (require 'guix-emacs)
   (guix-emacs-load-autoloads 'all))
 
+(add-hook 'scheme-mode-hook 'guix-devel-activate-mode-maybe)
+
 (provide 'guix-init)
diff --git a/gnu/packages/audio.scm b/gnu/packages/audio.scm
index cbf06250d0..a35ef278ee 100644
--- a/gnu/packages/audio.scm
+++ b/gnu/packages/audio.scm
@@ -60,6 +60,7 @@
   #:use-module (gnu packages readline)
   #:use-module (gnu packages xiph)
   #:use-module (gnu packages xml)
+  #:use-module (gnu packages xorg)
   #:use-module (gnu packages zip)
   #:use-module (srfi srfi-1))
 
@@ -1739,6 +1740,39 @@ directly to a different computer on your LAN network.  It is an audio daemon
 with a much different focus than most other audio daemons.")
     (license license:gpl3+)))
 
+(define-public xjackfreak
+  (package
+    (name "xjackfreak")
+    (version "1.0")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append
+                    "https://github.com/johnhldavis/xjackfreak/archive/v"
+                    version ".tar.gz"))
+              (file-name (string-append name "-" version ".tar.gz"))
+              (sha256
+               (base32
+                "0xj6gpxfnw9jbdgwgm0x23xgfvj2kwmwb1nk0drw8lxgcchkq7d9"))))
+    (build-system gnu-build-system)
+    (arguments
+     `(#:make-flags
+       (list (string-append "docdir=" (assoc-ref %outputs "out")
+                            "/share/doc/xjackfreak"))))
+    (inputs
+     `(("jack" ,jack-1)
+       ("libx11" ,libx11)
+       ("libxt" ,libxt)
+       ("libxext" ,libxext)))
+    (native-inputs
+     `(("pkg-config" ,pkg-config)))
+    (home-page "https://github.com/johnhldavis/xjackfreak")
+    (synopsis "JACK audio frequency analyzer and display")
+    (description
+     "XJackFreak is an audio analysis and equalizing tool for the Jack Audio
+Connection Kit.  It can display the FFT of any input, modify it and output the
+result.")
+    (license license:gpl3+)))
+
 (define-public zita-convolver
   (package
     (name "zita-convolver")
diff --git a/gnu/packages/graphics.scm b/gnu/packages/graphics.scm
index f224ebfd32..02e65d3276 100644
--- a/gnu/packages/graphics.scm
+++ b/gnu/packages/graphics.scm
@@ -28,6 +28,8 @@
   #:use-module (gnu packages autotools)
   #:use-module (gnu packages bash)
   #:use-module (gnu packages boost)
+  #:use-module (gnu packages image)
+  #:use-module (gnu packages python)
   #:use-module (gnu packages fontutils)
   #:use-module (gnu packages pkg-config)
   #:use-module (gnu packages compression)
@@ -130,6 +132,44 @@ use in computer imaging applications.  The IlmImf C++ libraries support
 storage of the \"EXR\" file format for storing 16-bit floating-point images.")
     (license license:bsd-3)))
 
+(define-public openimageio
+  (package
+    (name "openimageio")
+    (version "1.5.18")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "https://github.com/OpenImageIO/oiio/"
+                                  "archive/Release-" version ".tar.gz"))
+              (file-name (string-append name "-" version ".tar.gz"))
+              (sha256
+               (base32
+                "0mn7cz19mn8dcrhkq15h25gl20ammr1wz0j2j3c2vxs6ph7zn8jy"))))
+    (build-system cmake-build-system)
+    ;; FIXME: To run all tests successfully, test image sets from multiple
+    ;; third party sources have to be present.  For details see
+    ;; https://github.com/OpenImageIO/oiio/blob/master/INSTALL
+    (arguments `(#:tests? #f))
+    (native-inputs
+     `(("pkg-config" ,pkg-config)))
+    (inputs
+     `(("boost" ,boost)
+       ("libpng" ,libpng)
+       ("libjpeg" ,libjpeg-8)
+       ("libtiff" ,libtiff)
+       ("giflib" ,giflib)
+       ("openexr" ,openexr)
+       ("ilmbase" ,ilmbase)
+       ("python" ,python-2)
+       ("zlib" ,zlib)))
+    (synopsis "C++ library for reading and writing images")
+    (description
+     "OpenImageIO is a library for reading and writing images, and a bunch of
+related classes, utilities, and applications.  There is a particular emphasis
+on formats and functionality used in professional, large-scale animation and
+visual effects work for film.")
+    (home-page "http://www.openimageio.org")
+    (license license:bsd-3)))
+
 (define-public ctl
   (package
     (name "ctl")
diff --git a/gnu/packages/python.scm b/gnu/packages/python.scm
index ca367929e0..0c13303d7d 100644
--- a/gnu/packages/python.scm
+++ b/gnu/packages/python.scm
@@ -3388,14 +3388,14 @@ a front-end for C compilers or analysis tools.")
 (define-public python-cffi
   (package
     (name "python-cffi")
-    (version "0.8.6")
+    (version "1.2.1")
     (source
      (origin
       (method url-fetch)
       (uri (string-append "https://pypi.python.org/packages/source/c/"
                           "cffi/cffi-" version ".tar.gz"))
       (sha256
-       (base32 "0406j3sgndmx88idv5zxkkrwfqxmjl18pj8gf47nsg4ymzixjci5"))))
+       (base32 "0g8yfzinry1vsj6d1jlnd19338bh92lhhk207ksy4lm1n3g73dga"))))
     (build-system python-build-system)
     (outputs '("out" "doc"))
     (inputs
@@ -3405,10 +3405,10 @@ a front-end for C compilers or analysis tools.")
     (native-inputs
      `(("pkg-config" ,pkg-config)
        ("python-sphinx" ,python-sphinx)
+       ("python-pytest" ,python-pytest)
        ("python-setuptools" ,python-setuptools)))
     (arguments
-     `(#:tests? #f ; FIXME: requires pytest
-       #:phases
+     `(#:phases
        (alist-cons-after
         'install 'install-doc
         (lambda* (#:key outputs #:allow-other-keys)
@@ -4945,3 +4945,26 @@ printing of sub-tables by specifying a row range.")
 
 (define-public python2-prettytable
   (package-with-python2 python-prettytable))
+
+(define-public python-pyasn1
+  (package
+    (name "python-pyasn1")
+    (version "0.1.8")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (string-append "https://pypi.python.org/packages/source/p/"
+                           "pyasn1/pyasn1-" version ".tar.gz"))
+       (sha256
+        (base32
+         "0iw31d9l0zwx35szkzq72hiw002wnqrlrsi9dpbrfngcl1ybwcsx"))))
+    (build-system python-build-system)
+    (home-page "http://pyasn1.sourceforge.net/")
+    (synopsis "ASN.1 types and codecs")
+    (description
+     "This is an implementation of ASN.1 types and codecs in Python.  It is
+suitable for a wide range of protocols based on the ASN.1 specification.")
+    (license bsd-2)))
+
+(define-public python2-pyasn1
+  (package-with-python2 python-pyasn1))
diff --git a/guix/build/download.scm b/guix/build/download.scm
index d362fc1f26..4b7c53d2c6 100644
--- a/guix/build/download.scm
+++ b/guix/build/download.scm
@@ -101,27 +101,29 @@ width of the bar is BAR-WIDTH."
 
 (define (string-pad-middle left right len)
   "Combine LEFT and RIGHT with enough padding in the middle so that the
-resulting string has length at least LEN.  This right justifies RIGHT."
-  (string-append left
-                 (string-pad right (max 0 (- len (string-length left))))))
-
-(define (store-url-abbreviation url)
-  "Return a friendlier version of URL for display."
-  (let ((store-path (string-append (%store-directory) "/" (basename url))))
-    ;; Take advantage of the implementation for store paths.
-    (store-path-abbreviation store-path)))
+resulting string has length at least LEN (it may overflow).  If the string
+does not overflow, the last char in RIGHT will be flush with the LEN
+column."
+  (let* ((total-used (+ (string-length left)
+                        (string-length right)))
+         (num-spaces (max 1 (- len total-used)))
+         (padding    (make-string num-spaces #\space)))
+    (string-append left padding right)))
 
 (define* (store-path-abbreviation store-path #:optional (prefix-length 6))
-  "Return an abbreviation of STORE-PATH for display, showing PREFIX-LENGTH
-characters of the hash."
-  (let ((base (basename store-path)))
-    (string-append (string-take base prefix-length)
-                   "…"
-                   (string-drop base 32))))
+  "If STORE-PATH is the file name of a store entry, return an abbreviation of
+STORE-PATH for display, showing PREFIX-LENGTH characters of the hash.
+Otherwise return STORE-PATH."
+  (if (string-prefix? (%store-directory) store-path)
+      (let ((base (basename store-path)))
+        (string-append (string-take base prefix-length)
+                       "…"
+                       (string-drop base 32)))
+      store-path))
 
 (define* (progress-proc file size
                         #:optional (log-port (current-output-port))
-                        #:key (abbreviation identity))
+                        #:key (abbreviation basename))
   "Return a procedure to show the progress of FILE's download, which is SIZE
 bytes long.  The returned procedure is suitable for use as an argument to
 `dump-port'.  The progress report is written to LOG-PORT, with ABBREVIATION
@@ -519,7 +521,7 @@ on success."
                   (_       (list (string->uri url))))))
 
   (define (fetch uri file)
-    (format #t "starting download of `~a' from `~a'...~%"
+    (format #t "~%Starting download of ~a~%From ~a...~%"
             file (uri->string uri))
     (case (uri-scheme uri)
       ((http https)
diff --git a/guix/profiles.scm b/guix/profiles.scm
index d19b49f6d2..0b417a64de 100644
--- a/guix/profiles.scm
+++ b/guix/profiles.scm
@@ -474,7 +474,9 @@ MANIFEST."
                            '#$(manifest-inputs manifest)))))
 
   (gexp->derivation "info-dir" build
-                    #:modules '((guix build utils))))
+                    #:modules '((guix build utils))
+                    #:local-build? #t
+                    #:substitutable? #f))
 
 (define (ghc-package-cache-file manifest)
   "Return a derivation that builds the GHC 'package.cache' file for all the
@@ -527,7 +529,8 @@ entries of MANIFEST, or #f if MANIFEST does not have any GHC packages."
              (map manifest-entry-name (manifest-entries manifest)))
         (gexp->derivation "ghc-package-cache" build
                           #:modules '((guix build utils))
-                          #:local-build? #t)
+                          #:local-build? #t
+                          #:substitutable? #f)
         (return #f))))
 
 (define (ca-certificate-bundle manifest)
@@ -591,7 +594,8 @@ MANIFEST.  Single-file bundles are required by programs such as Git and Lynx."
 
   (gexp->derivation "ca-certificate-bundle" build
                     #:modules '((guix build utils))
-                    #:local-build? #t))
+                    #:local-build? #t
+                    #:substitutable? #f))
 
 (define (gtk-icon-themes manifest)
   "Return a derivation that unions all icon themes from manifest entries and
@@ -669,7 +673,8 @@ creates the GTK+ 'icon-theme.cache' file for each theme."
                                       (guix build profiles)
                                       (guix search-paths)
                                       (guix records))
-                          #:local-build? #t)
+                          #:local-build? #t
+                          #:substitutable? #f)
         (return #f))))
 
 (define %default-profile-hooks
@@ -727,7 +732,14 @@ the monadic procedures listed in HOOKS--such as an Info 'dir' file, etc."
                                   (guix build utils)
                                   (guix search-paths)
                                   (guix records))
-                      #:local-build? #t)))
+
+                      ;; 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)))
 
 (define (profile-regexp profile)
   "Return a regular expression that matches PROFILE's name and number."
diff --git a/guix/ui.scm b/guix/ui.scm
index 4a3630f242..67dd062a34 100644
--- a/guix/ui.scm
+++ b/guix/ui.scm
@@ -803,7 +803,10 @@ converted to a space; sequences of more than one line break are preserved."
 
 (define (texi->plain-text str)
   "Return a plain-text representation of texinfo fragment STR."
-  (stexi->plain-text (texi-fragment->stexi str)))
+  ;; 'texi-fragment->stexi' uses a string port so make sure it's a
+  ;; Unicode-capable one (see <http://bugs.gnu.org/11197>.)
+  (with-fluids ((%default-port-encoding "UTF-8"))
+    (stexi->plain-text (texi-fragment->stexi str))))
 
 (define (package-description-string package)
   "Return a plain-text representation of PACKAGE description field."
diff --git a/tests/cran.scm b/tests/cran.scm
index c9cb5f69d0..ba5699a133 100644
--- a/tests/cran.scm
+++ b/tests/cran.scm
@@ -149,8 +149,7 @@
          ('version "1.2.3")
          ('source ('origin
                     ('method 'url-fetch)
-                    ('uri ('string-append "mirror://cran/src/contrib/my-example-sxml_"
-                                          'version ".tar.gz"))
+                    ('uri ('cran-uri "my-example-sxml" 'version))
                     ('sha256
                      ('base32
                       (? string? hash)))))
diff --git a/tests/ui.scm b/tests/ui.scm
index 25fc709431..bd4c907525 100644
--- a/tests/ui.scm
+++ b/tests/ui.scm
@@ -22,6 +22,7 @@
   #:use-module (guix profiles)
   #:use-module (guix store)
   #:use-module (guix derivations)
+  #:use-module (guix tests)
   #:use-module (srfi srfi-1)
   #:use-module (srfi srfi-11)
   #:use-module (srfi srfi-19)
@@ -89,6 +90,12 @@ interface, and powerful string processing.")
   (fill-paragraph "First line.
 Second line" 24))
 
+(test-equal "package-description-string vs. Unicode"
+  "b•ll•t\n\n"                                ;see <http://bugs.gnu.org/21536>
+  (with-fluids ((%default-port-encoding "ISO-8859-1"))
+    (package-description-string
+     (dummy-package "foo" (description "b•ll•t")))))
+
 (test-equal "package-specification->name+version+output"
   '(("guile" #f "out")
     ("guile" "2.0.9" "out")