@@ -7,49 +7,197 @@
77with pkgs;
88
99let
10− withIfdInputs = builtins.mapAttrs (n: x:
11− if n == "ifdInputs"
12− then pkgs.recurseIntoAttrs (builtins.mapAttrs (_: pkgs.haskell-nix.withInputs) x)
13− else x);
10+ # Set recurseForDerivations for both children and grand-children values in
11+ # the input association list, but only if the key is "ifdInputs".
12+ #
13+ # withIfdInputs :: AttrSet -> AttrSet
14+ #
15+ # The values in the input attribute set must be attribute sets themselves.
16+ #
17+ # >>> withIfdInputs { ifdInputs = { plan-nix = { a = true; b = "hello"; }; }; cat = 2; }
18+ # { ifdInputs = {
19+ # plan-nix = {
20+ # a = true;
21+ # b = "hello";
22+ # recurseForDerivations = true;
23+ # };
24+ # recurseForDerivations = true;
25+ # };
26+ # cat = 2;
27+ # }
28+ #
29+ # >>> withIfdInputs { dog = "hello"; }
30+ # { dog = "hello"; }
31+ #
32+ # >>> withIfdInputs { }
33+ # { }
34+ withIfdInputs =
35+ builtins.mapAttrs
36+ (name: val:
37+ if name == "ifdInputs"
38+ then
39+ pkgs.recurseIntoAttrs
40+ (builtins.mapAttrs (_: v: pkgs.haskell-nix.withInputs v) val)
41+ else val
42+ );
43+
1444 util = import ./util.nix { inherit (pkgs.haskell-nix) cabal-install; };
15−in pkgs.recurseIntoAttrs {
16− haskellNixRoots = haskell-nix.haskellNixRoots' ifdLevel;
17−} // pkgs.lib.optionalAttrs (ifdLevel > 1) (
18− builtins.mapAttrs (_: y: withIfdInputs y) ((if ifdLevel < 3
19− then builtins.mapAttrs (_: d: pkgs.recurseIntoAttrs (pkgs.lib.filterAttrs (n: _: n == "ifdInputs") d))
20− else x: x) {
21− cabal-simple = haskell-nix.callPackage ./cabal-simple { inherit util; };
22− cabal-simple-prof = haskell-nix.callPackage ./cabal-simple-prof { inherit util; };
23− cabal-sublib = haskell-nix.callPackage ./cabal-sublib { inherit util; };
24− cabal-22 = haskell-nix.callPackage ./cabal-22 { inherit util; };
25− with-packages = haskell-nix.callPackage ./with-packages { inherit util; };
26− builder-haddock = haskell-nix.callPackage ./builder-haddock {};
27− stack-simple = haskell-nix.callPackage ./stack-simple {};
28− stack-local-resolver = haskell-nix.callPackage ./stack-local-resolver {};
29− snapshots = haskell-nix.callPackage ./snapshots {};
30− shell-for = haskell-nix.callPackage ./shell-for {};
31− shell-for-setup-deps = haskell-nix.callPackage ./shell-for-setup-deps {};
32− setup-deps = import ./setup-deps { inherit pkgs; };
33− callStackToNix = haskell-nix.callPackage ./call-stack-to-nix {};
34− callCabalProjectToNix = haskell-nix.callPackage ./call-cabal-project-to-nix {};
35− cabal-source-repo = haskell-nix.callPackage ./cabal-source-repo {};
36− buildable = haskell-nix.callPackage ./buildable {};
37− project-flags-cabal = haskell-nix.callPackage ./project-flags/cabal.nix {};
38− project-flags-stack = haskell-nix.callPackage ./project-flags/stack.nix {};
39− fully-static = haskell-nix.callPackage ./fully-static { inherit (pkgs) buildPackages; };
40− ghc-options-cabal = haskell-nix.callPackage ./ghc-options/cabal.nix {};
41− ghc-options-stack = haskell-nix.callPackage ./ghc-options/stack.nix {};
42− exe-only = haskell-nix.callPackage ./exe-only { inherit util; };
43− stack-source-repo = haskell-nix.callPackage ./stack-source-repo {};
45+
46+ # Map the values in an association list over the withIfdInputs function.
47+ #
48+ # addIfdInputsToVal :: AttrSet -> AttrSet
49+ #
50+ # The values in the input association list must be attribute sets themselves.
51+ addIfdInputsToVal = builtins.mapAttrs (_: val: withIfdInputs val);
52+
53+ # Keep only the attribute with the key "ifdInputs".
54+ #
55+ # filterAttrsIfdInputs :: AttrSet -> AttrSet
56+ #
57+ # >>> filterAttrsIfdInputs { ifdInputs = 1; foobar = 2 }
58+ # { ifdInputs = 1 }
59+ #
60+ # >>> filterAttrsIfdInputs { foobar = "hello" }
61+ # { }
62+ filterAttrsIfdInputs = pkgs.lib.filterAttrs (n: _: n == "ifdInputs");
63+
64+ # Remove all keys and values in a attribute set where the key
65+ # doesn't equal "ifdInputs". Set the "recurseForDerivations"
66+ # key in the resulting value.
67+ #
68+ # filterNonIfdInputsSetRecurse :: AttrSet -> AttrSet
69+ #
70+ # >>> filterNonIfdInputsSetRecurse { ifdInputs = 1; foobar = 2 }
71+ # { ifdInputs = 1; recurseForDerivations = true }
72+ #
73+ # >>> filterNonIfdInputsSetRecurse { foobar = "hello" }
74+ # { recurseForDerivations = true; }
75+ filterNonIfdInputsSetRecurse = attrs:
76+ pkgs.recurseIntoAttrs (filterAttrsIfdInputs attrs);
77+
78+ # Filter all out all the keys/values for child values of this attribute set
79+ # where the key is not equal to "ifdInputs".
80+ #
81+ # filterNonIfdInputsValues :: AttrSet -> AttrSet
82+ #
83+ # The values in the input AttrSet must be attribute sets themselves.
84+ #
85+ # >>> filterNonIfdInputsValues { foo = { ifdInputs = 1; cat = 2; }; bar = { dog = "hello"; }; }
86+ # { foo = {
87+ # ifdInputs = 1;
88+ # recurseForDerivations = true;
89+ # };
90+ # bar = {
91+ # recurseForDerivations = true;
92+ # };
93+ # }
94+ #
95+ # >>> filterNonIfdInputsValues { }
96+ # { }
97+ filterNonIfdInputsValues = attrs:
98+ builtins.mapAttrs (_: d: filterNonIfdInputsSetRecurse d) attrs;
99+
100+ # Call filterNonIfdInputsValues on the input attribute set, but only
101+ # if ifdLevel is less than 3. Otherwise, just return the attribute set.
102+ #
103+ # filterNonIfdInputsValuesLTLevel3 :: AttrSet -> AttrSet
104+ #
105+ # >>> filterNonIfdInputsValuesLTLevel3 2 { cabal-doctests = { ifdInputs = {...}; run = ""; }; cabal-simple = { run = ""; }; }
106+ # { cabal-doctests = {
107+ # ifdInputs = {...};
108+ # recurseForDerivations = true;
109+ # };
110+ # cabal-simple = {
111+ # recurseForDerivations = true;
112+ # };
113+ # }
114+ #
115+ # >>> filterNonIfdInputsValuesLTLevel3 1000 { cabal-doctests = { ifdInputs = {...}; run = "..."; }; cabal-simple = { run = "..."; }; }
116+ # { cabal-doctests = {
117+ # ifdInputs = {...};
118+ # run = "...";
119+ # recurseForDerivations = true;
120+ # };
121+ # cabal-simple = {
122+ # run = "...";
123+ # recurseForDerivations = true;
124+ # };
125+ # }
126+ #
127+ # >>> filterNonIfdInputsValuesLTLevel3 0 { }
128+ # { }
129+ filterNonIfdInputsValuesLTLevel3 = ifdLevel: attrs:
130+ if ifdLevel < 3
131+ then filterNonIfdInputsValues attrs
132+ else attrs;
44133
45134 # Run unit tests with: nix-instantiate --eval --strict -A unit.tests
46135 # An empty list means success.
47− unit = let
48− tests = haskell-nix.callPackage ./unit.nix {};
49− in runCommand "unit-tests" { passthru = { inherit tests; }; }
50− (lib.concatMapStringsSep "\n" (t: "echo ${t.name} failed") tests +
51− (if builtins.length tests == 0 then "\ntouch $out" else "\nexit 1"));
52−}))
136+ unitTests =
137+ let
138+ tests = haskell-nix.callPackage ./unit.nix {};
139+ testsFailedEcho = lib.concatMapStringsSep "\n" (t: "echo ${t.name} failed") tests;
140+ testsFinalLine = if builtins.length tests == 0 then "\ntouch $out" else "\nexit 1";
141+ testsScript = testsFailedEcho + testsFinalLine;
142+ in
143+ runCommand "unit-tests" { passthru = { inherit tests; }; } testsScript;
144+
145+ # All tests.
146+ allTests = {
147+ cabal-simple = haskell-nix.callPackage ./cabal-simple { inherit util; };
148+ cabal-simple-prof = haskell-nix.callPackage ./cabal-simple-prof { inherit util; };
149+ cabal-sublib = haskell-nix.callPackage ./cabal-sublib { inherit util; };
150+ cabal-22 = haskell-nix.callPackage ./cabal-22 { inherit util; };
151+ with-packages = haskell-nix.callPackage ./with-packages { inherit util; };
152+ builder-haddock = haskell-nix.callPackage ./builder-haddock {};
153+ stack-simple = haskell-nix.callPackage ./stack-simple {};
154+ stack-local-resolver = haskell-nix.callPackage ./stack-local-resolver {};
155+ snapshots = haskell-nix.callPackage ./snapshots {};
156+ shell-for = haskell-nix.callPackage ./shell-for {};
157+ shell-for-setup-deps = haskell-nix.callPackage ./shell-for-setup-deps {};
158+ setup-deps = import ./setup-deps { inherit pkgs; };
159+ callStackToNix = haskell-nix.callPackage ./call-stack-to-nix {};
160+ callCabalProjectToNix = haskell-nix.callPackage ./call-cabal-project-to-nix {};
161+ cabal-source-repo = haskell-nix.callPackage ./cabal-source-repo {};
162+ buildable = haskell-nix.callPackage ./buildable {};
163+ project-flags-cabal = haskell-nix.callPackage ./project-flags/cabal.nix {};
164+ project-flags-stack = haskell-nix.callPackage ./project-flags/stack.nix {};
165+ fully-static = haskell-nix.callPackage ./fully-static { inherit (pkgs) buildPackages; };
166+ ghc-options-cabal = haskell-nix.callPackage ./ghc-options/cabal.nix {};
167+ ghc-options-stack = haskell-nix.callPackage ./ghc-options/stack.nix {};
168+ exe-only = haskell-nix.callPackage ./exe-only { inherit util; };
169+ stack-source-repo = haskell-nix.callPackage ./stack-source-repo {};
170+
171+ unit = unitTests;
172+ };
173+
174+ # This is the same as allTests, but filter out all the key/vaules from the
175+ # tests other than the "ifdInputs" key if the input ifdLevel is less than 3.
176+ allTestsRemoveIfdLTLevel3 = ifdLevel:
177+ filterNonIfdInputsValuesLTLevel3 ifdLevel allTests;
178+
179+ # This is the same as allTestsRemoveIfdLTLevel3, but make sure
180+ # recurseForDerivations is set on all child values under the
181+ # ifdInputs key.
182+ allTestsWithIfdInputs = ifdLevel:
183+ addIfdInputsToVal (allTestsRemoveIfdLTLevel3 ifdLevel);
184+
185+ # This is the same as allTestsWithIfdInputs, but returns an empty attribute set
186+ # if the input ifdLevel is 0 or 1.
187+ #
188+ # Here is the result based on the input ifdLevel:
189+ #
190+ # - input ifdLevel is 0 or 1: {}
191+ # - input ifdLevel is 2: filter out everything from the children of allTests
192+ # except for the ifdInputs attribute
193+ # - input ifdLevel is 3 or greater: return allTests
194+ optionalIfdTests = ifdLevel:
195+ pkgs.lib.optionalAttrs (ifdLevel > 1) (allTestsWithIfdInputs ifdLevel);
196+in
197+
198+pkgs.recurseIntoAttrs {
199+ haskellNixRoots = haskell-nix.haskellNixRoots' ifdLevel;
200+} // optionalIfdTests ifdLevel
53201
54202## more possible test cases
55203# 1. fully static linking