on bab2eae help sign in
haskell.nix/lib/stack-cache-generator.nix
113 lines 4.3 kB history raw
1# Generate cache entries for dependencies of package defined in `src`
3{ pkgs, haskellLib }:
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, branchMap ? null
17 # A way to specify in which branch a git commit can
18 # be found
19, lookupBranch ?
20 if branchMap != null
21 then { location, tag, ...}: branchMap."${location}"."${tag}" or null
22 else _: null
23, resolverSha256 ? null
24, nix-tools ? pkgs.haskell-nix.internal-nix-tools # When building stack projects we use the internal nix-tools (compiled with a fixed GHC version)
25, ...
26}:
27let
28 # We only care about the stackYaml file. If src is a local directory
29 # we want to avoid recalculating the cache unless the stack.yaml file
30 # changes.
32 inherit (haskellLib.fetchResolver {
33 inherit src stackYaml resolverSha256;
34 }) resolver fetchedResolver;
36 # Filter just the stack yaml file and any resolver yaml file it points to.
37 maybeCleanedSource =
38 if haskellLib.canCleanSource src
39 then haskellLib.cleanSourceWith {
40 inherit src;
41 filter = path: type:
42 let
43 origSrc = if src ? _isLibCleanSourceWith then src.origSrc else src;
44 origSubDir = if src ? _isLibCleanSourceWithEx then src.origSubDir else "";
45 relPath = pkgs.lib.removePrefix (toString origSrc + origSubDir + "/") path;
47 # checks if path1 is a parent directory for path2
48 isParent = path1: path2: pkgs.lib.hasPrefix "${path1}/" path2;
50 in
51 (relPath == stackYaml)
52 || (resolver != null && (relPath == resolver || isParent relPath resolver))
53 ;
54 }
55 else src;
57 # All repos served via ssh or git protocols are usually private
58 private = url: pkgs.lib.substring 0 4 url != "http";
60 repos = builtins.fromJSON (builtins.readFile (pkgs.runCommand "stack-repos" {
61 buildInputs = [ nix-tools ];
62 } ''
63 TMP=$(mktemp -d)
64 cd $TMP
65 cp -r "${maybeCleanedSource}/." $TMP
66 chmod -R +w $TMP
67 substituteInPlace ${stackYaml} --replace "# nix-sha256:" "nix-sha256:"
68 ${pkgs.lib.optionalString (fetchedResolver != null) ''
69 substituteInPlace ${stackYaml} --replace "${resolver}" "${fetchedResolver}"
70 ''}
71 stack-repos --stack-yaml ${stackYaml}
72 cp repos.json $out
73 ''));
75 cabalName = path: builtins.readFile (pkgs.runCommand "cabal-name" {
76 buildInputs = [ nix-tools ];
77 } ''
78 cabal-name ${path} > $out
79 '');
81 hashPath = path:
82 builtins.readFile (pkgs.runCommand "hash-path" { preferLocalBuild = true; }
83 "echo -n $(${pkgs.nix}/bin/nix-hash --type sha256 --base32 ${path}) > $out");
84in with pkgs.lib;
85concatMap (dep:
86 let
87 is-private = private dep.url;
88 sha256 = if dep.sha256 != null
89 then dep.sha256
90 else lookupSha256 {
91 location = dep.url;
92 tag = dep.rev;
93 };
94 branch = lookupBranch {
95 location = dep.url;
96 tag = dep.rev;
97 };
98 pkgsrc =
99 if !is-private && sha256 != null
100 then pkgs.fetchgit {
101 inherit (dep) url rev;
102 inherit sha256;
103 }
104 else builtins.fetchGit ({
105 inherit (dep) url rev;
106 } // pkgs.lib.optionalAttrs (branch != null) { ref = branch; });
107 in map (subdir: {
108 name = cabalName "${pkgsrc}/${subdir}";
109 inherit (dep) url rev;
110 inherit is-private;
111 sha256 = if !is-private then hashPath pkgsrc else null;
112 } // (optionalAttrs (subdir != "") { inherit subdir; }))
113 (dep.subdirs or [ "" ])) repos