nix-community / lorri

Your project’s nix-env [maintainer=@Profpatsch,@nyarly]
Apache License 2.0
677 stars 24 forks source link

Lorri does not set `IN_NIX_SHELL` when realizing derivations #65

Open deviant opened 3 years ago

deviant commented 3 years ago

Describe the bug

In a regular nix-shell, builds are evaluated with IN_NIX_SHELL set. This allows you to, for instance, use your default.nix directly, while adding some development dependencies when in a shell. Lorri doesn't do this, meaning expressions that work as expected in nix-shell may provide a different environment in Lorri.

To Reproduce

Steps to reproduce the behavior:

v@january ~> cd (mktemp -d)
v@january /t/tmp.7nY21hGq4L> cat shell.nix
with import <nixpkgs> {};
let
  foo = writeShellScriptBin "foo" ''
    echo bar
  '';
in mkShell {
  packages = lib.optional lib.inNixShell foo;
}
v@january /t/tmp.7nY21hGq4L> nix-shell
these derivations will be built:
  /nix/store/ghn3hhrabvy76jwr76pzxm3ynhw5qnqw-foo.drv
building '/nix/store/ghn3hhrabvy76jwr76pzxm3ynhw5qnqw-foo.drv'...
v@january /t/tmp.7nY21hGq4L> foo
bar
v@january /t/tmp.7nY21hGq4L> ^D
v@january /t/tmp.7nY21hGq4L> lorri init
Aug 14 04:23:01.863 INFO file already exists, skipping, message: Make sure shell.nix is of a form that works with nix-shell., path: ./shell.nix
Aug 14 04:23:01.863 INFO wrote file, path: ./.envrc
Aug 14 04:23:01.863 INFO done
direnv: error /tmp/tmp.7nY21hGq4L/.envrc is blocked. Run `direnv allow` to approve its content
v@january /t/tmp.7nY21hGq4L> direnv allow
direnv: loading /tmp/tmp.7nY21hGq4L/.envrc
Aug 14 04:23:14.186 INFO lorri has not completed an evaluation for this project yet, nix_file: /tmp/tmp.7nY21hGq4L/shell.nix
direnv: export +IN_NIX_SHELL
v@january /t/tmp.7nY21hGq4L> 
direnv: loading /tmp/tmp.7nY21hGq4L/.envrc
direnv: export +AR +AS +CC +CONFIG_SHELL +CXX +HOST_PATH +IN_LORRI_SHELL +IN_NIX_SHELL +LD +NIX_BINTOOLS +NIX_BINTOOLS_WRAPPER_TARGET_HOST_x86_64_unknown_linux_gnu +NIX_BUILD_CORES +NIX_BUILD_TOP +NIX_CC +NIX_CC_WRAPPER_TARGET_HOST_x86_64_unknown_linux_gnu +NIX_CFLAGS_COMPILE +NIX_ENFORCE_NO_NATIVE +NIX_HARDENING_ENABLE +NIX_INDENT_MAKE +NIX_LDFLAGS +NIX_LOG_FD +NIX_STORE +NM +OBJCOPY +OBJDUMP +RANLIB +READELF +SIZE +SOURCE_DATE_EPOCH +STRINGS +STRIP +allowSubstitutes +buildInputs +builder +configureFlags +depsBuildBuild +depsBuildBuildPropagated +depsBuildTarget +depsBuildTargetPropagated +depsHostHost +depsHostHostPropagated +depsTargetTarget +depsTargetTargetPropagated +doCheck +doInstallCheck +extraClosure +name +nativeBuildInputs +nobuildPhase +origArgs +origBuilder +origExtraClosure +origOutputs +origPATH +origSystem +out +outputs +patches +phases +preHook +preferLocalBuild +propagatedBuildInputs +propagatedNativeBuildInputs +shell +shellHook +stdenv +strictDeps +system ~PATH ~XDG_DATA_DIRS
v@january /t/tmp.7nY21hGq4L> 
v@january /t/tmp.7nY21hGq4L> foo
foo: command not found
v@january /t/tmp.7nY21hGq4L [127]> 

Expected behavior

Metadata

v@january /t/tmp.7nY21hGq4L> lorri info
error: The following required arguments were not provided:
    --shell-file <nix_file>

USAGE:
    lorri info --shell-file <nix_file>

For more information try --help
v@january /t/tmp.7nY21hGq4L [1]> 
v@january /t/tmp.7nY21hGq4L> uname -a
Linux january 5.10.37 #1-NixOS SMP Fri May 14 07:50:46 UTC 2021 x86_64 GNU/Linux

Additional context

None, really. This feels like an edge case you're unlikely to run into unless you're weird.

sternenseemann commented 3 years ago

Some example code (even generated code?) for haskell development environments also used this to switch between building drv and drv.env. Here the situation is even worse: The environment won't even work properly if drv.env isn't used.

deviant commented 3 years ago

This is a little off-topic, but does direnv's use nix handle this correctly? If not, we probably ought to report it there as well.

Profpatsch commented 3 years ago

lorri shell does set it iirc.

There was a reason why we don’t set it which should be documented somewhere in the code or git blame.

deviant commented 3 years ago

lorri shell does set it iirc.

Just tried that, it doesn't seem to be any different?

IN_NIX_SHELL is set within the shell itself, so if one were to do a nix-build from within the shell (produced either via lorri direnv, or lorri shell, etc), it would build foo as expected. So it is setting the variable, just not in enough places.

Profpatsch commented 3 years ago

Looks like we are setting it in two places:

https://github.com/nix-community/lorri/blob/dfbf9b3d22474380ee5e096931dbf25b1c162d10/src/ops/direnv/envrc.bash#L163

https://github.com/nix-community/lorri/blob/b84602c7132293e23eb8957ba493f188ce89ea1c/src/logged-evaluation.nix#L144

iogrt commented 1 year ago

This seems to have the side-effect of, in Haskell projects, tricking nix-build into building drv.env, when what you'd really want is to build drv.

Not sure what's the cleanest way to approach this, ideally instead of exporting IN_NIX_SHELL it could be set and unset on lorri commands only. If not possible, create a lorri build command?

As a band-aid, I've been using IN_NIX_SHELL= nix-build && lorri watch because lorri loses it's connection after building.

This is my default.nix for reference:

{ pkgs ? import <nixpkgs> {}}:
pkgs.haskellPackages.developPackage {
  root = ./.;
}