Skip to content

Commit

Permalink
Support hpack include directives
Browse files Browse the repository at this point in the history
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
  • Loading branch information
TeofilC committed Apr 18, 2024
1 parent 22676df commit e3698e7
Showing 1 changed file with 37 additions and 12 deletions.
49 changes: 37 additions & 12 deletions nix/build-support/stacklock2nix/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,15 @@
# defaultLocalPkgFilter: pkgName: path: type: true
# ```
localPkgFilter ?
defaultLocalPkgFilter: pkgName: path: type: defaultLocalPkgFilter path type
defaultLocalPkgFilter: pkgName: path: type: defaultLocalPkgFilter path type,
# A function to generate a cabal file for a local package.
# Normally this is handled by `cabal2nix`, but in special cases we might want
# to do this ourselves, eg, when using hpack `!include`s.
#
#
# generateCabalFile :: String -> String -> Path -> Path
generateCabalFile ?
pkgName: subdir: filteredSrc: filteredSrc
}:

# The stack.yaml path can be computed from the stack.yaml.lock path, or
Expand Down Expand Up @@ -558,15 +566,19 @@ let
# Example: `"my-cool-pkg"`
pkgNameFromPackageYaml =
let
packageYaml = readYAML (justCabalFilePath + "/package.yaml");
in
if packageYaml ? name then
packageYaml.name
else
throw
("Could not find read a .name field from the package.yaml file in package ${localPkgPathStr}. " +
"This is unexpected. All package.yaml files should have a top-level .name field. " +
"package.yaml file: ${builtins.toJSON packageYaml}");
packageYamlName = builtins.readFile
(runCommand "read-package-name" {}
''
function fail {
echo "Could not find read a .name field from the package.yaml file in package ${localPkgPathStr}."
echo "This is unexpected. All package.yaml files should have a top-level .name field."
echo "package.yaml file: "
cat package.yaml
exit 1
}
(sed -nr 's/name:\s*\"?(.*)\"?\s*/\1/p' ${justCabalFilePath + "/package.yaml"} | tr -d '\n' >$out) || fail''
);
in packageYamlName;

# Whether or not this package has at least one .cabal file.
#
Expand Down Expand Up @@ -626,12 +638,25 @@ let

# Path to the Haskell package.
#
# pkgPath :: Path
pkgPath = lib.cleanSourceWith {
# filteredPkgPath :: Path
filteredPkgPath = lib.cleanSourceWith {
src = rawPkgPath;
filter = path: type: localPkgFilter localPkgDefaultFilter pkgName path type;
name = "stacklock2nix-pkg-sources-" + pkgName;
};

# Path to the Haskell package,
# but if it doesn't contain a .cabal file
# then we call the `generateCabalFile` function to potentially pre-generate
# the .cabal file. This is useful if the `package.yaml` file needs special
# treatment, eg, because of includes.
#
# pkgPath :: Path
pkgPath =
if hasSingleCabalFile then
filteredPkgPath
else
generateCabalFile pkgName localPkgPathStr filteredPkgPath;
in
{ inherit pkgPath pkgName; };

Expand Down

0 comments on commit e3698e7

Please sign in to comment.