Skip to content

Commit e3698e7

Browse files
committed
Support hpack include directives
Add a `generateCabalFile` argument that allows us to pre-genereate the cabal file, thus allowing us to create an environment where hpack can successfully find included files. We also just read the package.yaml file directly to get the name rather than by calling readYAML, since include directives lead to unparseable YAML. Resolves cdepillabout#47
1 parent 22676df commit e3698e7

File tree

1 file changed

+37
-12
lines changed

1 file changed

+37
-12
lines changed

nix/build-support/stacklock2nix/default.nix

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,15 @@
133133
# defaultLocalPkgFilter: pkgName: path: type: true
134134
# ```
135135
localPkgFilter ?
136-
defaultLocalPkgFilter: pkgName: path: type: defaultLocalPkgFilter path type
136+
defaultLocalPkgFilter: pkgName: path: type: defaultLocalPkgFilter path type,
137+
# A function to generate a cabal file for a local package.
138+
# Normally this is handled by `cabal2nix`, but in special cases we might want
139+
# to do this ourselves, eg, when using hpack `!include`s.
140+
#
141+
#
142+
# generateCabalFile :: String -> String -> Path -> Path
143+
generateCabalFile ?
144+
pkgName: subdir: filteredSrc: filteredSrc
137145
}:
138146

139147
# The stack.yaml path can be computed from the stack.yaml.lock path, or
@@ -558,15 +566,19 @@ let
558566
# Example: `"my-cool-pkg"`
559567
pkgNameFromPackageYaml =
560568
let
561-
packageYaml = readYAML (justCabalFilePath + "/package.yaml");
562-
in
563-
if packageYaml ? name then
564-
packageYaml.name
565-
else
566-
throw
567-
("Could not find read a .name field from the package.yaml file in package ${localPkgPathStr}. " +
568-
"This is unexpected. All package.yaml files should have a top-level .name field. " +
569-
"package.yaml file: ${builtins.toJSON packageYaml}");
569+
packageYamlName = builtins.readFile
570+
(runCommand "read-package-name" {}
571+
''
572+
function fail {
573+
echo "Could not find read a .name field from the package.yaml file in package ${localPkgPathStr}."
574+
echo "This is unexpected. All package.yaml files should have a top-level .name field."
575+
echo "package.yaml file: "
576+
cat package.yaml
577+
exit 1
578+
}
579+
(sed -nr 's/name:\s*\"?(.*)\"?\s*/\1/p' ${justCabalFilePath + "/package.yaml"} | tr -d '\n' >$out) || fail''
580+
);
581+
in packageYamlName;
570582

571583
# Whether or not this package has at least one .cabal file.
572584
#
@@ -626,12 +638,25 @@ let
626638

627639
# Path to the Haskell package.
628640
#
629-
# pkgPath :: Path
630-
pkgPath = lib.cleanSourceWith {
641+
# filteredPkgPath :: Path
642+
filteredPkgPath = lib.cleanSourceWith {
631643
src = rawPkgPath;
632644
filter = path: type: localPkgFilter localPkgDefaultFilter pkgName path type;
633645
name = "stacklock2nix-pkg-sources-" + pkgName;
634646
};
647+
648+
# Path to the Haskell package,
649+
# but if it doesn't contain a .cabal file
650+
# then we call the `generateCabalFile` function to potentially pre-generate
651+
# the .cabal file. This is useful if the `package.yaml` file needs special
652+
# treatment, eg, because of includes.
653+
#
654+
# pkgPath :: Path
655+
pkgPath =
656+
if hasSingleCabalFile then
657+
filteredPkgPath
658+
else
659+
generateCabalFile pkgName localPkgPathStr filteredPkgPath;
635660
in
636661
{ inherit pkgPath pkgName; };
637662

0 commit comments

Comments
 (0)