Skip to content

Latest commit

 

History

History
194 lines (128 loc) · 10.5 KB

README.md

File metadata and controls

194 lines (128 loc) · 10.5 KB

1. Introduction

clam.nix is for modularizing shell hooks TODO link in Nix expressions (usually stored in shell.nix files) that are to be used with the nix-shell command line tool. The body of the clam.nix function is a shell script template, and the input attributes enable plugging in custom shell commands at specific stages TODO link of its execution.

For example, taking the reference usage demonstrated in elixir-phoenix-postgres/shell.nix (see its README), a sub-shell will be set up for a Phoenix (an Elixir web framework) project, with the required language packages and a PostgreSQL instance running in the background (actions phase TODO:link), all of which will be cleaned up upon exiting the shell (i.e., packages deleted, database stopped, etc.). Another example is setting up git secret.

The idea itself was suggested by @SRGOM in issue #1, but instead of modularizing shell scripts themselves (e.g., like this), decided to solve it with the Nix language using imports.

2. Phases of the clam.nix shell script template and the input attributes controlling them

where The clam.nix function expects an attribute set in the form of

{ nixShellDataDir ? ".nix-shell"
, cavern          ? ""
, rump            ? ""
}:

where

  • nixShellDataDir (default value: .nix-shell)

is a string used to name of a temporary directory that will be created in the directory where the Nix expression is invoked with nix-shell; see setup phase (TODO link)

  • cavern (default value: "")

is a string that should evaluate to valid shell commands; see actions phase (TODO link) section for the details and examples

  • rump (default value: "")

is a string that should also evaluate to valid shell commands; see clean-up phase (TODO link)

The template can be broken up into the following phases (these are also marked in the source):

  1. setup (nixShellDataDir)

  2. actions (cavern)

  3. clean-up (rump)

The items in parentheses refer to attribute names in the clam.nix function's input attribute set that play a role in the respective phase.

An empty clam shell slightly opened, photographed on a sandy beach with the ocean and the clear sky as a background.

A mnemonic (By febb, CC BY-SA 3.0, Link)
├── _helpers
│   └── shell-hook
│       │
│       ├── clam.nix         - the shell script template
│       │
│       ├── inserts          - generic shell script snippets
│       │   │                  that add extra functionality;
│       │   │                  see "2.3 Inserts"
│       │   │
│       │   ├── mix.nix
│       │   └── postgres.nix
│       │
│       └── README.md        - this readme
│
├── elixir-phoenix-postgres  - other project-  or app-specific
├── ...                        shell.nix-es  below  this point
:

2.1 Phases

2.1.1 Setup phase

NOTE: This phase doesn't accept any custom shell commands at the moment, only the name of the temporary directory specified by nixShellDataDir.

  1. Creates a temporary directory (set by nixShellDataDir, see above)

    Used to store application-specific data, instead of having those scattered around in the system (e.g., in the user's home directory, /run, etc.); it will be deleted when exiting the shell (see 1.3 Clean-up TODO link section).

    Examples of application specific data:

  2. Makes the path of the temporary directory available in the NIX_SHELL_DIR environment variable in the new sub-shell created by nix-shell

    NIX_SHELL_DIR can then be used in custom shell commands (see example usage in ./inserts/postgres.nix for example).

  3. Set up empty CLEANUP_CALLBACKS array to register callback functions to be run in the clean-up phase TODO link. (See 2.3 Clean-up callbacks section TODO link)

2.1.2 Actions phase

This phase has no default actions, and the cavern input attribute is an empty string by default - so without any user-specified actions this phase will be skipped, and the clean-up phase TODO link will commence.

elixir-phoenix-postgres/shell.nix provides the reference usage for clam.nix.

2.1.3 Clean-up phase

Default actions:

cd $PWD               # (1)
rm -rf $NIX_SHELL_DIR # (2)

That is,

  1. return to the project directory (see comment), and
  2. delete the $NIX_SHELL_DIR directory (see 2.1.1 Setup phase section), but any other clean-up measures need to be provided by the user.

TODO: Is there a need to retain it? My workflow is usually to (1) enter nix-shell, (2) do stuff, and (3) suspend the system at the end of the day/session, so I start in the same environment the next time. This also means if I make changes to the environment, and these won't be reflected when I'll enter it the next time. I would argue that deleting it is good because it forces one to update the shell.nix on change (and some action will definitely warrant this anyway, such as changing environment variables).

For example, if a database instance has been started previously, it will keep running when exiting Nix shell, unless it is explicitly stopped in the clean-up phase (via shell commands specified in rump; see 2.2.3 rump).

Not unsetting environment variables is alright, because nix-shell starts a sub-shell so these will go out of scope when leaving; nix shell may be another matter though.

2.2 Inserts

(i.e., the contents of the ./inserts/ script snippets directory)

Inserts are just string Nix expressions that evaluate to shell commands pertaining to a specific topic or tool; they are basically modules that can be plugged into a shell.nix on demand. The main rationale behind clam.nix was to promote re-use of parts of shell hooks.

For example, elixir-phoenix-postgres/shell.nix sets up an development environment for an Elixir web framework, and it spins up a PostgreSQL server via the ./inserts/postgres.nix insert. This script could have been used for a Python or Go web project just as easily.

TODO link to Nix strings, explain .nix files, import, or just add string directly, sho extending postgres.nix in elixir shell.nix, go into clean up callbacks and elaborate the pros of including them in inserts (self-contained scripts that clean up after themselves). Add direnv to the mix (i.e., include that fora specific project, but these shell.nix templates good for starting out with a new project)

2.3 Clean-up callbacks

∞. Pre-requisite concepts (work in progress)

Derivation

TODO

$stdenv/setup

TODO

nix-shell

TODO

I believe that nix-shell's Nix manual entry is grossly over-simplified, and its behaviour does raise questions.

nix-shell shell hook (or shellHook)

Shell hooks (in this context) are shell scripts executed once before entering the sub-shell set up by nix-shell. From nix-shell's Nix manual entry:

If the derivation defines the variable shellHook, it will be evaluated after $stdenv/setup has been sourced. Since this hook is not executed by regular Nix builds, it allows you to perform initialisation specific to nix-shell. For example, the derivation attribute

shellHook =
  ''
    echo "Hello shell"
  '';

will cause nix-shell to print "Hello shell".

[†] There is a difference between Unix and TCP/IP sockets and not all Unix sockets are files (see wiki and this question).