cachix / devenv

Fast, Declarative, Reproducible, and Composable Developer Environments
https://devenv.sh
Apache License 2.0
3.47k stars 252 forks source link

Consider running a flake in a subdirectory #1164

Open nick-kadutskyi opened 1 week ago

nick-kadutskyi commented 1 week ago

In process of setting up devenv via flake.nix I noticed that my nix store gained 50 gb in size. Turned out Nix is copying the whole source tree into the store for evaluation (I've just started using Nix and didn't know that) and my project is 2 GB so getting it copied on every change in flake.nix makes it very slow and bloats the nix store. In my case I do not need my repo in the nix store because I just need some packages (php) and services (mysql, php-fpm, httpd) and do not want to build the project.

To avoid this I moved flake.nix into a subdirectory (nix) and refer to that flake via path: in .envrc config (use flake path:nix --impure instead of use flake --impure) or run nix develop path:nix --impure. Referring to a flake via path: ignores whatever is tracked in git repo and instead copies all the file tree where flake.nix is located. So having flake.nix in an empty subdirectory will result into copying only nix/flake.nix and nix/flake.lock into the store.

This solves the problem of running nix develop or using direnv but it doesn't solve devenv up because I can't run it from root of the project and in that script flake.nix is referred via git so that if I cd into my subdirectory (nix) and run devenv up it will copy the whole project into the nix store.

To solve this I just created a similar script in my repo and added it into the flake as a module to have it accessible from the terminal as devenv-custom. The change I made to the script:

...
 command=$1
  if [[ ! -z $command ]]; then
    shift
  fi

+ flakePath=$1
+ if [[ $flakePath == "path:"* ]]; then
+   shift
+ else
+   flakePath="."
+ fi

  case $command in
    up)
-     procfilescript=$(nix build '.#${shellPrefix (config._module.args.name or "default")}devenv-up' --no-link --print-out-paths --impure)
+     procfilescript=$(nix build $flakePath#'${shellPrefix (config._module.args.name or "default")}devenv-up' --no-link --print-out-paths --impure)
      if [ "$(cat $procfilescript|tail -n +2)" = "" ]; then
        echo "No 'processes' option defined: https://devenv.sh/processes/"
        exit 1
      else
...

This allows me to

I am ok running my own script but I propose to consider this change at least until this PR is merged.

domenkozar commented 1 week ago

If you use devenv binary you won't have this issue.

nick-kadutskyi commented 1 week ago

@domenkozar when I run nix develop path:nix --impure I am entering shell where I get a different version of devenv (bash script) which has only up and version commands. Even if I use the devenv binary (installed in my nix profile) I think I will get into the same problems:

Both devenv script and binary will work in my case if I would not have a git repo. In a non-git project nix build .#procfileScript will be treated as nix build path:.#procfileScript wile in git repo it's treated as nix build git+file:.#procfileScript (See Path-like syntax) so if I want to still refer to it as path: while in git repo I need to do that explicitly.

Also devenv binary requires devenv.nix instead of flake.nix.