on iko/ghcjs-patch-master help sign in
Use suitable hackage state for index-state (#673)

Fixes #672 by using the first index-state that is > than desired index state. It also passes `--index-state` to `cabal v2-cconfigre` to make sure it cabal uses only the packages in the hackage file that are before the specified date. Fixes #540 by returning the `index-state` used back out of `cabalProject` in the same way `plan-nix` is returned.

commitdcadfa8ab486e8902fa153bd5c4b65b0cf5ce9e7 authorHamish Mackenzie <Hamish.Mackenzie@iohk.io> dateSat 13 Jun 2020, 01:03 (6 years ago) parent5abaf47
7 files changed+124−29
lib/call-cabal-project-to-nix.nix+51−10 lib/import-and-filter-project.nix+2−5 overlays/haskell.nix+18−6 test/call-cabal-project-to-nix/default.nix+6−4 test/call-stack-to-nix/default.nix+4−4 test/default.nix+4 test/index-state/default.nix+39
lib/call-cabal-project-to-nix.nix+51−10
@@ -122,14 +122,39 @@ let
122122 else builtins.trace ("Using latest index state" + (if name == null then "" else " for " + name) + "!")
123123 (pkgs.lib.last (builtins.attrNames index-state-hashes));
124124
125+in
126+ assert (if index-state-found == null
127+ then throw "No index state passed and none found in ${cabalProjectFileName}" else true);
128+
129+ assert (if index-sha256 == null && !(pkgs.lib.hasSuffix "Z" index-state-found)
130+ then throw "Index state found was ${index-state-found} and no `index-sha256` was provided. "
131+ "The index hash lookup code requires zulu time zone (ends in a Z)" else true);
132+
133+let
134+ # If a hash was not specified find a suitable cached index state to
135+ # use that will contain all the packages we need. By using the
136+ # first one after the desired index-state we can avoid recalculating
137+ # when new index-state-hashes are added.
138+ # See https://github.com/input-output-hk/haskell.nix/issues/672
139+ cached-index-state = if index-sha256 != null
140+ then index-state-found
141+ else
142+ let
143+ suitable-index-states =
144+ builtins.filter
145+ (s: s >= index-state-found) # This compare is why we need zulu time
146+ (builtins.attrNames index-state-hashes);
147+ in
148+ if builtins.length suitable-index-states == 0
149+ then index-state-found
150+ else pkgs.lib.head suitable-index-states;
151+
125152 # Lookup hash for the index state we found
126153 index-sha256-found = if index-sha256 != null
127154 then index-sha256
128− else index-state-hashes.${index-state-found} or null;
155+ else index-state-hashes.${cached-index-state} or null;
129156
130157in
131− assert (if index-state-found == null
132− then throw "No index state passed and none found in ${cabalProjectFileName}" else true);
133158 assert (if index-sha256-found == null
134159 then throw "Unknown index-state ${index-state-found}, the latest index-state I know about is ${pkgs.lib.last (builtins.attrNames index-state-hashes)}. You may need to update to a newer hackage.nix." else true);
135160
@@ -389,12 +414,23 @@ let
389414 ''}
390415 export SSL_CERT_FILE=${cacert}/etc/ssl/certs/ca-bundle.crt
391416 export GIT_SSL_CAINFO=${cacert}/etc/ssl/certs/ca-bundle.crt
392− HOME=${dotCabal {
393− inherit cabal-install nix-tools extra-hackage-tarballs;
394− index-state =
395− builtins.trace ("Using index-state: ${index-state-found}" + (if name == null then "" else " for " + name))
396− index-state-found;
397− sha256 = index-sha256-found; }} cabal v2-configure \
417+ HOME=${
418+ # This creates `.cabal` directory that is as it would have
419+ # been at the time `cached-index-state`. We may include
420+ # some packages that will be excluded by `index-state-found`
421+ # which is used by cabal (cached-index-state >= index-state-found).
422+ dotCabal {
423+ inherit cabal-install nix-tools extra-hackage-tarballs;
424+ index-state = cached-index-state;
425+ sha256 = index-sha256-found;
426+ }
427+ } cabal v2-configure \
428+ --index-state=${
429+ # Setting the desired `index-state` here in case it was not
430+ # from the cabal.project file. This will further restrict the
431+ # packages used by the solver (cached-index-state >= index-state-found).
432+ builtins.trace ("Using index-state: ${index-state-found}" + (if name == null then "" else " for " + name))
433+ index-state-found} \
398434 --with-ghc=${ghc.targetPrefix}ghc \
399435 --with-ghc-pkg=${ghc.targetPrefix}ghc-pkg \
400436 --enable-tests \
@@ -437,4 +473,9 @@ let
437473 # move pkgs.nix to default.nix ensure we can just nix `import` the result.
438474 mv $out${subDir'}/pkgs.nix $out${subDir'}/default.nix
439475 '');
440−in { projectNix = plan-nix; inherit src; inherit (fixedProject) sourceRepos; }
476+in {
477+ projectNix = plan-nix;
478+ index-state = index-state-found;
479+ inherit src;
480+ inherit (fixedProject) sourceRepos;
481+}
lib/import-and-filter-project.nix+2−5
@@ -19,9 +19,7 @@ let
1919 projectSubDir = pkgs.lib.strings.removePrefix "/" projectSubDir'; # Without /
2020 projectSubDir'' = if projectSubDir == "" then "" else projectSubDir + "/"; # With trailing /
2121 project = import "${projectNix}${projectSubDir'}";
22−in {
23− nix = projectNix;
24− pkgs = project // {
22+in project // {
2523 extras = hackage: let old = (project.extras hackage).packages; in {
2624 packages = pkgs.lib.attrsets.mapAttrs (name: value:
2725 if builtins.isFunction value
@@ -46,5 +44,4 @@ in {
4644 src = (pkgs.lib).mkDefault packageSrc;
4745 }) old;
4846 };
49− };
50−}
47+ }
overlays/haskell.nix+18−6
@@ -459,9 +459,12 @@ final: prev: {
459459 # plan-nix without building the project.
460460 cabalProject' =
461461 { ... }@args:
462− let plan = importAndFilterProject (callCabalProjectToNix args);
462+ let
463+ callProjectResults = callCabalProjectToNix args;
463464 in let pkg-set = mkCabalProjectPkgSet
464− { plan-pkgs = plan.pkgs;
465+ { plan-pkgs = importAndFilterProject {
466+ inherit (callProjectResults) projectNix sourceRepos src;
467+ };
465468 pkg-def-extras = args.pkg-def-extras or [];
466469 modules = (args.modules or [])
467470 ++ final.lib.optional (args ? ghcOverride || args ? ghc)
@@ -470,7 +473,12 @@ final: prev: {
470473 { compiler.nix-name = args.compiler-nix-name; };
471474 extra-hackages = args.extra-hackages or [];
472475 };
473− in addProjectAndPackageAttrs { inherit (pkg-set.config) hsPkgs; inherit pkg-set; plan-nix = plan.nix; };
476+ in addProjectAndPackageAttrs {
477+ inherit (pkg-set.config) hsPkgs;
478+ inherit pkg-set;
479+ plan-nix = callProjectResults.projectNix;
480+ inherit (callProjectResults) index-state;
481+ };
474482
475483 # Take `hsPkgs` from the `rawProject` and update all the packages and
476484 # components so they have a `.project` attribute and as well as
@@ -509,20 +517,24 @@ final: prev: {
509517
510518 stackProject' =
511519 { ... }@args:
512− let stack = importAndFilterProject (callStackToNix ({ inherit cache; } // args));
520+ let callProjectResults = callStackToNix ({ inherit cache; } // args);
513521 generatedCache = genStackCache {
514522 inherit (args) src;
515523 stackYaml = args.stackYaml or "stack.yaml";
516524 };
517525 cache = args.cache or generatedCache;
518526 in let pkg-set = mkStackPkgSet
519− { stack-pkgs = stack.pkgs;
527+ { stack-pkgs = importAndFilterProject callProjectResults;
520528 pkg-def-extras = (args.pkg-def-extras or []);
521529 modules = final.lib.singleton (mkCacheModule cache)
522530 ++ (args.modules or [])
523531 ++ final.lib.optional (args ? ghc) { ghc.package = args.ghc; };
524532 };
525− in addProjectAndPackageAttrs { inherit (pkg-set.config) hsPkgs; inherit pkg-set; stack-nix = stack.nix; };
533+ in addProjectAndPackageAttrs {
534+ inherit (pkg-set.config) hsPkgs;
535+ inherit pkg-set;
536+ stack-nix = callProjectResults.projectNix;
537+ };
526538
527539 stackProject = args: let p = stackProject' args;
528540 in p.hsPkgs // {
test/call-cabal-project-to-nix/default.nix+6−4
@@ -5,19 +5,21 @@ with stdenv.lib;
55let
66 # This test could use cabalProject', but it does so that it
77 # tests using callCabalProjectToNix and importAndFilterProject
8− plan = (importAndFilterProject (callCabalProjectToNix {
8+ callProjectResults = callCabalProjectToNix {
99 index-state = "2020-05-25T00:00:00Z";
1010 # reuse the cabal-simple test project
1111 src = testSrc "cabal-simple";
12− }));
12+ };
1313 pkgSet = mkCabalProjectPkgSet {
14− plan-pkgs = plan.pkgs;
14+ plan-pkgs = importAndFilterProject {
15+ inherit (callProjectResults) projectNix sourceRepos src;
16+ };
1517 };
1618 packages = pkgSet.config.hsPkgs;
1719
1820in recurseIntoAttrs {
1921 ifdInputs = {
20− plan-nix = plan.nix;
22+ plan-nix = callProjectResults.projectNix;
2123 };
2224 run = stdenv.mkDerivation {
2325 name = "call-cabal-project-to-nix-test";
test/call-stack-to-nix/default.nix+4−4
@@ -3,11 +3,11 @@
33with stdenv.lib;
44
55let
6− stack = importAndFilterProject (callStackToNix {
6+ callProjectResults = callStackToNix {
77 src = testSrc "stack-simple";
8− });
8+ };
99 pkgSet = mkStackPkgSet {
10− stack-pkgs = stack.pkgs;
10+ stack-pkgs = importAndFilterProject callProjectResults;
1111 pkg-def-extras = [];
1212 modules = [];
1313 };
@@ -15,7 +15,7 @@ let
1515
1616in recurseIntoAttrs {
1717 ifdInputs = {
18− stack-nix = stack.nix;
18+ stack-nix = callProjectResults.projectNix;
1919 };
2020 run = stdenv.mkDerivation {
2121 name = "callStackToNix-test";
test/default.nix+4
@@ -181,6 +181,10 @@ let
181181 # Pandoc does not build with ghcjs or ghc 8.10.1 yet (lookup-sha256 and fully-static build pandoc)
182182 lookup-sha256 = callTest ./lookup-sha256 {};
183183 fully-static = callTest ./fully-static { inherit (pkgs) buildPackages; };
184+ } // lib.optionalAttrs (pkgs.haskell-nix.defaultCompilerNixName != "ghc8101") {
185+ # This test makes a plan for building cabal 3.2 using index-states that will
186+ # never work with ghc 8.10.1
187+ index-state = callTest ./index-state {};
184188 };
185189
186190 # This is the same as allTests, but filter out all the key/vaules from the
test/index-state/default.nixnew file+39
@@ -0,0 +1,39 @@
1+# Test a package set
2+{ stdenv, testSrc, tool }:
3+
4+with stdenv.lib;
5+
6+let
7+ # The hackage-security 0.6.0.1 was uploaded at 2020-04-06T20:54:35Z
8+ # See https://hackage.haskell.org/package/hackage-security-0.6.0.1
9+ version-used-at = index-state: (tool "cabal" {
10+ version = "3.2.0.0";
11+ inherit index-state;
12+ }).project.hsPkgs.hackage-security.components.library.version;
13+ version-before = version-used-at "2020-04-06T20:54:34Z";
14+ version-after = version-used-at "2020-04-06T20:54:35Z";
15+
16+in
17+ stdenv.mkDerivation {
18+ name = "index-state-test";
19+
20+ buildCommand = ''
21+ if [[ "${version-before}" != "0.6.0.0" ]]; then
22+ echo 'Unexpected version ${version-before} (expected "0.6.0.0")'
23+ exit 0
24+ fi
25+ if [[ "${version-after}" != "0.6.0.1" ]]; then
26+ echo 'Unexpected version ${version-after} (expected "0.6.0.1")'
27+ exit 0
28+ fi
29+
30+ touch $out
31+ '';
32+
33+ meta.platforms = platforms.all;
34+
35+ passthru = {
36+ # Used for debugging with nix repl
37+ inherit project packages;
38+ };
39+ }