command-error 0.8.0

Detailed error messages and status checking for `std::process::Command`
Documentation
{
  lib,
  callPackage,
}:
# Turn a directory tree containing package files suitable for `callPackages`
# into a matching nested attribute set of derivations
#
# For example, if the following files existed relative to the starting
# directory:
#
# ```nix
# # ./writeFoo.nix
# { writeText }:
#
# { file }:
#
# writeText file "foo"
# ```
#
# ```nix
# # ./bar/baz.nix
# { writeFoo }:
#
# writeFoo { file = "example.txt"; }
# ```
#
# Then `pkgs.bar.baz` will be the same thing as
# `pkgs.writeText "example.text" "foo"`.
#
# Tweaked from @Gabriella439's code.
directory: let
  supported = basename: type:
    lib.hasSuffix ".nix" basename || type == "directory";

  loop = dir: let
    toKeyVal = basename: type: let
      path = dir + "/${basename}";
    in {
      name = builtins.replaceStrings [".nix"] [""] basename;

      value =
        if type == "regular"
        then callPackage path {}
        else if type == "directory"
        then let
          default = path + "/default.nix";
        in
          if builtins.pathExists default
          then callPackage default {}
          else loop path
        else
          abort
          ''
            packagesFromDirectory: Unsupported file type

            File type: ${type}

            Path: ${path}
          '';
    };
  in
    builtins.listToAttrs
    (lib.mapAttrsToList toKeyVal (lib.filterAttrs supported (builtins.readDir dir)));
in
  loop (./. + "/${directory}")