# Extend the Nix interpreter to enable builtins.extraBuiltins,
# which provides an unsafe exec.
# Useful to get secrets from a local password-store.
{ config, lib, pkgs, ... }:
let cfg = config.nix-plugins;
    inherit (lib) types;

    /*
    # Wrapper around nix to load extra-builtins.nix with nix-plugins.
    nix-with-extra-builtins = pkgs.writeShellScriptBin "nix-with-extra-builtins" ''
      ${pkgs.nix}/bin/nix \
       --option plugin-files ${pkgs.nix-plugins}/lib/nix/plugins/libnix-extra-builtins.so \
       --option extra-builtins-file ${cfg.extra-builtins} \
       "$@"
    '';
    */

    # Wrapper around pass to call it with exec in extra-builtins.nix.
    # Unfortunately it can only load secrets which can be represented as a Nix string,
    # hence without null-byte and such special characters.
    # FIXME: make a nix-pass-chomp
    nix-pass = pkgs.writeShellScript "nix-pass" ''
      set -e
      f=$(mktemp)
      trap "shred -u $f" EXIT
      ${pkgs.pass}/bin/pass show "$1" >"$f"
      nix-instantiate --eval -E "builtins.readFile $f"
    '';
    # Like nix-pass but remove the trailing spaces and newlines at the end of the content.
    nix-pass-chomp = pkgs.writeShellScript "nix-pass-chomp" ''
      set -e
      f=$(mktemp)
      trap "shred -u $f" EXIT
      pass="$(${pkgs.pass}/bin/pass show "$1")"
      printf %s "$pass" >"$f"
      nix-instantiate --eval -E "builtins.readFile $f"
    '';

    # Wrapper around pass to call it with exec in extra-builtins.nix and put the output in a file.
    # Needed for boot.initrd.network.ssh.host*Key.
    nix-pass-to-file = pkgs.writeShellScript "nix-pass-to-file" ''
      set -e
      set -o pipefail
      ${pkgs.pass}/bin/pass show "$1" |
      install -D -m 400 /dev/stdin "$2"
      printf '%s\n' "$2"
    '';

    # Wrapper around pass to call it with exec in extra-builtins.nix and put the output in a file.
    # Needed for boot.initrd.network.ssh.host*Key.
    nix-pass-to-store = pkgs.writeShellScript "nix-pass-to-store" ''
      set -e
      ${pkgs.pass}/bin/pass show "$1" >"$f"
      nix-store --add "$f"
    '';

    # Wrapper around git to call it with exec in extra-builtins.nix.
    nix-git = pkgs.writeShellScript "nix-git" ''
      cd "$1"; shift
      ${pkgs.git}/bin/git "$@"
    '';
in
{
  options.nix-plugins = {
    enable = lib.mkEnableOption "nix-plugins";
    extra-builtins = lib.mkOption {
      type = types.lines;
      default = ''
        pass         = path: exec [ "${nix-pass}" path ];
        pass-chomp   = path: exec [ "${nix-pass-chomp}" path ];
        pass-to-file = path: name: exec [ "${nix-pass-to-file}" path name ];
        git          = dir: args: exec ([ "${nix-git}" dir ] ++ args);
        git-time     = dir: path: exec [ "${nix-git}" dir "log" "-1" "--format=%ct" "--" path ];
      '';
      description = ''
        Content put in extra-builtins.nix for nix-plugins.
      '';
      apply = lines: pkgs.writeText "extra-builtins.nix" (''
        { exec, ... }:
        {
        '' + lines + ''
        }
      '');
    };
  };
  config = lib.mkIf cfg.enable {
    nix.enable = true;
    nix.nixConf = ''
      plugin-files        = ${pkgs.nix-plugins}/lib/nix/plugins/libnix-extra-builtins.so
      extra-builtins-file = ${cfg.extra-builtins}
    '';
  };
}