| 1 | # GNU Guix --- Functional package management for GNU |
| 2 | # Copyright © 2012, 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org> |
| 3 | # Copyright © 2013 Nikita Karetnikov <nikita@karetnikov.org> |
| 4 | # |
| 5 | # This file is part of GNU Guix. |
| 6 | # |
| 7 | # GNU Guix is free software; you can redistribute it and/or modify it |
| 8 | # under the terms of the GNU General Public License as published by |
| 9 | # the Free Software Foundation; either version 3 of the License, or (at |
| 10 | # your option) any later version. |
| 11 | # |
| 12 | # GNU Guix is distributed in the hope that it will be useful, but |
| 13 | # WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | # GNU General Public License for more details. |
| 16 | # |
| 17 | # You should have received a copy of the GNU General Public License |
| 18 | # along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. |
| 19 | |
| 20 | # |
| 21 | # Test the `guix package' command-line utility. |
| 22 | # |
| 23 | |
| 24 | guix package --version |
| 25 | |
| 26 | readlink_base () |
| 27 | { |
| 28 | basename `readlink "$1"` |
| 29 | } |
| 30 | |
| 31 | module_dir="t-guix-package-$$" |
| 32 | profile="t-profile-$$" |
| 33 | tmpfile="t-guix-package-file-$$" |
| 34 | rm -f "$profile" "$tmpfile" |
| 35 | |
| 36 | trap 'rm -f "$profile" "$profile-"[0-9]* "$tmpfile"; rm -rf "$module_dir" t-home-'"$$" EXIT |
| 37 | |
| 38 | # Use `-e' with a non-package expression. |
| 39 | if guix package --bootstrap -e +; |
| 40 | then false; else true; fi |
| 41 | |
| 42 | # Install a store item and make sure the version and output in the manifest |
| 43 | # are correct. |
| 44 | guix package --bootstrap -p "$profile" -i `guix build guile-bootstrap` |
| 45 | test "`guix package -A guile-bootstrap | cut -f 1-2`" \ |
| 46 | = "`guix package -p "$profile" -I | cut -f 1-2`" |
| 47 | test "`guix package -p "$profile" -I | cut -f 3`" = "out" |
| 48 | rm "$profile" |
| 49 | |
| 50 | guix package --bootstrap -p "$profile" -i guile-bootstrap |
| 51 | test -L "$profile" && test -L "$profile-1-link" |
| 52 | test -f "$profile/bin/guile" |
| 53 | |
| 54 | # Make sure the profile is a GC root. |
| 55 | guix gc --list-live | grep "`readlink "$profile-1-link"`" |
| 56 | |
| 57 | # Installing the same package a second time does nothing. |
| 58 | guix package --bootstrap -p "$profile" -i guile-bootstrap |
| 59 | test -L "$profile" && test -L "$profile-1-link" |
| 60 | ! test -f "$profile-2-link" |
| 61 | test -f "$profile/bin/guile" |
| 62 | |
| 63 | # No search path env. var. here. |
| 64 | guix package -p "$profile" --search-paths |
| 65 | guix package -p "$profile" --search-paths | grep '^export PATH=' |
| 66 | test "`guix package -p "$profile" --search-paths | wc -l`" = 1 # $PATH |
| 67 | ( set -e; set -x; \ |
| 68 | eval `guix package --search-paths=prefix -p "$PWD/$profile"`; \ |
| 69 | test "`type -P guile`" = "$PWD/$profile/bin/guile" ; \ |
| 70 | type -P rm ) |
| 71 | |
| 72 | # Exit with 1 when a generation does not exist. |
| 73 | if guix package -p "$profile" --delete-generations=42; |
| 74 | then false; else true; fi |
| 75 | |
| 76 | # Exit with 0 when trying to delete the zeroth generation. |
| 77 | guix package -p "$profile" --delete-generations=0 |
| 78 | |
| 79 | # Make sure multiple arguments to -i works. |
| 80 | guix package --bootstrap -i guile gcc -p "$profile" -n |
| 81 | |
| 82 | # Make sure the `:' syntax works. |
| 83 | guix package --bootstrap -i "glibc:debug" -p "$profile" -n |
| 84 | |
| 85 | # Make sure nonexistent outputs are reported. |
| 86 | guix package --bootstrap -i "guile-bootstrap:out" -p "$profile" -n |
| 87 | if guix package --bootstrap -i "guile-bootstrap:does-not-exist" -p "$profile" -n; |
| 88 | then false; else true; fi |
| 89 | if guix package --bootstrap -i "guile-bootstrap:does-not-exist" -p "$profile"; |
| 90 | then false; else true; fi |
| 91 | |
| 92 | # Check whether `--list-available' returns something sensible. |
| 93 | guix package -p "$profile" -A 'gui.*e' | grep guile |
| 94 | |
| 95 | # Check whether `--show' returns something sensible. |
| 96 | guix package --show=guile | grep "^name: guile" |
| 97 | |
| 98 | # Ensure `--show' doesn't fail for packages with non-package inputs. |
| 99 | guix package --show=texlive |
| 100 | |
| 101 | # Search. |
| 102 | LC_MESSAGES=C |
| 103 | export LC_MESSAGES |
| 104 | test "`guix package -s "An example GNU package" | grep ^name:`" = \ |
| 105 | "name: hello" |
| 106 | test -z "`guix package -s "n0t4r341p4ck4g3"`" |
| 107 | |
| 108 | # Search with one and then two regexps. |
| 109 | # First we get printed circuit boards *and* board games. |
| 110 | guix package -s '\<board\>' > "$tmpfile" |
| 111 | grep '^name: pcb' "$tmpfile" |
| 112 | grep '^name: gnubg' "$tmpfile" |
| 113 | |
| 114 | # Second we get only board games. |
| 115 | guix package -s '\<board\>' -s game > "$tmpfile" |
| 116 | grep -v '^name: pcb' "$tmpfile" > /dev/null |
| 117 | grep '^name: gnubg' "$tmpfile" |
| 118 | |
| 119 | rm -f "$tmpfile" |
| 120 | |
| 121 | # Make sure `--search' can display all the packages. |
| 122 | guix package --search="" > /dev/null |
| 123 | |
| 124 | # There's no generation older than 12 months, so the following command should |
| 125 | # have no effect. |
| 126 | generation="`readlink_base "$profile"`" |
| 127 | if guix package -p "$profile" --delete-generations=12m; |
| 128 | then false; else true; fi |
| 129 | test "`readlink_base "$profile"`" = "$generation" |
| 130 | |
| 131 | # The following command should not delete the current generation, even though |
| 132 | # it matches the given pattern (see <http://bugs.gnu.org/19978>.) And since |
| 133 | # there's nothing else to delete, it should just fail. |
| 134 | guix package --list-generations -p "$profile" |
| 135 | if guix package --bootstrap -p "$profile" --delete-generations=1.. |
| 136 | then false; else true; fi |
| 137 | test "`readlink_base "$profile"`" = "$generation" |
| 138 | |
| 139 | # Make sure $profile is a GC root at this point. |
| 140 | real_profile="`readlink -f "$profile"`" |
| 141 | if guix gc -d "$real_profile" |
| 142 | then false; else true; fi |
| 143 | test -d "$real_profile" |
| 144 | |
| 145 | # Now, let's remove all the symlinks to $real_profile, and make sure |
| 146 | # $real_profile is no longer a GC root. |
| 147 | rm "$profile" "$profile"-[0-9]-link |
| 148 | guix gc -d "$real_profile" |
| 149 | [ ! -d "$real_profile" ] |
| 150 | |
| 151 | # Package transformations. |
| 152 | |
| 153 | # Make sure we get the right version number when using '--with-source'. |
| 154 | mkdir "$module_dir" |
| 155 | emacs_tarball="$module_dir/emacs-42.5.9rc7.tar.gz" |
| 156 | touch "$emacs_tarball" |
| 157 | guix package -p "$profile" -i emacs --with-source="$emacs_tarball" -n \ |
| 158 | 2> "$tmpfile" |
| 159 | grep -E 'emacs[[:blank:]]+42\.5\.9rc7[[:blank:]]+.*-emacs-42.5.9rc7' \ |
| 160 | "$tmpfile" |
| 161 | rm "$emacs_tarball" "$tmpfile" |
| 162 | rmdir "$module_dir" |
| 163 | |
| 164 | |
| 165 | # |
| 166 | # Try with the default profile. |
| 167 | # |
| 168 | |
| 169 | XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}" |
| 170 | export XDG_CACHE_HOME |
| 171 | HOME="$PWD/t-home-$$" |
| 172 | export HOME |
| 173 | |
| 174 | mkdir -p "$HOME" |
| 175 | |
| 176 | # Get the canonical directory name so that 'guix package' recognizes it. |
| 177 | HOME="`cd $HOME; pwd -P`" |
| 178 | |
| 179 | guix package --bootstrap -i guile-bootstrap |
| 180 | test -L "$HOME/.guix-profile" |
| 181 | test -f "$HOME/.guix-profile/bin/guile" |
| 182 | |
| 183 | # Move to the empty profile. |
| 184 | default_profile="`readlink "$HOME/.guix-profile"`" |
| 185 | for i in `seq 1 3` |
| 186 | do |
| 187 | # Make sure the current generation is a GC root. |
| 188 | profile_link="`readlink "$default_profile"`" |
| 189 | guix gc --list-live | grep "`readlink "$profile_link"`" |
| 190 | |
| 191 | guix package --bootstrap --roll-back |
| 192 | ! test -f "$HOME/.guix-profile/bin" |
| 193 | ! test -f "$HOME/.guix-profile/lib" |
| 194 | test "`readlink "$default_profile"`" = "$default_profile-0-link" |
| 195 | done |
| 196 | |
| 197 | # Check whether '-p ~/.guix-profile' makes any difference. |
| 198 | # See <http://bugs.gnu.org/17939>. |
| 199 | if test -e "$HOME/.guix-profile-0-link"; then false; fi |
| 200 | if test -e "$HOME/.guix-profile-1-link"; then false; fi |
| 201 | guix package --bootstrap -p "$HOME/.guix-profile" -i guile-bootstrap |
| 202 | if test -e "$HOME/.guix-profile-1-link"; then false; fi |
| 203 | guix package --bootstrap --roll-back -p "$HOME/.guix-profile" |
| 204 | if test -e "$HOME/.guix-profile-0-link"; then false; fi |
| 205 | |
| 206 | # Extraneous argument. |
| 207 | if guix package install foo-bar; |
| 208 | then false; else true; fi |
| 209 | |
| 210 | # Make sure the "broken pipe" doesn't yield an error. |
| 211 | # Note: 'pipefail' is a Bash-specific option. |
| 212 | set -o pipefail || true |
| 213 | guix package -A g | head -1 2> "$HOME/err1" |
| 214 | guix package -I | head -1 2> "$HOME/err2" |
| 215 | test "`cat "$HOME/err1" "$HOME/err2"`" = "" |
| 216 | |
| 217 | # Make sure '-L' extends the package module search path. |
| 218 | mkdir "$module_dir" |
| 219 | |
| 220 | cat > "$module_dir/foo.scm"<<EOF |
| 221 | (define-module (foo) |
| 222 | #:use-module (guix packages) |
| 223 | #:use-module (gnu packages emacs)) |
| 224 | |
| 225 | (define-public x |
| 226 | (package (inherit emacs) |
| 227 | (name "emacs-foo-bar") |
| 228 | (version "42"))) |
| 229 | EOF |
| 230 | |
| 231 | guix package -A emacs-foo-bar -L "$module_dir" | grep 42 |
| 232 | guix package -i emacs-foo-bar@42 -n -L "$module_dir" |
| 233 | |
| 234 | # Same thing using the 'GUIX_PACKAGE_PATH' environment variable. |
| 235 | GUIX_PACKAGE_PATH="$module_dir" |
| 236 | export GUIX_PACKAGE_PATH |
| 237 | guix package -A emacs-foo-bar | grep 42 |
| 238 | guix package -i emacs-foo-bar@42 -n |
| 239 | |
| 240 | # Make sure patches that live under $GUIX_PACKAGE_PATH are found. |
| 241 | cat > "$module_dir/emacs.patch"<<EOF |
| 242 | This is a fake patch. |
| 243 | EOF |
| 244 | cat > "$module_dir/foo.scm"<<EOF |
| 245 | (define-module (foo) |
| 246 | #:use-module (guix packages) |
| 247 | #:use-module (gnu packages) |
| 248 | #:use-module (gnu packages emacs)) |
| 249 | |
| 250 | (define-public x |
| 251 | (package (inherit emacs) |
| 252 | (source (origin (inherit (package-source emacs)) |
| 253 | (patches (list (search-patch "emacs.patch"))))) |
| 254 | (name "emacs-foo-bar-patched") |
| 255 | (version "42"))) |
| 256 | |
| 257 | (define-public y |
| 258 | (package (inherit emacs) |
| 259 | (name "super-non-portable-emacs") |
| 260 | (supported-systems '("foobar64-hurd")))) |
| 261 | EOF |
| 262 | guix package -i emacs-foo-bar-patched -n |
| 263 | |
| 264 | # Same when -L is used. |
| 265 | ( unset GUIX_PACKAGE_PATH; \ |
| 266 | guix package -L "$module_dir" -i emacs-foo-bar-patched -n ) |
| 267 | |
| 268 | # Make sure installing from a file works. |
| 269 | cat > "$module_dir/package.scm"<<EOF |
| 270 | (use-modules (gnu)) |
| 271 | (use-package-modules bootstrap) |
| 272 | |
| 273 | %bootstrap-guile |
| 274 | EOF |
| 275 | guix package --bootstrap --install-from-file="$module_dir/package.scm" |
| 276 | |
| 277 | # This one should not show up in searches since it's no supported on the |
| 278 | # current system. |
| 279 | test "`guix package -A super-non-portable-emacs`" = "" |
| 280 | test "`guix package -s super-non-portable-emacs | grep ^systems:`" = "systems: " |
| 281 | |
| 282 | # Don't upgrade packages marked for removal: <http://bugs.gnu.org/27262>. |
| 283 | guix package --bootstrap -p "$profile" -i guile-bootstrap |
| 284 | |
| 285 | cat > "$module_dir/foo.scm"<<EOF |
| 286 | (define-module (foo) |
| 287 | #:use-module (guix) |
| 288 | #:use-module (gnu packages bootstrap)) |
| 289 | |
| 290 | (define-public x |
| 291 | (package (inherit %bootstrap-guile) (version "42"))) |
| 292 | EOF |
| 293 | |
| 294 | guix package --bootstrap -p "$profile" -r guile-bootstrap -u guile |
| 295 | test ! -f "$profile/bin/guile" |
| 296 | guix package --bootstrap -p "$profile" --roll-back |
| 297 | test -f "$profile/bin/guile" |
| 298 | rm "$profile-2-link" |
| 299 | |
| 300 | unset GUIX_PACKAGE_PATH |
| 301 | |
| 302 | |
| 303 | # Using 'GUIX_BUILD_OPTIONS'. |
| 304 | available="`guix package -A | sort`" |
| 305 | GUIX_BUILD_OPTIONS="--dry-run --no-grafts" |
| 306 | export GUIX_BUILD_OPTIONS |
| 307 | |
| 308 | # Make sure $GUIX_BUILD_OPTIONS is not simply appended to the command-line, |
| 309 | # which would break 'guix package -A' and similar. |
| 310 | available2="`guix package -A | sort`" |
| 311 | test "$available2" = "$available" |
| 312 | guix package -I |
| 313 | |
| 314 | # Restore '--no-grafts', which makes sure we don't end up building stuff when |
| 315 | # '--dry-run' is passed. |
| 316 | GUIX_BUILD_OPTIONS="--no-grafts" |
| 317 | |
| 318 | # Applying a manifest file. |
| 319 | cat > "$module_dir/manifest.scm"<<EOF |
| 320 | (use-package-modules bootstrap) |
| 321 | |
| 322 | (packages->manifest (list %bootstrap-guile)) |
| 323 | EOF |
| 324 | guix package --bootstrap -m "$module_dir/manifest.scm" |
| 325 | guix package -I | grep guile |
| 326 | test `guix package -I | wc -l` -eq 1 |
| 327 | |
| 328 | # Error reporting. |
| 329 | cat > "$module_dir/manifest.scm"<<EOF |
| 330 | (use-package-modules bootstrap) |
| 331 | (packages->manifest |
| 332 | (list %bootstrap-guile |
| 333 | wonderful-package-that-does-not-exist)) |
| 334 | EOF |
| 335 | if guix package --bootstrap -n -m "$module_dir/manifest.scm" \ |
| 336 | 2> "$module_dir/stderr" |
| 337 | then false |
| 338 | else |
| 339 | cat "$module_dir/stderr" |
| 340 | grep "manifest.scm:[1-3]:.*wonderful-package.*: unbound variable" \ |
| 341 | "$module_dir/stderr" |
| 342 | fi |