@@ -70,13 +70,19 @@ self: super: {
70 { pkg-def # Base package set. Either from stackage (via stack-to-nix) or from a cabal projects plan file (via plan-to-nix)
70 { pkg-def # Base package set. Either from stackage (via stack-to-nix) or from a cabal projects plan file (via plan-to-nix)
71 , pkg-def-extras ? [] # Additional packages to augment the Base package set `pkg-def` with.
71 , pkg-def-extras ? [] # Additional packages to augment the Base package set `pkg-def` with.
72 , modules ? []
72 , modules ? []
73+ , extra-hackages ? [] # Extra Hackage repositories to use besides main one.
77+ hackageAll = builtins.foldl' (base: extra: base // extra) hackage extra-hackages;
75− import ../package-set.nix (args // {
80+ import ../package-set.nix {
81+ inherit (args) pkg-def pkg-def-extras;
76 modules = defaultModules ++ modules;
82 modules = defaultModules ++ modules;
77 pkgs = self;
83 pkgs = self;
78− inherit hackage pkg-def;
84+ hackage = hackageAll;
81 # Some boot packages (libiserv) are in lts, but not in hackage,
87 # Some boot packages (libiserv) are in lts, but not in hackage,
82 # so we should not try to get it from hackage based on the stackage
88 # so we should not try to get it from hackage based on the stackage
@@ -128,6 +134,7 @@ self: super: {
128 { plan-pkgs # Path to the output of plan-to-nix
134 { plan-pkgs # Path to the output of plan-to-nix
129 , pkg-def-extras ? []
135 , pkg-def-extras ? []
130 , modules ? []
136 , modules ? []
137+ , extra-hackages ? []
@@ -146,6 +153,7 @@ self: super: {
146 modules = [ { doExactConfig = true; } patchesModule ]
153 modules = [ { doExactConfig = true; } patchesModule ]
147 ++ modules
154 ++ modules
148 ++ plan-pkgs.modules or [];
155 ++ plan-pkgs.modules or [];
156+ inherit extra-hackages;
151 # Package sets for all stackage snapshots.
159 # Package sets for all stackage snapshots.
@@ -169,33 +177,60 @@ self: super: {
169 nix-tools = self.buildPackages.haskell-nix.nix-tools-cross-compiled;
177 nix-tools = self.buildPackages.haskell-nix.nix-tools-cross-compiled;
170 # TODO perhaps there is a cleaner way to get a suitable nix-tools.
178 # TODO perhaps there is a cleaner way to get a suitable nix-tools.
172− # Produce a fixed output derivation from a moving target (hackage index tarball)
180+ # Produce a fixed output derivation from a moving target (hackage index tarball)
181+ # Takes desired index-state and sha256 and produces a set { name, index }, where
182+ # index points to "01-index.tar.gz" file downloaded from hackage.haskell.org.
173 hackageTarball = { index-state, sha256, nix-tools ? self.haskell-nix.nix-tools, ... }:
183 hackageTarball = { index-state, sha256, nix-tools ? self.haskell-nix.nix-tools, ... }:
174 assert sha256 != null;
184 assert sha256 != null;
185+ let at = builtins.replaceStrings [":"] [""] index-state; in
186+ { name = "hackage.haskell.org-at-${at}";
175− self.fetchurl {
187+ index = self.fetchurl {
176− name = "01-index.tar.gz-at-${builtins.replaceStrings [":"] [""] index-state}";
188+ name = "01-index.tar.gz-at-${at}";
177 url = "https://hackage.haskell.org/01-index.tar.gz";
189 url = "https://hackage.haskell.org/01-index.tar.gz";
178 downloadToTemp = true;
190 downloadToTemp = true;
179 postFetch = "${nix-tools}/bin/truncate-index -o $out -i $downloadedFile -s ${index-state}";
191 postFetch = "${nix-tools}/bin/truncate-index -o $out -i $downloadedFile -s ${index-state}";
181 outputHashAlgo = "sha256";
193 outputHashAlgo = "sha256";
182 outputHash = sha256;
194 outputHash = sha256;
198+ # Creates Cabal local repository from { name, index } set.
185− mkLocalHackageRepo = import ../mk-local-hackage-repo { inherit hackageTarball; pkgs = self; };
199+ mkLocalHackageRepo = import ../mk-local-hackage-repo self;
187− dotCabal = { index-state, sha256, cabal-install, ... }@args:
201+ dotCabal = { index-state, sha256, cabal-install, extra-hackage-tarballs ? [], ... }@args:
203+ allTarballs = [ (hackageTarball args) ] ++ extra-hackage-tarballs;
204+ allNames = self.lib.concatMapStringsSep "-" (tarball: tarball.name) allTarballs;
205+ # Main Hackage index-state is embedded in its name and thus will propagate to
206+ # dotCabalName anyway.
207+ dotCabalName = "dot-cabal-" + allNames;
188− self.runCommand "dot-cabal-at-${builtins.replaceStrings [":"] [""] index-state}" { nativeBuildInputs = [ cabal-install ]; } ''
209+ self.runCommand dotCabalName { nativeBuildInputs = [ cabal-install ]; } ''
189 mkdir -p $out/.cabal
210 mkdir -p $out/.cabal
190 cat <<EOF > $out/.cabal/config
211 cat <<EOF > $out/.cabal/config
212+ ${self.lib.concatStrings (
191− repository cached
215+ repository ${tarball.name}
192− url: file:${mkLocalHackageRepo args}
216+ url: file:${mkLocalHackageRepo tarball}
193− secure: True
217+ secure: True
194− root-keys:
218+ root-keys:
195− key-threshold: 0
219+ key-threshold: 0
225+ # All repositories must be mkdir'ed before calling new-update on any repo,
226+ # otherwise it fails.
227+ ${self.lib.concatStrings (map ({ name, ... }: ''
197− mkdir -p $out/.cabal/packages/cached
228+ mkdir -p $out/.cabal/packages/${name}
231+ ${self.lib.concatStrings (map ({ name, ... }: ''
198− HOME=$out cabal new-update cached
232+ HOME=$out cabal new-update ${name}
201 # Some of features of haskell.nix rely on using a hackage index
236 # Some of features of haskell.nix rely on using a hackage index
@@ -429,6 +464,7 @@ self: super: {
429 pkg-def-extras = args.pkg-def-extras or [];
464 pkg-def-extras = args.pkg-def-extras or [];
430 modules = (args.modules or [])
465 modules = (args.modules or [])
431 ++ self.lib.optional (args ? ghc) { ghc.package = args.ghc; };
466 ++ self.lib.optional (args ? ghc) { ghc.package = args.ghc; };
467+ extra-hackages = args.extra-hackages or [];
433 in { inherit (pkg-set.config) hsPkgs; inherit pkg-set; plan-nix = plan.nix; };
469 in { inherit (pkg-set.config) hsPkgs; inherit pkg-set; plan-nix = plan.nix; };