Skip to content

Latest commit

 

History

History
262 lines (224 loc) · 8.82 KB

nix.org

File metadata and controls

262 lines (224 loc) · 8.82 KB

Nix environment setup library for Elvish

Functions to set up the Nix environment variables for Elvish.

Table of Contents

Implementation

Libraries

We use the re and util modules.

use re
use str
use github.com/zzamboni/elvish-modules/util

Environment setup

I have two environment setup functions, one for a multi-user environment (default on macOS) and the other for a single-user setup.

Multi-user setup

This is the default setup on macOS. This script was ported to Elvish from /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh.

fn multi-user-setup {
  # Set up secure multi-user builds: non-root users build through the
  # Nix daemon.
  if (or (not-eq $E:USER root) (not ?(test -w /nix/var/nix/db))) {
    set E:NIX_REMOTE = daemon
  }

  set E:NIX_USER_PROFILE_DIR = "/nix/var/nix/profiles/per-user/"$E:USER
  var nix-profiles = [
    "/nix/var/nix/profiles/default"
    $E:HOME"/.nix-profile"
  ]
  set E:NIX_PROFILES = (str:join " " $nix-profiles)

  # Set up the per-user profile.
  mkdir -m 0755 -p $E:NIX_USER_PROFILE_DIR
  if (not ?(test -O $E:NIX_USER_PROFILE_DIR)) {
    echo (styled "WARNING: bad ownership on "$E:NIX_USER_PROFILE_DIR yellow) >&2
  }

  if ?(test -w $E:HOME) {
    if (not ?(test -L $E:HOME/.nix-profile)) {
      if (not-eq $E:USER root) {
        ln -s $E:NIX_USER_PROFILE_DIR/profile $E:HOME/.nix-profile
      } else {
        # Root installs in the system-wide profile by default.
        ln -s /nix/var/nix/profiles/default $E:HOME/.nix-profile
      }
    }

    # Subscribe the root user to the NixOS channel by default.
    if (and (eq $E:USER root) (not ?(test -e $E:HOME/.nix-channels))) {
      echo "https://nixos.org/channels/nixpkgs-unstable nixpkgs" > $E:HOME/.nix-channels
    }

    # Create the per-user garbage collector roots directory.
    var nix-user-gcroots-dir = "/nix/var/nix/gcroots/per-user/"$E:USER
    mkdir -m 0755 -p $nix-user-gcroots-dir
    if (not ?(test -O $nix-user-gcroots-dir)) {
      echo (styled "WARNING: bad ownership on "$nix-user-gcroots-dir yellow) >&2
    }

    # Set up a default Nix expression from which to install stuff.
    if (or (not ?(test -e $E:HOME/.nix-defexpr)) ?(test -L $E:HOME/.nix-defexpr)) {
      rm -f $E:HOME/.nix-defexpr
      mkdir -p $E:HOME/.nix-defexpr
      if (not-eq $E:USER root) {
        ln -s /nix/var/nix/profiles/per-user/root/channels $E:HOME/.nix-defexpr/channels_root
      }
    }
  }

  set E:NIX_SSL_CERT_FILE = "/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"
  set E:NIX_PATH = "/nix/var/nix/profiles/per-user/root/channels"
  # E:MANPATH = ~/.nix-profile/share/man
  set paths = [
    ~/.nix-profile/bin
    ~/.nix-profile/sbin
    ~/.nix-profile/lib/kde4/libexec
    /nix/var/nix/profiles/default/bin
    /nix/var/nix/profiles/default/sbin
    /nix/var/nix/profiles/default/lib/kde4/libexec
    $@paths
  ]

  #echo (styled "Nix environment ready" green)
}

Single-user setup

This is not fully tested as I don’t use this setup - use with care!

fn single-user-setup {
  # Set up single-user Nix (no daemon)
  if (not-eq $E:HOME "") {
    var nix-link = ~/.nix-profile
    if (not ?(test -L $nix-link)) {
      echo (styled "creating "$nix-link green) >&2
      var -nix-def-link = /nix/var/nix/profiles/default
      ln -s $-nix-def-link $nix-link
    }
    set paths = [
      $nix-link"/bin"
      $nix-link"/sbin"
      $@paths
    ]
    # Subscribe the user to the Nixpkgs channel by default.
    if (not ?(test -e ~/.nix-channels)) {
      echo "https://nixos.org/channels/nixpkgs-unstable nixpkgs" > ~/.nix-channels
    }
    # Append ~/.nix-defexpr/channels/nixpkgs to $NIX_PATH so that
    # <nixpkgs> paths work when the user has fetched the Nixpkgs
    # channel.
    if (not-eq $E:NIX_PATH "") {
      set E:NIX_PATH = $E:NIX_PATH":nixpkgs="$E:HOME"/.nix-defexpr/channels/nixpkgs"
    } else {
      set E:NIX_PATH = "nixpkgs="$E:HOME"/.nix-defexpr/channels/nixpkgs"
    }

    # Set $NIX_SSL_CERT_FILE so that Nixpkgs applications like curl work.
    if ?(test -e  /etc/ssl/certs/ca-certificates.crt ) { # NixOS, Ubuntu, Debian, Gentoo, Arch
      set E:NIX_SSL_CERT_FILE = /etc/ssl/certs/ca-certificates.crt
    } elif ?(test -e  /etc/ssl/ca-bundle.pem ) { # openSUSE Tumbleweed
      set E:NIX_SSL_CERT_FILE = /etc/ssl/ca-bundle.pem
    } elif ?(test -e  /etc/ssl/certs/ca-bundle.crt ) { # Old NixOS
      set E:NIX_SSL_CERT_FILE = /etc/ssl/certs/ca-bundle.crt
    } elif ?(test -e  /etc/pki/tls/certs/ca-bundle.crt ) { # Fedora, CentOS
      set E:NIX_SSL_CERT_FILE = /etc/pki/tls/certs/ca-bundle.crt
    } elif ?(test -e  $nix-link"/etc/ssl/certs/ca-bundle.crt" ) { # fall back to cacert in Nix profile
      set E:NIX_SSL_CERT_FILE = $nix-link"/etc/ssl/certs/ca-bundle.crt"
    } elif ?(test -e  $nix-link"/etc/ca-bundle.crt" ) { # old cacert in Nix profile
      set E:NIX_SSL_CERT_FILE = $nix-link"/etc/ca-bundle.crt"
    }
  }
}

Utility functions

Searching for packages

nix:search is a wrapper around nix-env -qa, which removes the automatic pager wrapper, and pipes through json_pp if the first argument is --json.

fn search {|@pkgs|
  var pipecmd = cat
  var opts = []
  if (eq $pkgs[0] "--json") {
    set pipecmd = json_pp
  }
  nix-env -qa $@opts $@pkgs | $pipecmd
}

Installing packages

nix:install is a wrapper around nix-env -i.

fn install {|@pkgs|
  nix-env -i $@pkgs
}

Moving from Homebrew to Nix

nix:brew-to-nix is a simple interactive function to go through installed Homebrew packages and allow you to replace them with their Nix equivalents. Only loops through the “leaves” - i.e. Homebrew packages that do not have any dependents, so it will not loop through everything. You may need to run it a few times to fully clean up.

fn brew-to-nix {
  brew leaves | each {|pkg|
    echo (styled "Package "$pkg green)
    brew info $pkg
    var loop = $true
    while $loop {
      set loop = $false
      print (styled $pkg": [R]emove/[Q]uery nix/[K]eep/Remove and [I]nstall with nix? " yellow)
      var resp = (util:readline </dev/tty)
      if (eq $resp "r") {
        brew uninstall --force $pkg
      } elif (eq $resp "q") {
        set _ = ?(search --description '.*'$pkg'.*')
        set loop = $true
      } elif (eq $resp "i") {
        install $pkg
        brew uninstall --force $pkg
      }
    }
  }
}

Displaying package information

nix:info is a wrapper to query nix packages, but showing more information than what nix-env usually provides, by extracting it from the package metadata.

fn info {|pkg|
  # Get data
  var install-path = nil
  var installed = ?(set install-path = [(re:split '\s+' (nix-env -q --out-path $pkg 2>/dev/null))][1])
  var flag = (if $installed { put "-q" } else { put "-qa" })
  var data = (nix-env $flag --json $pkg | from-json)
  var top-key = (keys $data | take 1)
  set pkg = $data[$top-key]
  var meta = $pkg[meta]

  # Produce the output
  print (styled $pkg[name] yellow)
  if (has-key $meta description) {
    echo ":" $meta[description]
  } else {
    echo ""
  }
  if (has-key $meta homepage) {
    echo (styled "Homepage: " blue) $meta[homepage]
  }
  if $installed {
    echo (styled "Installed:" green) $install-path
  } else {
    echo (styled "Not installed" red)
  }
  echo From: (re:replace ':\d+' "" $meta[position])
  if (has-key $meta longDescription) {
    echo ""
    echo $meta[longDescription] | fmt
  }
}