diff --git a/flake-module.nix b/flake-module.nix index 85383a3a..93d76710 100644 --- a/flake-module.nix +++ b/flake-module.nix @@ -177,19 +177,7 @@ in # # In future, we could just read `cabal.project`. See #76. let - # Like pkgs.haskell.lib.haskellPathsInDir' but with a few differences - # - Allows top-level .cabal files - haskellPathsInDir' = path: - lib.filterAttrs (k: v: v != null) (lib.mapAttrs' - (k: v: - if v == "regular" && lib.strings.hasSuffix ".cabal" k - then lib.nameValuePair (lib.strings.removeSuffix ".cabal" k) path - else - if v == "directory" && builtins.pathExists (path + "/${k}/${k}.cabal") - then lib.nameValuePair k (path + "/${k}") - else lib.nameValuePair k null - ) - (builtins.readDir path)); + errorNoDefault = msg: builtins.throw '' haskell-flake: A default value for `packages` cannot be auto-detected: @@ -199,7 +187,8 @@ in ''; cabalPaths = let - cabalPaths = haskellPathsInDir' self; + haskellPathsInDir = import ./nix/haskellPathsInDir.nix { inherit lib; }; + cabalPaths = haskellPathsInDir self; in if cabalPaths == { } then diff --git a/nix/haskellPathsInDir.nix b/nix/haskellPathsInDir.nix new file mode 100644 index 00000000..e32c6313 --- /dev/null +++ b/nix/haskellPathsInDir.nix @@ -0,0 +1,46 @@ +# Like pkgs.haskell.lib.haskellPathsInDir' but with a few differences +# - Allows top-level .cabal files +# - Recurses into subdirectories +# - Allows package.yaml files +{ lib, ... }: + +path': + +let + parseCabalName = file: + lib.strings.removeSuffix ".cabal" file; + parseHpackName = file: + # TODO: this is a hack, we should use a proper parser + let + line = builtins.head (lib.strings.split "[[:space:]]*\n[[:space:]]*" (builtins.readFile file)); + extract = xs: builtins.head (builtins.tail (builtins.tail xs)); + in + extract (lib.strings.split "[[:space:]]*name[[:space:]]*:[[:space:]]*" line); + f = path: lib.mapAttrsToList + (k: v: + let + pass = [ ]; + one = x: [ x ]; + in + if v == "regular" + then + if lib.strings.hasSuffix ".cabal" k + then one (lib.nameValuePair (parseCabalName k) path) + else if k == "package.yaml" + then one (lib.nameValuePair (parseHpackName k) path) + else pass + else + if v == "directory" + then + if builtins.pathExists (path + "/${k}/${k}.cabal") + then + one (lib.nameValuePair k (path + "/${k}")) + else + if builtins.pathExists (path + "/${k}/package.yaml") + then one (lib.nameValuePair (parseHpackName (path + "/${k}/package.yaml")) (path + "/${k}")) + else f (path + "/${k}") + else pass + ) + (builtins.readDir path); +in +lib.listToAttrs (lib.flatten (f path'))