nix-community / nix-direnv

A fast, persistent use_nix/use_flake implementation for direnv [maintainer=@Mic92 / @bbenne10]

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Requires GNU grep

tviti opened this issue · comments

commented

Issue

This isn't really an issue with nix-direnv, but more of a caveate I encountered when trying to use nix-direnv on macOS. I first encountered this using direnv-mode in emacs w/ nix-direnv on macOS, but it looks like it's also a problem just using direnv from bash on macOS.

From a directory that DOESN'T have a cached environment (i.e. .direnv either doesn't exist or is empty), the following error is shown when making a first attempt at loading the env:

usage: grep [-abcDEFGHhIiJLlmnOoqRSsUVvwxZ] [-A num] [-B num] [-C[num]]
	[-e pattern] [-f file] [--binary-files=value] [--color=when]
	[--context[=num]] [--directories=action] [--label] [--line-buffered]
	[--null] [pattern] [file ...]

which results in the creation of an empty cache.

Setup

Directory structure:

nix-direnv-test taylor$ ls -la
total 16
drwxr-xr-x   5 taylor  staff   160 Mar 10 11:26 .
drwxr-xr-x  55 taylor  staff  1760 Mar 10 11:24 ..
drwxr-xr-x   3 taylor  staff    96 Mar 10 11:26 .direnv
-rw-r--r--   1 taylor  staff     8 Mar 10 11:24 .envrc
-rw-r--r--   1 taylor  staff    87 Mar 10 11:25 shell.nix

.direnv:

use nix

shell.nix:

let pkgs = import <nixpkgs> { };
in pkgs.mkShell {
    buildInputs = [ pkgs.hello ];
}

Steps to reproduce

nix-direnv-test taylor$ direnv allow
direnv: loading ~/Source/nix-direnv-test/.envrc
direnv: using nix
usage: grep [-abcDEFGHhIiJLlmnOoqRSsUVvwxZ] [-A num] [-B num] [-C[num]]
	[-e pattern] [-f file] [--binary-files=value] [--color=when]
	[--context[=num]] [--directories=action] [--label] [--line-buffered]
	[--null] [pattern] [file ...]

Fix

The issue seems to be that nix-direnv is trying to invoke the macOS builtin BSD-grep at /usr/bin/grep, which for one reason or another doesn't like (in direnvrc):

    tmp=$(nix-shell --show-trace --pure "$@" --run "$dump_cmd" \
              | grep -oP '(?<=_____direnv_____).*')

I haven't actually spent any time trying to figure out WHY that line is problematic with the builtin grep, but I managed to sort this out by installing nix-direnv with the following derivation, which explicitely uses nixpkgs.gnugrep

{ bash, fetchFromGitHub, gnugrep, stdenv }:

stdenv.mkDerivation {
  name = "nix-direnv";

  src = fetchFromGitHub {
    owner = "nix-community";
    repo = "nix-direnv";
    rev = "81d3f5083ae68aec5d9f6fc9eebac57c82a9d280";
    sha256 = "067493hbsij59bvaqi38iybacqbzwx876dvdm651b5mn3zs3h42c";
  };

  phases = [ "unpackPhase" "patchPhase" "installPhase" ];

  prePatch = ''
    substituteInPlace direnvrc --replace "/usr/bin/env bash" "${bash}/bin/bash"
    substituteInPlace direnvrc --replace "grep" "${gnugrep}/bin/grep"
  '';
  
  installPhase = ''
    mkdir -p $out/share/nix-direnv
    cp -rv ./* $out/share/nix-direnv
  '';
}

Interesting. I might be able to replace this invocation with an awk call that should be portable. Do you now if nix show-derivation $out | grep -E -o -m1 '/nix/store/.*.drv' is problematic with bsdgrep?

@zimbatm does direnv on macOS uses the builtin bash btw? Because that might also cause problems.

Replacing /usr/bin/env bash should not have any effect because direnv executes the bash version itself.

yes... direnv uses whatever bash is in the environment

In that case I should suggest people to install direnv via nixpkgs or get a newer version via $packagemanager. I have not tested bash compatibility though.

The one that comes from nixpkgs is bound to the nixpkgs bash at compile time.

Anyone using Homebrew should also brew install bash

It would be great if direnv would have something like a .direnv.d or even environment variables to load third party plugins. I think it is time to package nix-direnv in nixpkgs itself.

Can we convince the homebrew maintainers to also hard code bash? https://github.com/Homebrew/homebrew-core/blob/master/Formula/direnv.rb#L18

@Mic92 direnv looks in ~/.config/direnv/lib/*.sh for additional libs. (since v2.21)

Ok. This would not play well with vanilla nix or most other system package manager in that regard, but a home-manager module could work.

Nix-direnv can now be installed via nix. This version will hard code nix as well as gnugrep.