Overview
The regular nix-env
operations manipulate (build new) environments
consisting of a merge of several packages created by symlinking all
the files from the individual packages together into common bin,
lib, etc. directories which are then added to the users $PATH
,
$PYTHONPATH
, etc. environment variables.
This is a project to add a more module
style interface. The
module
utility provides a command that manipulates the users
environment to enable multiple packages simultaneously by placing
multiple entries in the users $PATH
, $PYTHONPATH
, etc. environment
variables.
The following is an example of the sort of interaction we are looking to support
- user logs in with no Nix environment,
- user runs
nix-path load nixpkgs.python27 nixpkgs.python27Packages.scipy
, - user runs
nix-path unload nixpkgs.python27Packages.scipy
, and - user runs
nix-path load nixpkgs.python27Packages.regex
.
Modify user environment
As with the module command, the ultimate output of nix-path
is
shell script that can be sourced by the current shell in order to
modify the user's environment as requested. This is done by creating
a function such as
function module {
eval "$(nix-path bash "$@")"
}
Assuming an initial empty environment, based on the final environment diff presented at the end of the computing enviroment additions section, a typical invocation would be
module load nixpkgs.python27 nixpkgs.python27Packages.scipy
export NIX_MODULES="nixpkgs.python27 nixpkgs.python27Packages.scipy"
export NIX_CC=/nix/store/jycz7ha7dm3ls1sjnznn3638193klbxv-gcc-wrapper-5.3.0
export NIX_CFLAGS_COMPILE= -isystem /nix/store/88186csqfg6v6zldsip0w122hwp761m6-python-2.7.11/include -isystem /nix/store/jvnlwk07wqwrry024x07isq83wz8j30k-openblas-0.2.14/include
export NIX_LDFLAGS=-rpath /nix/store/a2j8f1mvk039bkvyxfzdlpa5h31k3k0z-shell/lib64 -rpath /nix/store/a2j8f1mvk039bkvyxfzdlpa5h31k3k0z-shell/lib -L/nix/store/88186csqfg6v6zldsip0w122hwp761m6-python-2.7.11/lib -L/nix/store/w7fj1fxrjvhshik2d71zlfxns8hjn0dh-python2.7-scipy-0.17.0/lib -L/nix/store/jvnlwk07wqwrry024x07isq83wz8j30k-openblas-0.2.14/lib -L/nix/store/5ag1nw0s6mzhmhxrm0ij8s76yvi2wxpp-python2.7-numpy-1.10.4/lib -L/nix/store/mkav3jmz0p6jd8ik7h9mnfa3i3k5vrjw-python2.7-setuptools-19.4/lib
export PATH=/nix/store/88186csqfg6v6zldsip0w122hwp761m6-python-2.7.11/bin:/nix/store/jvnlwk07wqwrry024x07isq83wz8j30k-openblas-0.2.14/bin:/nix/store/5ag1nw0s6mzhmhxrm0ij8s76yvi2wxpp-python2.7-numpy-1.10.4/bin:/nix/store/mkav3jmz0p6jd8ik7h9mnfa3i3k5vrjw-python2.7-setuptools-19.4/bin:/nix/store/wz6508rdk04wn5nilzil1c7zbqg7lx4w-patchelf-0.9/bin:/nix/store/krwiax9xcn6m745k5ifwbcmavmhpi43k-paxctl-0.9/bin:/nix/store/jycz7ha7dm3ls1sjnznn3638193klbxv-gcc-wrapper-5.3.0/bin:/nix/store/xmrh23qgsbrk9gd0z72sj58kg1czmpcd-binutils-2.26/bin:/nix/store/d2ljpb414jpmzik3cvl0xlmr5m4aggp7-gcc-5.3.0/bin:/nix/store/bb32xf954imhdrzn7j8h82xs1bx7p3fr-glibc-2.23/bin:/nix/store/lphk3qrh53kv2j69b3sry5jmhfbrz1ns-coreutils-8.25/bin:/nix/store/lphk3qrh53kv2j69b3sry5jmhfbrz1ns-coreutils-8.25/bin:/nix/store/jshnvw5qxcbz8hyjx0k5g9f5ddlny7lb-findutils-4.4.2/bin:/nix/store/sfcxcsswbgbv2vfkf6ma420zikbz4k9n-diffutils-3.3/bin:/nix/store/c2rnzsrhby57x1cg9kab7zbcgcqfam1y-gnused-4.2.2/bin:/nix/store/rlw8bhavsn39fgvvxif89f4w476x6z7p-gnugrep-2.22/bin:/nix/store/wskqdq2cif8lnr59d1yy41j5k45n21k5-gawk-4.1.3/bin:/nix/store/h0cy1px0jdr0j331r79zr3i3bybwpxqw-gnutar-1.28/bin:/nix/store/4yl71n9qsjw5bkndzdg1aarzassy6hpy-gzip-1.6/bin:/nix/store/nlhixpi844nri62cdkcp8d4dkhxwvj2j-bzip2-1.0.6/bin:/nix/store/cqnrdrxkwbq835rkyxcscdw119yppjpl-gnumake-4.1/bin:/nix/store/7sb42axk5lrxqz45nldrb2pchlys14s1-bash-4.3-p42/bin:/nix/store/n1ih0w9qcjswvprycxxgx82wg10h8dpj-patch-2.7.5/bin:/nix/store/nbi1p1l7f25nr8ji9vf6bfi4blw9dhwa-xz-5.2.2/bin:"$PATH"
export CXX=g++
export PYTHONPATH=/nix/store/88186csqfg6v6zldsip0w122hwp761m6-python-2.7.11/lib/python2.7/site-packages:/nix/store/w7fj1fxrjvhshik2d71zlfxns8hjn0dh-python2.7-scipy-0.17.0/lib/python2.7/site-packages:/nix/store/5ag1nw0s6mzhmhxrm0ij8s76yvi2wxpp-python2.7-numpy-1.10.4/lib/python2.7/site-packages:/nix/store/mkav3jmz0p6jd8ik7h9mnfa3i3k5vrjw-python2.7-setuptools-19.4/lib/python2.7/site-packages
export CC=gcc
where "$PATH"
would actually be expanded by nix-path
to be the
original value of $PATH
. Note that inclusion of $NIX_MODULES
environment variable that keeps track of the currently loaded modules.
This modification to the user's environment is computed as follows
- compute the environment
additions required by the old
package set given by
$NIX_MODULES
, - compute the new set of packages requires according to the user's
secified operation (i.e., add to
$NIX_MODULES
onmodule load
and remove from$NIX_MODULES
onmodule unload
), - compute the environment additions required by the new package set,
- compute the new user's environment based by making the additions, removals, and substitutions to the current environment dictated by the difference between old environment additions and the new ones,
- output the new environment created from the old one by making these
changes and updating
$NIX_MODULES
to reflect the new packages.
Comparison to nix-shell
The nix-shell -p python27 python27Packages.scipy
command builds the
following derivation
nix-instantiate --expr 'with import <nixpkgs> { }; runCommand "shell" { buildInputs = [ python27 python27Packages.scipy ]; } "env"'
/nix/store/c5rxb8fkfqqzxwrxafhp7gjhpszag9dm-shell.drv
pp-aterm -i /nix/store/c5rxb8fkfqqzxwrxafhp7gjhpszag9dm-shell.drv
Derive(
[("out", "/nix/store/a2j8f1mvk039bkvyxfzdlpa5h31k3k0z-shell", "", "")]
, [ ("/nix/store/9my5m5a8annapkzqjizn2156wv2v71ag-bash-4.3-p42.drv", ["out"])
, ("/nix/store/dp8i98g0gs9qf09hm6ndc2jxh7qcx656-stdenv.drv", ["out"])
, ("/nix/store/l62r4a1ngr22f935lrf72gq2lpvv82cx-python2.7-scipy-0.17.0.drv", ["out"])
, ("/nix/store/nc9lg7f0f0mh8882vqnqpi0pkq8zkc79-python-2.7.11.drv", ["out"])
]
, ["/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh"]
, "x86_64-linux"
, "/nix/store/7sb42axk5lrxqz45nldrb2pchlys14s1-bash-4.3-p42/bin/bash"
, ["-e", "/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh"]
, [ ("buildCommand", "env")
, ("buildInputs", "")
, ("builder", "/nix/store/7sb42axk5lrxqz45nldrb2pchlys14s1-bash-4.3-p42/bin/bash")
, ("name", "shell")
, ("nativeBuildInputs", "/nix/store/88186csqfg6v6zldsip0w122hwp761m6-python-2.7.11 /nix/store/w7fj1fxrjvhshik2d71zlfxns8hjn0dh-python2.7-scipy-0.17.0")
, ("out", "/nix/store/a2j8f1mvk039bkvyxfzdlpa5h31k3k0z-shell")
, ("propagatedBuildInputs", "")
, ("propagatedNativeBuildInputs", "")
, ("stdenv", "/nix/store/6k2hhari1vjiy0wjjv3lcvaf8s1pcbmm-stdenv")
, ("system", "x86_64-linux")
]
)
It then parses this derivation, set the environment variables
indicated in it, and then starts a shell with an rcfile that does
source $stdenv/setup
. This is the script that prepares for doing a
build inside a Nix chroot environment and it uses the various Nix hook
mechanisms to create an approriate environment.
We will do the same, except, instead of starting a shell, we will output commands to set the evnironment variables. This will allow our output to be evaluated by bash and modify the user's current environment to give access to the desired packages.
Computing environment additions
This section details how to determine what environment additions are required to enable a set of Nix packages.
We need the store paths for coreutils
, stdenv
, and each of the packages
our user would like in their environment
nix-env --query --available --out-path --attr nixpkgs.bash
nix-env --query --available --out-path --attr nixpkgs.coreutils
nix-env --query --available --out-path --attr nixpkgs.stdenv
nix-env --query --available --out-path --attr nixpkgs.python27
nix-env --query --available --out-path --attr nixpkgs.python27Packages.scipy
bash-4.3-p42 doc=/nix/store/mzc36xa3w8djrafpc9sfxzyb9bafjbr3-bash-4.3-p42-doc;/nix/store/7sb42axk5lrxqz45nldrb2pchlys14s1-bash-4.3-p42
coreutils-8.25 /nix/store/lphk3qrh53kv2j69b3sry5jmhfbrz1ns-coreutils-8.25
stdenv /nix/store/6k2hhari1vjiy0wjjv3lcvaf8s1pcbmm-stdenv
python-2.7.11 /nix/store/88186csqfg6v6zldsip0w122hwp761m6-python-2.7.11
python2.7-scipy-0.17.0 /nix/store/w7fj1fxrjvhshik2d71zlfxns8hjn0dh-python2.7-scipy-0.17.0
The bash
and stdenv
paths can be burned into nix-path
, but the
stdenv
package should likely always be looked up to ensure the
version agrees with the requested packages. If any of these store
paths do not exist then we need to create them. See build
packages for details.
cat << "EOF" | /nix/store/lphk3qrh53kv2j69b3sry5jmhfbrz1ns-coreutils-8.25/bin/env -i /nix/store/7sb42axk5lrxqz45nldrb2pchlys14s1-bash-4.3-p42/bin/bash
export TMPDIR="$(/nix/store/lphk3qrh53kv2j69b3sry5jmhfbrz1ns-coreutils-8.25/bin/mktemp -d)"
echo '# Pre-setup environment'
export NIX_BUILD_TOP="$TMPDIR"
export NIX_STORE=/nix/store
export nativeBuildInputs="/nix/store/88186csqfg6v6zldsip0w122hwp761m6-python-2.7.11 /nix/store/w7fj1fxrjvhshik2d71zlfxns8hjn0dh-python2.7-scipy-0.17.0"
export out="/nix/store/a2j8f1mvk039bkvyxfzdlpa5h31k3k0z-shell"
export stdenv="/nix/store/6k2hhari1vjiy0wjjv3lcvaf8s1pcbmm-stdenv"
/nix/store/lphk3qrh53kv2j69b3sry5jmhfbrz1ns-coreutils-8.25/bin/env
echo '# Post-setup environment'
source "$stdenv/setup"
unset NIX_ENFORCE_PURITY NIX_INDENT_MAKE NIX_BUILD_CORES SOURCE_DATE_EPOCH TZ SSL_CERT_FILE _PATH shell SHELL CONFIG_SHELL
/nix/store/lphk3qrh53kv2j69b3sry5jmhfbrz1ns-coreutils-8.25/bin/env
rm -fr "$TMPDIR"
EOF
# Pre-setup environment
TMPDIR=/tmp/tmp.wQwnLiyZVf
nativeBuildInputs=/nix/store/88186csqfg6v6zldsip0w122hwp761m6-python-2.7.11 /nix/store/w7fj1fxrjvhshik2d71zlfxns8hjn0dh-python2.7-scipy-0.17.0
NIX_STORE=/nix/store
stdenv=/nix/store/6k2hhari1vjiy0wjjv3lcvaf8s1pcbmm-stdenv
NIX_BUILD_TOP=/tmp/tmp.wQwnLiyZVf
PWD=/home/tyson/nix-path
out=/nix/store/a2j8f1mvk039bkvyxfzdlpa5h31k3k0z-shell
SHLVL=1
_=/nix/store/lphk3qrh53kv2j69b3sry5jmhfbrz1ns-coreutils-8.25/bin/env
# Post-setup environment
NIX_CC=/nix/store/jycz7ha7dm3ls1sjnznn3638193klbxv-gcc-wrapper-5.3.0
TMPDIR=/tmp/tmp.wQwnLiyZVf
NIX_CFLAGS_COMPILE= -isystem /nix/store/88186csqfg6v6zldsip0w122hwp761m6-python-2.7.11/include -isystem /nix/store/jvnlwk07wqwrry024x07isq83wz8j30k-openblas-0.2.14/include
nativeBuildInputs=/nix/store/88186csqfg6v6zldsip0w122hwp761m6-python-2.7.11 /nix/store/w7fj1fxrjvhshik2d71zlfxns8hjn0dh-python2.7-scipy-0.17.0
NIX_STORE=/nix/store
stdenv=/nix/store/6k2hhari1vjiy0wjjv3lcvaf8s1pcbmm-stdenv
NIX_LDFLAGS=-rpath /nix/store/a2j8f1mvk039bkvyxfzdlpa5h31k3k0z-shell/lib64 -rpath /nix/store/a2j8f1mvk039bkvyxfzdlpa5h31k3k0z-shell/lib -L/nix/store/88186csqfg6v6zldsip0w122hwp761m6-python-2.7.11/lib -L/nix/store/w7fj1fxrjvhshik2d71zlfxns8hjn0dh-python2.7-scipy-0.17.0/lib -L/nix/store/jvnlwk07wqwrry024x07isq83wz8j30k-openblas-0.2.14/lib -L/nix/store/5ag1nw0s6mzhmhxrm0ij8s76yvi2wxpp-python2.7-numpy-1.10.4/lib -L/nix/store/mkav3jmz0p6jd8ik7h9mnfa3i3k5vrjw-python2.7-setuptools-19.4/lib
PATH=/nix/store/88186csqfg6v6zldsip0w122hwp761m6-python-2.7.11/bin:/nix/store/jvnlwk07wqwrry024x07isq83wz8j30k-openblas-0.2.14/bin:/nix/store/5ag1nw0s6mzhmhxrm0ij8s76yvi2wxpp-python2.7-numpy-1.10.4/bin:/nix/store/mkav3jmz0p6jd8ik7h9mnfa3i3k5vrjw-python2.7-setuptools-19.4/bin:/nix/store/wz6508rdk04wn5nilzil1c7zbqg7lx4w-patchelf-0.9/bin:/nix/store/krwiax9xcn6m745k5ifwbcmavmhpi43k-paxctl-0.9/bin:/nix/store/jycz7ha7dm3ls1sjnznn3638193klbxv-gcc-wrapper-5.3.0/bin:/nix/store/xmrh23qgsbrk9gd0z72sj58kg1czmpcd-binutils-2.26/bin:/nix/store/d2ljpb414jpmzik3cvl0xlmr5m4aggp7-gcc-5.3.0/bin:/nix/store/bb32xf954imhdrzn7j8h82xs1bx7p3fr-glibc-2.23/bin:/nix/store/lphk3qrh53kv2j69b3sry5jmhfbrz1ns-coreutils-8.25/bin:/nix/store/lphk3qrh53kv2j69b3sry5jmhfbrz1ns-coreutils-8.25/bin:/nix/store/jshnvw5qxcbz8hyjx0k5g9f5ddlny7lb-findutils-4.4.2/bin:/nix/store/sfcxcsswbgbv2vfkf6ma420zikbz4k9n-diffutils-3.3/bin:/nix/store/c2rnzsrhby57x1cg9kab7zbcgcqfam1y-gnused-4.2.2/bin:/nix/store/rlw8bhavsn39fgvvxif89f4w476x6z7p-gnugrep-2.22/bin:/nix/store/wskqdq2cif8lnr59d1yy41j5k45n21k5-gawk-4.1.3/bin:/nix/store/h0cy1px0jdr0j331r79zr3i3bybwpxqw-gnutar-1.28/bin:/nix/store/4yl71n9qsjw5bkndzdg1aarzassy6hpy-gzip-1.6/bin:/nix/store/nlhixpi844nri62cdkcp8d4dkhxwvj2j-bzip2-1.0.6/bin:/nix/store/cqnrdrxkwbq835rkyxcscdw119yppjpl-gnumake-4.1/bin:/nix/store/7sb42axk5lrxqz45nldrb2pchlys14s1-bash-4.3-p42/bin:/nix/store/n1ih0w9qcjswvprycxxgx82wg10h8dpj-patch-2.7.5/bin:/nix/store/nbi1p1l7f25nr8ji9vf6bfi4blw9dhwa-xz-5.2.2/bin
NIX_BUILD_TOP=/tmp/tmp.wQwnLiyZVf
PWD=/home/tyson/nix-path
CXX=g++
out=/nix/store/a2j8f1mvk039bkvyxfzdlpa5h31k3k0z-shell
CONFIG_SHELL=/nix/store/7sb42axk5lrxqz45nldrb2pchlys14s1-bash-4.3-p42/bin/bash
SHLVL=1
PYTHONPATH=/nix/store/88186csqfg6v6zldsip0w122hwp761m6-python-2.7.11/lib/python2.7/site-packages:/nix/store/w7fj1fxrjvhshik2d71zlfxns8hjn0dh-python2.7-scipy-0.17.0/lib/python2.7/site-packages:/nix/store/5ag1nw0s6mzhmhxrm0ij8s76yvi2wxpp-python2.7-numpy-1.10.4/lib/python2.7/site-packages:/nix/store/mkav3jmz0p6jd8ik7h9mnfa3i3k5vrjw-python2.7-setuptools-19.4/lib/python2.7/site-packages
CC=gcc
_=/nix/store/lphk3qrh53kv2j69b3sry5jmhfbrz1ns-coreutils-8.25/bin/env
We then need to compute the difference between these two environments
to see what the $stdenv/setup
script has done
NIX_CC=/nix/store/jycz7ha7dm3ls1sjnznn3638193klbxv-gcc-wrapper-5.3.0
NIX_CFLAGS_COMPILE= -isystem /nix/store/88186csqfg6v6zldsip0w122hwp761m6-python-2.7.11/include -isystem /nix/store/jvnlwk07wqwrry024x07isq83wz8j30k-openblas-0.2.14/include
NIX_LDFLAGS=-rpath /nix/store/a2j8f1mvk039bkvyxfzdlpa5h31k3k0z-shell/lib64 -rpath /nix/store/a2j8f1mvk039bkvyxfzdlpa5h31k3k0z-shell/lib -L/nix/store/88186csqfg6v6zldsip0w122hwp761m6-python-2.7.11/lib -L/nix/store/w7fj1fxrjvhshik2d71zlfxns8hjn0dh-python2.7-scipy-0.17.0/lib -L/nix/store/jvnlwk07wqwrry024x07isq83wz8j30k-openblas-0.2.14/lib -L/nix/store/5ag1nw0s6mzhmhxrm0ij8s76yvi2wxpp-python2.7-numpy-1.10.4/lib -L/nix/store/mkav3jmz0p6jd8ik7h9mnfa3i3k5vrjw-python2.7-setuptools-19.4/lib
PATH=/nix/store/88186csqfg6v6zldsip0w122hwp761m6-python-2.7.11/bin:/nix/store/jvnlwk07wqwrry024x07isq83wz8j30k-openblas-0.2.14/bin:/nix/store/5ag1nw0s6mzhmhxrm0ij8s76yvi2wxpp-python2.7-numpy-1.10.4/bin:/nix/store/mkav3jmz0p6jd8ik7h9mnfa3i3k5vrjw-python2.7-setuptools-19.4/bin:/nix/store/wz6508rdk04wn5nilzil1c7zbqg7lx4w-patchelf-0.9/bin:/nix/store/krwiax9xcn6m745k5ifwbcmavmhpi43k-paxctl-0.9/bin:/nix/store/jycz7ha7dm3ls1sjnznn3638193klbxv-gcc-wrapper-5.3.0/bin:/nix/store/xmrh23qgsbrk9gd0z72sj58kg1czmpcd-binutils-2.26/bin:/nix/store/d2ljpb414jpmzik3cvl0xlmr5m4aggp7-gcc-5.3.0/bin:/nix/store/bb32xf954imhdrzn7j8h82xs1bx7p3fr-glibc-2.23/bin:/nix/store/lphk3qrh53kv2j69b3sry5jmhfbrz1ns-coreutils-8.25/bin:/nix/store/lphk3qrh53kv2j69b3sry5jmhfbrz1ns-coreutils-8.25/bin:/nix/store/jshnvw5qxcbz8hyjx0k5g9f5ddlny7lb-findutils-4.4.2/bin:/nix/store/sfcxcsswbgbv2vfkf6ma420zikbz4k9n-diffutils-3.3/bin:/nix/store/c2rnzsrhby57x1cg9kab7zbcgcqfam1y-gnused-4.2.2/bin:/nix/store/rlw8bhavsn39fgvvxif89f4w476x6z7p-gnugrep-2.22/bin:/nix/store/wskqdq2cif8lnr59d1yy41j5k45n21k5-gawk-4.1.3/bin:/nix/store/h0cy1px0jdr0j331r79zr3i3bybwpxqw-gnutar-1.28/bin:/nix/store/4yl71n9qsjw5bkndzdg1aarzassy6hpy-gzip-1.6/bin:/nix/store/nlhixpi844nri62cdkcp8d4dkhxwvj2j-bzip2-1.0.6/bin:/nix/store/cqnrdrxkwbq835rkyxcscdw119yppjpl-gnumake-4.1/bin:/nix/store/7sb42axk5lrxqz45nldrb2pchlys14s1-bash-4.3-p42/bin:/nix/store/n1ih0w9qcjswvprycxxgx82wg10h8dpj-patch-2.7.5/bin:/nix/store/nbi1p1l7f25nr8ji9vf6bfi4blw9dhwa-xz-5.2.2/bin
CXX=g++
PYTHONPATH=/nix/store/88186csqfg6v6zldsip0w122hwp761m6-python-2.7.11/lib/python2.7/site-packages:/nix/store/w7fj1fxrjvhshik2d71zlfxns8hjn0dh-python2.7-scipy-0.17.0/lib/python2.7/site-packages:/nix/store/5ag1nw0s6mzhmhxrm0ij8s76yvi2wxpp-python2.7-numpy-1.10.4/lib/python2.7/site-packages:/nix/store/mkav3jmz0p6jd8ik7h9mnfa3i3k5vrjw-python2.7-setuptools-19.4/lib/python2.7/site-packages
CC=gcc
Building packages
We could just request nix-store
to realize the outpaths, but this
will only works if they are available via a substitution. We will
instead go through the derivation even though this is a bit of a pain
because only nix-env
support the special handling of
~/.nix-defexpr (i.e., going through it and subdirectories to create
an attribute set from all the top-level nix expressions in it).
To be entirely correct it is a good idea to throw in some GC links. We do this using the following scheme for the tempoary derivation links nix-path-<host>-<pid>-<n>
nix-instantiate --add-root /nix/var/nix/gcroots/per-user/tyson/nix-path-gb241-4534-1 --expr 'with import <nixpkgs> { }; python27'
nix-instantiate --add-root /nix/var/nix/gcroots/per-user/tyson/nix-path-gb241-4534-2 --expr 'with import <nixpkgs> { }; python27Packages.scipy'
/nix/var/nix/gcroots/per-user/tyson/nix-path-gb241-4534-1
/nix/var/nix/gcroots/per-user/tyson/nix-path-gb241-4534-2
nix-store --add-root /nix/var/nix/gcroots/per-user/tyson/88186csqfg6v6zldsip0w122hwp761m6-python-2.7.11 --realize /nix/var/nix/gcroots/per-user/tyson/nix-path-gb241-4534-1
nix-store --add-root /nix/var/nix/gcroots/per-user/tyson/w7fj1fxrjvhshik2d71zlfxns8hjn0dh-python2.7-scipy-0.17.0 --realize /nix/var/nix/gcroots/per-user/tyson/nix-path-gb241-4534-2
rm /nix/var/nix/gcroots/per-user/tyson/nix-path-gb241-4534-1
rm /nix/var/nix/gcroots/per-user/tyson/nix-path-gb241-4534-2
/nix/var/nix/gcroots/per-user/tyson/88186csqfg6v6zldsip0w122hwp761m6-python-2.7.11
/nix/var/nix/gcroots/per-user/tyson/w7fj1fxrjvhshik2d71zlfxns8hjn0dh-python2.7-scipy-0.17.0
We leave the links to the actual packages in the store to avoid the garbage collector collecting them while the user is using them.