@@ -70,13 +70,19 @@ self: super: {
7070 { pkg-def # Base package set. Either from stackage (via stack-to-nix) or from a cabal projects plan file (via plan-to-nix)
7171 , pkg-def-extras ? [] # Additional packages to augment the Base package set `pkg-def` with.
7272 , modules ? []
73+ , extra-hackages ? [] # Extra Hackage repositories to use besides main one.
7374 }@args:
7475
75− import ../package-set.nix (args // {
76+ let
77+ hackageAll = builtins.foldl' (base: extra: base // extra) hackage extra-hackages;
78+ in
79+
80+ import ../package-set.nix {
81+ inherit (args) pkg-def pkg-def-extras;
7682 modules = defaultModules ++ modules;
7783 pkgs = self;
78− inherit hackage pkg-def;
79− });
84+ hackage = hackageAll;
85+ };
8086
8187 # Some boot packages (libiserv) are in lts, but not in hackage,
8288 # so we should not try to get it from hackage based on the stackage
@@ -128,6 +134,7 @@ self: super: {
128134 { plan-pkgs # Path to the output of plan-to-nix
129135 , pkg-def-extras ? []
130136 , modules ? []
137+ , extra-hackages ? []
131138 }@args:
132139
133140 let
@@ -146,6 +153,7 @@ self: super: {
146153 modules = [ { doExactConfig = true; } patchesModule ]
147154 ++ modules
148155 ++ plan-pkgs.modules or [];
156+ inherit extra-hackages;
149157 };
150158
151159 # Package sets for all stackage snapshots.
@@ -169,33 +177,60 @@ self: super: {
169177 nix-tools = self.buildPackages.haskell-nix.nix-tools-cross-compiled;
170178 # TODO perhaps there is a cleaner way to get a suitable nix-tools.
171179
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.
173183 hackageTarball = { index-state, sha256, nix-tools ? self.haskell-nix.nix-tools, ... }:
174184 assert sha256 != null;
175− self.fetchurl {
176− name = "01-index.tar.gz-at-${builtins.replaceStrings [":"] [""] index-state}";
185+ let at = builtins.replaceStrings [":"] [""] index-state; in
186+ { name = "hackage.haskell.org-at-${at}";
187+ index = self.fetchurl {
188+ name = "01-index.tar.gz-at-${at}";
177189 url = "https://hackage.haskell.org/01-index.tar.gz";
178190 downloadToTemp = true;
179191 postFetch = "${nix-tools}/bin/truncate-index -o $out -i $downloadedFile -s ${index-state}";
180192
181193 outputHashAlgo = "sha256";
182194 outputHash = sha256;
195+ };
183196 };
184197
185− mkLocalHackageRepo = import ../mk-local-hackage-repo { inherit hackageTarball; pkgs = self; };
198+ # Creates Cabal local repository from { name, index } set.
199+ mkLocalHackageRepo = import ../mk-local-hackage-repo self;
186200
187− dotCabal = { index-state, sha256, cabal-install, ... }@args:
188− self.runCommand "dot-cabal-at-${builtins.replaceStrings [":"] [""] index-state}" { nativeBuildInputs = [ cabal-install ]; } ''
201+ dotCabal = { index-state, sha256, cabal-install, extra-hackage-tarballs ? [], ... }@args:
202+ let
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;
208+ in
209+ self.runCommand dotCabalName { nativeBuildInputs = [ cabal-install ]; } ''
189210 mkdir -p $out/.cabal
190211 cat <<EOF > $out/.cabal/config
191− repository cached
192− url: file:${mkLocalHackageRepo args}
193− secure: True
194− root-keys:
195− key-threshold: 0
212+ ${self.lib.concatStrings (
213+ map (tarball:
214+ ''
215+ repository ${tarball.name}
216+ url: file:${mkLocalHackageRepo tarball}
217+ secure: True
218+ root-keys:
219+ key-threshold: 0
220+
221+ '') allTarballs
222+ )}
196223 EOF
197− mkdir -p $out/.cabal/packages/cached
198− HOME=$out cabal new-update cached
224+
225+ # All repositories must be mkdir'ed before calling new-update on any repo,
226+ # otherwise it fails.
227+ ${self.lib.concatStrings (map ({ name, ... }: ''
228+ mkdir -p $out/.cabal/packages/${name}
229+ '') allTarballs)}
230+
231+ ${self.lib.concatStrings (map ({ name, ... }: ''
232+ HOME=$out cabal new-update ${name}
233+ '') allTarballs)}
199234 '';
200235
201236 # Some of features of haskell.nix rely on using a hackage index
@@ -429,6 +464,7 @@ self: super: {
429464 pkg-def-extras = args.pkg-def-extras or [];
430465 modules = (args.modules or [])
431466 ++ self.lib.optional (args ? ghc) { ghc.package = args.ghc; };
467+ extra-hackages = args.extra-hackages or [];
432468 };
433469 in { inherit (pkg-set.config) hsPkgs; inherit pkg-set; plan-nix = plan.nix; };
434470