Skip to content

Instantly share code, notes, and snippets.

@ocharles
Last active October 20, 2020 10:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ocharles/6d151ba14e3ee83bcb858748add8b3e2 to your computer and use it in GitHub Desktop.
Save ocharles/6d151ba14e3ee83bcb858748add8b3e2 to your computer and use it in GitHub Desktop.
{ pkgs, lib, haskellLib, plan-file }: self: super:
let
planJSON = pkgs.stdenv.mkDerivation {
buildInputs = with pkgs; [ cabal-install git pkgs.haskell.packages.ghc8101.ghc ];
name = "plan.json";
src =
builtins.filterSource
(
name: type:
let
not-dist =
!(pkgs.lib.hasSuffix "/dist" name) && !(pkgs.lib.hasSuffix "/dist-newstyle" name) && !(pkgs.lib.hasSuffix "/dist-repl" name);
is-cabal =
pkgs.lib.hasSuffix ".cabal" (baseNameOf name);
is-cabal-project =
pkgs.lib.hasSuffix ".project" (baseNameOf name);
in
not-dist && (type == "directory" || is-cabal || is-cabal-project)
)
./.;
buildPhase = ''
export SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt
export GIT_SSL_CAINFO=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt
HOME=$(pwd) cabal update
HOME=$(pwd) cabal configure
substituteInPlace dist-newstyle/cache/plan.json --replace "$(pwd)" "${./.}"
'';
installPhase = "cp dist-newstyle/cache/plan.json $out";
};
plan =
builtins.fromJSON (builtins.readFile planJSON);
hackage-revisions =
builtins.fromJSON (builtins.readFile ./hackage.json);
units-by-package =
lib.groupBy
(unit: unit.pkg-name)
(lib.filter is-built plan.install-plan);
is-built = unit:
unit.type != "pre-existing";
units =
lib.mapAttrs
(_: units: combineUnits (map analyze-unit units))
units-by-package;
analyze-unit = unit:
rec {
inherit (unit) flags;
pname = unit.pkg-name;
version = unit.pkg-version;
editedCabalFile = unit.pkg-cabal-sha256 or null;
revision =
let
revisions =
hackage-revisions."${pname}"."${version}".revisions;
bySha256 =
lib.listToAttrs
(
lib.mapAttrsToList
(
k: v:
lib.nameValuePair
(v.sha256 or "ignore")
(v.revNum or null)
)
revisions
);
in
toString (bySha256."${unit.pkg-cabal-sha256}" or null);
src =
if unit.pkg-src ? "repo" then
builtins.fetchTarball {
url = "${unit.pkg-src.repo.uri}package/${pname}-${version}/${pname}-${version}.tar.gz";
}
else
if unit.pkg-src ? "source-repo" && unit.pkg-src.source-repo.type == "git" then
builtins.fetchGit {
url = unit.pkg-src.source-repo.location;
ref = unit.pkg-src.source-repo.tag;
} + "/${unit.pkg-src.source-repo.subdir or ""}"
else if unit.pkg-src ? "path" && unit.pkg-src.type == "local" then
unit.pkg-src.path
else
builtins.trace (toString (builtins.toJSON unit.pkg-src)) (assert false; null);
};
combineUnits = units:
let
f = x: y:
if x.src != y.src then
builtins.trace "x = ${x.src}, y = ${y.src}" x
else
x;
in
lib.foldl f (lib.head units) units;
to-derivation =
package-name: unit:
let
flag-modifiers =
lib.mapAttrsToList
(
flag: enable: drv:
if enable then
haskellLib.enableCabalFlag drv flag
else
haskellLib.disableCabalFlag drv flag
)
(unit.flags or {});
initial-derivation =
self.callCabal2nix package-name (builtins.trace unit.src unit.src) {};
config = {
inherit (unit) editedCabalFile revision;
doCheck = false;
# Jailbreak everything because we're relying on Cabal to find a good plan,
# and we might have needed to override constraints.
jailbreak = true;
};
in
lib.foldl
(x: f: f x)
(haskellLib.overrideCabal initial-derivation (drv: config))
flag-modifiers;
in
lib.mapAttrs to-derivation units
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment