haskell.nix/modules/hackage.nix

90 lines
3.5 KiB
Nix
Raw Normal View History

2018-10-29 10:43:51 +03:00
{ lib, config, pkgs, ... }:
let
# hackage looks like the following:
# { "package-name" =
# { "a.b.c.d" =
# rec { sha256 = $pkgVersionSha256;
# revisions =
# { r0 = { outPath = ./hackage/...; revNum = 0; sha256 = $revisionSha256; };
# default = revisions.r0; };
# };
# };
# };
# }
# However it's more convenient to deal with the leaf nodes, and as such
# push the `sha256` of the package/version into the revision and keep the
# revision.sha256 as revisionSha256; as well as making the revision content
# addressable by it's revision hash.
#
# Thus we transform hackage into hackageConfigs, which will look like:
# { "package-name" =
# { "a.b.c.d" =
# rec { sha256 = $packageVersionSha256;
# revisions =
# { r0 = { outPath = ./hackage/...;
# sha256 = $packageVersionSha256;
# revision = $revNum;
# revisionSha256 = $revisionSha256; };
# default = revisions.r0;
# $revisionSha256 = revisions.r0; };
# };
# };
# };
# }
hackageConfigs =
lib.flip lib.mapAttrs config.hackage.db
(pname: lib.mapAttrs
(vnum: version: version // {
revisions =
let
2018-11-04 13:33:11 +03:00
rev2Config = rev: { system, compiler, flags, pkgs, hsPkgs, pkgconfPkgs, ... }@modArgs: {
2018-10-29 10:43:51 +03:00
inherit (version) sha256;
revision = rev.revNum;
revisionSha256 = rev.sha256;
2018-11-04 13:33:11 +03:00
} // import rev modArgs;
2018-10-29 10:43:51 +03:00
f = rev: acc: acc // {
# If there's a collision (e.g. a revision was
# reverted), pick the one with the smaller
# revNum. They're identical, but if the smaller one is
# r0 then we don't have to download a cabal file.
${rev.sha256} = if lib.hasAttr rev.sha256 acc && acc.${rev.sha256}.revNum < rev.revNum
then acc.${rev.sha256}
else rev;
};
contentAddressedRevs = lib.foldr f {} (builtins.attrValues version.revisions);
in lib.mapAttrs (_: rev2Config) (version.revisions // contentAddressedRevs);
}));
in {
options.ghc.package = lib.mkOption {
type = lib.types.package;
# obtain the compiler from the haskell packages.
# this should allow us to use `config` overrides
# in the nixpkgs setup, and properly override the
# complier as needed.
default = pkgs.buildPackages.haskell.compiler.${config.compiler.nix-name} or (throw ''
This version of Nixpkgs does not contain GHC ${config.compiler.version}
(or it is not present at attribute '${config.compiler.nix-name})').
Either switch to a version of Nixpkgs which does have this version, or use a version
of GHC which the current version of Nixpkgs contains.
'');
2018-11-04 13:33:11 +03:00
defaultText = "pkgs.buildPackages.haskell.compiler.\${config.compiler.nix-name}";
2018-10-29 10:43:51 +03:00
};
options.hackage.db = lib.mkOption {
type = lib.types.unspecified; # TODO: Worth type checking with modules? Or does that slow eval too much?
};
options.hackage.configs = lib.mkOption {
type = lib.types.unspecified;
};
# Note: we inject rts."1.0" as invalid here. This package can only
# be built by GHC's build system. However it may show up in stackage
# snapshots. As such we just null it out.
config.hackage.configs = hackageConfigs
// { rts."1.0".revisions.default = null; };
2018-10-29 10:43:51 +03:00
}