Skip to content

Commit

Permalink
Merge pull request NixOS#40 from sixhobbits/add-shell-tutorial-edits
Browse files Browse the repository at this point in the history
tutorial edits
  • Loading branch information
domenkozar committed Jun 14, 2020
2 parents 0a47ee3 + 96302fe commit 775842d
Showing 1 changed file with 36 additions and 30 deletions.
66 changes: 36 additions & 30 deletions source/tutorials/ad-hoc-developer-environments.rst
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
Ad hoc developer environments
=============================

Assuming you have :ref:`Nix installed <install-nix>`, it is able to download packages
and provide a new **shell environment** with packages available.
Assuming you have :ref:`Nix installed <install-nix>`, you can use it
to download packages and create new **shell environments** that use these packages.

This is a great way to play with Nix tooling and see some of its potential.


What is a shell environment?
----------------------------

A shell environment gives you access to the exact versions of packages specified by Nix.

A hello world example:

.. code:: shell-session
Expand All @@ -28,20 +30,21 @@ A hello world example:
$ hello
The program ‘hello’ is currently not installed.
Here we used the ``-p`` (packages) flag to specify that we needed the ``hello`` dependency. Nix found this, downloaded it, and made it available in a shell environment.


When are shell environments useful?
-----------------------------------

Sometimes you'd like **to use a tool, but it's not installed yet**. You don't want to
bother installing software, you only want to have it now.
Sometimes you'd like **to use a tool that you do not have installed**. You don't want to
bother installing the software, but you want to use it.

Sometimes you'd like **to try a tool for a few minutes**. For example, there's a new shiny
tool for writing presentation slides.

Sometimes you'd like **to give someone a one-liner also with instructions how to install
tools** being used and such that it works between all Linux distributions and on MacOS.
Sometimes you'd like **to give someone else a one-liner to install a set of tools** and you want this to work on all Linux distributions and MacOS.

Sometimes you'd like **to provide a script that is reproducible**, meaning it will also provide the tooling.
Sometimes you'd like **to provide a script that is reproducible**, meaning it will also provide any tools that it depends on.


Searching package attribute names
Expand All @@ -60,14 +63,14 @@ You can search the package list using:
gitMinimal git-2.25.0
The first column is the :term:`attribute name` and the second is :term:`package name` and its version.
The first column is the :term:`attribute name` and the second is the :term:`package name` and its version.

Once you are comfortable doing this, you can add other things too.
For example, packages of your own or custom shell aliases.

.. note::

Query for searching packages is a regex, so be aware when it comes to special characters.
The query you use for searching packages is a regex, so be aware when it comes to special characters.


Ad hoc shell environments
Expand All @@ -77,7 +80,7 @@ Once you have the :term:`attribute name` for packages, you can start a shell:

.. code:: shell-session
$ nix-shell -p git vim nano joe
$ nix-shell -p gitMinimal vim nano joe
these paths will be fetched (44.16 MiB download, 236.37 MiB unpacked):
...
/nix/store/fsn35pc8njnimgn2sn26dlsyxya1wssb-vim-8.2.0013
Expand All @@ -90,6 +93,8 @@ Once you have the :term:`attribute name` for packages, you can start a shell:
[nix-shell:~]$ which git
/nix/store/hx63qkip16i4wifaqgxwrrmxj4az53h1-git-2.25.0/bin/git
Note that even if you had git installed before, once in the shell only the exact version installed by Nix is used.

Press ``CTRL-D`` to exit the shell and those packages won't be available anymore.


Expand All @@ -98,7 +103,7 @@ Beyond tooling: Python libraries

``nix-shell`` provides a bunch of other bash variables from packages specified.

A quick example using Python and ``$PYTHONPATH``:
Let's try a quick example using Python and ``$PYTHONPATH``:

.. code:: shell-session
Expand All @@ -108,22 +113,24 @@ A quick example using Python and ``$PYTHONPATH``:
[nix-shell:~]$ python -c 'import django; print(django)'
<module 'django' from '/nix/store/c8ipxqsgh8xd6zmwb026lldsgr7hi315-python3-3.8.1-env/lib/python3.8/site-packages/django/__init__.py'>
We create ad hoc environment with ``$PYTHONPATH`` set and ``python`` available with ``django`` package as well.
We create an ad hoc environment with ``$PYTHONPATH`` set and ``python`` available, along with the ``django`` package as well.

``-p`` argument accepts Nix expression, but going into the Nix language is out of scope of this tutorial.
The ``-p`` argument can handle more than attribute names. You can use a full Nix expression, but we'll cover that in later tutorials.


Towards reproducibility
-----------------------

If you handed over these commands to another developer, they might get different results.
Even running in these basic Nix shells, if you handed over these commands to another developer, they could get different results.

These shell environments are **really convenient**, but they are **not yet reproducible**.
These shell environments are **really convenient**, but they are not **perfectly reproducible** in this form.

What do we mean by reproducible? No matter when or on what machine you run the command, the result will be the same.
The very same environment will be provided each time.
What do we mean by reproducible? A fully reproducible example would give exactly the same results no matter **when** or **on what machine** you run the command.
The environment provided would be identical each time.

The following is entirely reproducible and something you can share between colleagues:
Nix also offers fully reproducible environments, which it calls pure environments.

The following is a fully reproducible example and something that different colleagues with different machines, for example, could share.

.. code:: shell-session
Expand All @@ -134,19 +141,17 @@ The following is entirely reproducible and something you can share between colle
There are two things going on here:

1. ``--pure`` flag makes sure that bash environnment from your system is not inherited. That means the only ``git`` is available inside the shell.
This is useful for one-liners and scripts that run for example on a CI. While developing however, we'd like to have our editor around and
a bunch of other things so we skip the flag.
1. ``--pure`` flag makes sure that the bash environment from your system is not inherited. That means only the ``git`` that Nix installed is available inside the shell.
This is useful for one-liners and scripts that run for example within a CI environment. While developing, however, we'd like to have our editor around and a bunch of other things. Therefore we might skip the flag for development environments but use it in build ones.

2. ``-I`` pins nixpkgs revision to an exact git revision, leaving no doubt which version of Nix packages will be used.
2. The ``-I`` flag pins the nixpkgs revision to an **exact git revision**, leaving no doubt which exact version of Nix packages will be used.


Reproducible executables
------------------------

Finally, we can wrap scripts to provide a reproducible shell environment that we can commit to a git repository
and share with strangers online. As long as they have Nix installed, they'll be able to execute the script without
worrying about manually installing and later uninstalling dependencies at all.
Finally, we can wrap scripts with Nix to provide a reproducible shell environment that we can commit to a git repository
and share with strangers online. As long as they have Nix installed, they'll be able to execute the script without worrying about manually installing and later uninstalling dependencies at all.

.. code:: python
Expand All @@ -158,17 +163,18 @@ worrying about manually installing and later uninstalling dependencies at all.
print(django)
This is essentially the same example as in previous section, but this time declaratively source controlled!
This is essentially the same example as in the previous section, but this time declaratively source controlled! All of the required Nix commands are included as ``#!`` shebang headers in the scripts itself.


Going forward
-------------

- :ref:`pinning-nixpkgs`
We've only covered the bare essentials of Nix here. Once you're comfortable with these examples, take a look at:

- :ref:`pinning-nixpkgs` to see examples of more advanced Nix expressions

.. TODO: reproducible developer environments
- When using `nix-shell`, packages are downloaded into `/nix/store`, but never removed.
Once enough disk space accumulates, it's time to `Garbage Collect <https://nixos.org/nix/manual/#sec-garbage-collection>`_.
- `Garbage Collection <https://nixos.org/nix/manual/#sec-garbage-collection>`_- as when using `nix-shell`, packages are downloaded into `/nix/store`, but never removed.

- See ``man nix-shell`` for more options
- See ``man nix-shell`` for all of the options.

0 comments on commit 775842d

Please sign in to comment.