summaryrefslogtreecommitdiffstats
path: root/lib/haskell.nix
blob: f87cfa7613ff7bddbfdba44c0333baec8b990c8d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
{ lib }:

with builtins;

rec {

  # Derive a file by substituting
  # "${pkgs.foo}/bin/foo" for each {-pkg-}"foo", and
  # "${pkgs.bar}/bin/foo" for each {-pkg:bar-}"foo".
  # If a package doesn't exist, a warning gets printed.
  substitutePkgs = name: { callsite ? null, pkgs, path }:
    let
      sourceDescription =
        if callsite != null then
          "${name} in ${toString callsite}"
        else
          "${name} from ${toString path}";

      f = dependencies: s:
        let
          parse = match "(.*)([{]-pkg(:([^}]+))?-[}]\"([^\"]+)\")(.*)" s;
          prefix = elemAt parse 0;
          pname = if elemAt parse 3 != null then elemAt parse 3 else exename;
          exename = elemAt parse 4;
          suffix = elemAt parse 5;
          pkg = pkgs.${pname} or null;

          substitute =
            if pkg != null then
              "${pkg}/bin/${exename}"
            else
              trace (toString [
                "lib.haskell.substitutePkgs:"
                "warning:"
                "while deriving ${sourceDescription}:"
                "no substitute found for ${elemAt parse 1}"
              ])
              exename;
        in
        if parse == null then
          (pkgs.writeText name s).overrideAttrs (old: {
            dependencies =
              lib.uniq
                (lib.sort (lib.on lib.lessThan (lib.getAttr "name"))
                  (filter
                    (lib.ne null)
                    (old.dependencies or [] ++ dependencies)));
          })

        else
          f (dependencies ++ [pkg]) (prefix + toJSON substitute + suffix);
    in
    f [] (readFile path);
}