on 949b2df help sign in
haskell.nix/lib/stack-cache-generator.nix
99 lines 3.7 kB history raw
1# Generate cache entries for dependencies of package defined in `src`
3{ pkgs, haskellLib, nix-tools }:
4{ src
5, stackYaml ? "stack.yaml"
6, sha256map ? null
7 # An alternative to adding `# nix-sha256:` comments into the
8 # stack.yaml file:
9 # sha256map =
10 # { "https://github.com/jgm/pandoc-citeproc"."0.17"
11 # = "0dxx8cp2xndpw3jwiawch2dkrkp15mil7pyx7dvd810pwc22pm2q"; };
12, lookupSha256 ?
13 if sha256map != null
14 then { location, tag, ...}: sha256map."${location}"."${tag}"
15 else _: null
16, ...
17}:
18let
19 # We only care about the stackYaml file. If src is a local directory
20 # we want to avoid recalculating the cache unless the stack.yaml file
21 # changes.
23 # Using origSrcSubDir bypasses any cleanSourceWith so that it will work when
24 # access to the store is restricted. If origSrc was already in the store
25 # you can pass the project in as a string.
26 rawStackYaml = builtins.readFile ((src.origSrcSubDir or src) + ("/" + stackYaml));
28 # Determine the resolver as it may point to another file we need
29 # to look at.
30 resolver =
31 let
32 rs = pkgs.lib.lists.concatLists (
33 pkgs.lib.lists.filter (l: l != null)
34 (builtins.map (l: builtins.match "^resolver: *(.*)" l)
35 (pkgs.lib.splitString "\n" rawStackYaml)));
36 in
37 pkgs.lib.lists.head (rs ++ [ null ]);
39 # Filter just the stack yaml file and any reolver yaml file it points to.
40 maybeCleanedSource =
41 if haskellLib.canCleanSource src
42 then haskellLib.cleanSourceWith {
43 inherit src;
44 filter = path: type:
45 pkgs.lib.hasSuffix ("/" + stackYaml) path
46 || (resolver != null && pkgs.lib.hasSuffix ("/" + resolver) path);
47 }
48 else src;
50 # All repos served via ssh or git protocols are usually private
51 private = url: pkgs.lib.substring 0 4 url != "http";
53 repos = builtins.fromJSON (builtins.readFile (pkgs.runCommand "stack-repos" {
54 buildInputs = [ nix-tools ];
55 } ''
56 TMP=$(mktemp -d)
57 cd $TMP
58 cp -r "${maybeCleanedSource}/." $TMP
59 chmod -R +w $TMP
60 substituteInPlace ${stackYaml} --replace "# nix-sha256:" "nix-sha256:"
61 stack-repos --stack-yaml ${stackYaml}
62 cp repos.json $out
63 ''));
65 cabalName = path: builtins.readFile (pkgs.runCommand "cabal-name" {
66 buildInputs = [ nix-tools ];
67 } ''
68 cabal-name ${path} > $out
69 '');
71 hashPath = path:
72 builtins.readFile (pkgs.runCommand "hash-path" { preferLocalBuild = true; }
73 "echo -n $(${pkgs.nix}/bin/nix-hash --type sha256 --base32 ${path}) > $out");
74in with pkgs.lib;
75concatMap (dep:
76 let
77 is-private = private dep.url;
78 sha256 = if dep.sha256 != null
79 then dep.sha256
80 else lookupSha256 {
81 location = dep.url;
82 tag = dep.rev;
83 };
84 pkgsrc =
85 if !is-private && sha256 != null
86 then pkgs.fetchgit {
87 inherit (dep) url rev;
88 inherit sha256;
89 }
90 else builtins.fetchGit {
91 inherit (dep) url rev;
92 };
93 in map (subdir: {
94 name = cabalName "${pkgsrc}/${subdir}";
95 inherit (dep) url rev;
96 inherit is-private;
97 sha256 = if !is-private then hashPath pkgsrc else null;
98 } // (optionalAttrs (subdir != "") { inherit subdir; }))
99 (dep.subdirs or [ "" ])) repos