@@ -218,27 +218,77 @@ self: super: {
218218 cabal-to-nix "${src}" "${src}/${cabal-file}" > "$out"
219219 '';
220220
221+
222+ # Given a single cache entry:
223+ # { name = ...; url = ...; rev = ...; ref = ...; sha256 = ...; cabal-file = ...; type = ...; is-private = ...; }
224+ # compute a string that represents this cache entry:
225+ # "${url} ${rev} ${subdir} ${sha256} ${name} ${nix-expr}"
226+ #
227+ # This handles private repositories with the `is-private` argument
228+ # (with `builtins.fetchGit`), as well as handling stack-based projects
229+ # with the `type` argument.
230+ mkCacheLine = { name, url, rev, ref ? null, subdir ? ".", sha256 ? null, cabal-file ? "${name}.cabal", type ? "cabal", is-private ? false }:
231+ let
232+ # Fetch the entire repo, using either pkgs.fetchgit or
233+ # builtins.fetchGit depending on whether the repo is private.
234+ entireRepo =
235+ if is-private
236+ then
237+ # It doesn't make sense to specify sha256 on a private repo
238+ # because it is not used by buitins.fetchGit.
239+ assert isNull sha256;
240+ builtins.fetchGit {
241+ url = url;
242+ rev = rev;
243+ } // self.buildPackages.lib.optionalAttrs (ref != null) {
244+ ref = ref;
245+ }
246+ else
247+ # Non-private repos must have sha256 set.
248+ assert sha256 != null;
249+ # pkgs.fetchgit doesn't have any way of fetching from a given
250+ # ref.
251+ assert isNull ref;
252+ self.buildPackages.pkgs.fetchgit {
253+ url = url;
254+ rev = rev;
255+ sha256 = sha256;
256+ };
257+
258+ # This is basically entireRepo, but focused on the subdir if it is specified.
259+ repoWithSubdir =
260+ entireRepo + (if subdir == "." then "" else "/" + subdir);
261+
262+ nix-expr =
263+ if type == "cabal"
264+ then
265+ self.buildPackages.haskell-nix.callCabalToNix {
266+ src = repoWithSubdir;
267+ inherit name cabal-file;
268+ }
269+ else if type == "stack"
270+ then
271+ (self.buildPackages.haskell-nix.callStackToNix {
272+ src = repoWithSubdir;
273+ inherit name subdir;
274+ }).projectNix
275+ else
276+ throw "Unknown type '${type}` for a cache entry";
277+
278+ sha256String = if isNull sha256 then self.buildPackages.lib.fakeSha256 else sha256;
279+
280+ in "${url} ${rev} ${subdir} ${sha256String} ${name} ${nix-expr}";
281+
221282 # Given a list of repos:
222− # [ { name = ...; url = ...; rev = ...; sha256 = ... } ]
283+ # [ { name = ...; url = ...; rev = ...; ref = ...; sha256 = ...; cabal-file = ...; type = ...; is-private = ...; } ]
223284 # produce a cache file that can be used for
224285 # stack-to-nix or plan-to-nix to prevent them
225286 # from needing network access.
226− mkCacheFile = repos: let
227− fetchRepo = repo: (self.buildPackages.pkgs.fetchgit { inherit (repo) url sha256 rev; }) + (if repo.subdir or "." == "." then "" else "/" + repo.subdir);
228−
229− f = { name, url, rev, subdir ? ".", sha256, cabal-file ? "${name}.cabal", type ? "cabal" }@repo:
230− let nix-expr =
231− if type == "cabal"
232− then self.buildPackages.haskell-nix.callCabalToNix { src = (fetchRepo repo); inherit name cabal-file; }
233− else if type == "stack"
234− then (self.buildPackages.haskell-nix.callStackToNix { src = (fetchRepo repo); inherit name subdir; }).projectNix
235− else throw "Unknown type '${type}` for a cache entry";
236− in "${url} ${rev} ${subdir} ${sha256} ${name} ${nix-expr}";
237− in
238− self.buildPackages.pkgs.writeTextFile {
239− name = "cache-file";
240− text = self.buildPackages.lib.concatMapStringsSep "\n" f repos;
241− };
287+ mkCacheFile = repos:
288+ self.buildPackages.pkgs.writeTextFile {
289+ name = "cache-file";
290+ text = self.buildPackages.lib.concatMapStringsSep "\n" mkCacheLine repos;
291+ };
242292
243293 mkCacheModule = cache:
244294 # for each item in the `cache`, set
@@ -257,12 +307,23 @@ self: super: {
257307 # TODO: this should be moved into `call-stack-to-nix`
258308 # it should be automatic and not the burden of
259309 # the end user to work around nix peculiarities.
260− { packages = builtins.foldl' (x: y: x // y) {}
261− (builtins.map ({ name, url, rev, sha256, subdir ? null, ... }:
262− { ${name} = { src = self.buildPackages.pkgs.fetchgit { inherit url rev sha256; }; }
263− // self.buildPackages.lib.optionalAttrs (subdir != null)
264− { postUnpack = "sourceRoot+=/${subdir}; echo source root reset to $sourceRoot"; };
265− }) cache);
310+ { packages =
311+ let
312+ repoToAttr = { name, url, rev, ref ? null, sha256 ? null, subdir ? null, is-private ? false, ... }: {
313+ ${name} = {
314+ src =
315+ if is-private
316+ then
317+ builtins.fetchGit { inherit url rev; }
318+ // self.buildPackages.lib.optionalAttrs (ref != null) { inherit ref; }
319+ else
320+ self.buildPackages.pkgs.fetchgit { inherit url rev sha256; };
321+ } // self.buildPackages.lib.optionalAttrs (subdir != null) { postUnpack = "sourceRoot+=/${subdir}; echo source root reset to $sourceRoot"; };
322+ };
323+
324+ cacheMap = builtins.map repoToAttr cache;
325+ in
326+ builtins.foldl' (x: y: x // y) {} cacheMap;
266327 };
267328
268329 # Takes a haskell src directory runs cabal new-configure and plan-to-nix.