on iko/ghcjs-patch-master help sign in
Improve support for external Hackage repositories (#1370)
2576a94Hamish Mackenzie
@@ -1,6 +1,13 @@
1This file contains a summary of changes to Haskell.nix and `nix-tools`
1This file contains a summary of changes to Haskell.nix and `nix-tools`
2that will impact users.
2that will impact users.
3
3
4+## Feb 16, 2022
5+* Removed lookupSha256 argument from project functions.
6+ Pass a `sha256map` instead.
7+* Added better support for `repository` in `cabal.project`. These
8+ blocks should now work without the need for passing `extra-hackages` and
9+ `extra-hackage-tarballs`.
10+
4## Aug 6, 2021
11## Aug 6, 2021
5* Included dependencies of haskell.nix that were tracked in `nix/sources.json`
12* Included dependencies of haskell.nix that were tracked in `nix/sources.json`
6 as flake inputs (`flake.lock` replaces `nix/sources.json`).
13 as flake inputs (`flake.lock` replaces `nix/sources.json`).
lib/cabal-project-parser.nix+105−5
@@ -74,17 +74,21 @@ let
74 # --shar256: 003lm3pm0000hbfmii7xcdd9v20000flxf7gdl2pyxia7p014i8z
74 # --shar256: 003lm3pm0000hbfmii7xcdd9v20000flxf7gdl2pyxia7p014i8z
75 # will be trated like a field and returned here
75 # will be trated like a field and returned here
76 # (used in call-cabal-project-to-nix.nix to create a fixed-output derivation)
76 # (used in call-cabal-project-to-nix.nix to create a fixed-output derivation)
77− extractRepoData = cabalProjectFileName: lookupSha256: repo: {
77+ extractSourceRepoPackageData = cabalProjectFileName: sha256map: repo: {
78 url = repo.location;
78 url = repo.location;
79 ref = repo.tag;
79 ref = repo.tag;
80− sha256 = repo."--sha256" or (lookupSha256 repo);
80+ sha256 = repo."--sha256" or (
81+ if sha256map != null
82+ then sha256map."${repo.location}"."${repo.tag}"
83+ else null);
81 subdirs = if repo ? subdir
84 subdirs = if repo ? subdir
82 then pkgs.lib.filter (x: x != "") (pkgs.lib.splitString " " repo.subdir)
85 then pkgs.lib.filter (x: x != "") (pkgs.lib.splitString " " repo.subdir)
83 else ["."];
86 else ["."];
84 };
87 };
85
88
86 # Parse a source-repository-package and return data of `type: git` repositories
89 # Parse a source-repository-package and return data of `type: git` repositories
90+ # See tests/unit.nix for examples of input and output.
87− parseBlock = cabalProjectFileName: lookupSha256: block:
91+ parseSourceRepositoryPackageBlock = cabalProjectFileName: sha256map: block:
88 let
92 let
89 x = span (pkgs.lib.strings.hasPrefix " ") (pkgs.lib.splitString "\n" block);
93 x = span (pkgs.lib.strings.hasPrefix " ") (pkgs.lib.splitString "\n" block);
90 attrs = parseBlockLines x.fst;
94 attrs = parseBlockLines x.fst;
@@ -95,10 +99,106 @@ let
95 otherText = "\nsource-repository-package\n" + block;
99 otherText = "\nsource-repository-package\n" + block;
96 }
100 }
97 else {
101 else {
98− sourceRepo = extractRepoData cabalProjectFileName lookupSha256 attrs;
102+ sourceRepo = extractSourceRepoPackageData cabalProjectFileName sha256map attrs;
99 otherText = pkgs.lib.strings.concatStringsSep "\n" x.snd;
103 otherText = pkgs.lib.strings.concatStringsSep "\n" x.snd;
100 };
104 };
101
105
106+ parseSourceRepositoryPackages = cabalProjectFileName: sha256map: source-repo-override: projectFile:
107+ let
108+ blocks = pkgs.lib.splitString "\nsource-repository-package\n" ("\n" + projectFile);
109+ initialText = pkgs.lib.lists.take 1 blocks;
110+ repoBlocks = builtins.map (parseSourceRepositoryPackageBlock cabalProjectFileName sha256map) (pkgs.lib.lists.drop 1 blocks);
111+ overrideSourceRepo = sourceRepo: (source-repo-override.${sourceRepo.url} or (pkgs.lib.id)) sourceRepo;
112+ in {
113+ sourceRepos = pkgs.lib.lists.map (block: overrideSourceRepo block.sourceRepo) repoBlocks;
114+ otherText = pkgs.lib.strings.concatStringsSep "\n" (
115+ initialText
116+ ++ (builtins.map (x: x.otherText) repoBlocks));
117+ };
118+
119+ # Parse and replace repository
120+ # This works in a similar way to the `source-repository-package` but we are
121+ # able to simply replace the `repository` blocks with local `file:/nix/store` ones.
122+ # This works because `cabal configure` does not include any of the `/nix/sore/`
123+ # paths in the `plan.json` (so materialized plan-nix will still work as expeced).
124+ # See tests/unit.nix for examples of input and output.
125+ parseRepositoryBlock = cabalProjectFileName: sha256map: cabal-install: nix-tools: block:
126+ let
127+ lines = pkgs.lib.splitString "\n" block;
128+ # The first line will contain the repository name.
129+ x = span (pkgs.lib.strings.hasPrefix " ") (__tail lines);
130+ attrs = parseBlockLines x.fst;
131+ sha256 = attrs."--sha256" or (
132+ if sha256map != null
133+ then sha256map."${attrs.url}"
134+ else null);
135+ in rec {
136+ # This is `some-name` from the `repository some-name` line in the `cabal.project` file.
137+ name = __head lines;
138+ # The $HOME dir with `.cabal` sub directory after running `cabal new-update` to download the repository
139+ home =
140+ pkgs.evalPackages.runCommandLocal name ({
141+ nativeBuildInputs = [ cabal-install pkgs.evalPackages.curl nix-tools ];
142+ LOCALE_ARCHIVE = pkgs.lib.optionalString (pkgs.evalPackages.stdenv.buildPlatform.libc == "glibc") "${pkgs.evalPackages.glibcLocales}/lib/locale/locale-archive";
143+ LANG = "en_US.UTF-8";
144+ } // pkgs.lib.optionalAttrs (sha256 != null) {
145+ outputHashMode = "recursive";
146+ outputHashAlgo = "sha256";
147+ outputHash = sha256;
148+ }) ''
149+ mkdir -p $out/.cabal
150+ cat <<EOF > $out/.cabal/config
151+ repository ${name}
152+ url: ${attrs.url}
153+ ${pkgs.lib.optionalString (attrs ? secure) "secure: ${attrs.secure}"}
154+ ${pkgs.lib.optionalString (attrs ? root-keys) "root-keys: ${attrs.root-keys}"}
155+ ${pkgs.lib.optionalString (attrs ? key-threshold) "key-threshold: ${attrs.key-threshold}"}
156+ EOF
157+
158+ export SSL_CERT_FILE=${pkgs.evalPackages.cacert}/etc/ssl/certs/ca-bundle.crt
159+ mkdir -p $out/.cabal/packages/${name}
160+ HOME=$out cabal new-update ${name}
161+ '';
162+ # Output of hackage-to-nix
163+ hackage = import (
164+ pkgs.evalPackages.runCommandLocal ("hackage-to-nix-" + name) {
165+ nativeBuildInputs = [ cabal-install pkgs.evalPackages.curl nix-tools ];
166+ LOCALE_ARCHIVE = pkgs.lib.optionalString (pkgs.evalPackages.stdenv.buildPlatform.libc == "glibc") "${pkgs.evalPackages.glibcLocales}/lib/locale/locale-archive";
167+ LANG = "en_US.UTF-8";
168+ } ''
169+ mkdir -p $out
170+ hackage-to-nix $out ${home}/.cabal/packages/${name}/01-index.tar ${attrs.url}
171+ '');
172+ # Tarball info in the same format as `extra-hackage-tarballs` passed in to cabalProject
173+ tarball = {
174+ ${name} = home + "/.cabal/packages/${name}/01-index.tar.gz";
175+ };
176+ # Replacement `repository` block using `file:` uri and the remaining text (text that was not part of the attribute block).
177+ updatedText = ''
178+ repository ${name}
179+ url: file:${home + "/.cabal/packages/${name}"}
180+ secure: True
181+ root-keys:
182+ key-threshold: 0
183+ '' + pkgs.lib.strings.concatStringsSep "\n" x.snd;
184+ };
185+
186+ parseRepositories = cabalProjectFileName: sha256map: cabal-install: nix-tools: projectFile:
187+ let
188+ # This will leave the name of repository in the first line of each block
189+ blocks = pkgs.lib.splitString "\nrepository " ("\n" + projectFile);
190+ initialText = pkgs.lib.lists.take 1 blocks;
191+ repoBlocks = builtins.map (parseRepositoryBlock cabalProjectFileName sha256map cabal-install nix-tools) (pkgs.lib.lists.drop 1 blocks);
192+ in {
193+ extra-hackages = pkgs.lib.lists.map (block: block.hackage) repoBlocks;
194+ tarballs = pkgs.lib.lists.foldl' (x: block: x // block.tarball) {} repoBlocks;
195+ updatedText = pkgs.lib.strings.concatStringsSep "\n" (
196+ initialText
197+ ++ (builtins.map (x: x.updatedText) repoBlocks));
198+ };
199+
102in {
200in {
103− inherit parseIndexState parseBlockLines parseBlock;
201+ inherit parseIndexState parseSourceRepositoryPackages parseRepositories
202+ # These are only exposed for tests
203+ parseSourceRepositoryPackageBlock parseRepositoryBlock;
104}
204}
lib/call-cabal-project-to-nix.nix+25−23
@@ -30,13 +30,14 @@ in
30 # An alternative to adding `--sha256` comments into the
30 # An alternative to adding `--sha256` comments into the
31 # cabal.project file:
31 # cabal.project file:
32 # sha256map =
32 # sha256map =
33+ # { # For a `source-repository-package` use the `location` and `tag` as the key
33− # { "https://github.com/jgm/pandoc-citeproc"."0.17"
34+ # "https://github.com/jgm/pandoc-citeproc"."0.17"
34− # = "0dxx8cp2xndpw3jwiawch2dkrkp15mil7pyx7dvd810pwc22pm2q"; };
35+ # = "0dxx8cp2xndpw3jwiawch2dkrkp15mil7pyx7dvd810pwc22pm2q";
35−, lookupSha256 ?
36+ # # For a `repository` use the `url` as the key
36− if sha256map != null
37+ # "https://raw.githubusercontent.com/input-output-hk/hackage-overlay-ghcjs/bfc363b9f879c360e0a0460ec0c18ec87222ec32"
37− then { location, tag, ...}: sha256map."${location}"."${tag}"
38+ # = "sha256-g9xGgJqYmiczjxjQ5JOiK5KUUps+9+nlNGI/0SpSOpg=";
38− else _: null
39+ # };
39−, extra-hackage-tarballs ? []
40+, extra-hackage-tarballs ? {}
40, source-repo-override ? {} # Cabal seems to behave incoherently when
41, source-repo-override ? {} # Cabal seems to behave incoherently when
41 # two source-repository-package entries
42 # two source-repository-package entries
42 # provide the same packages, making it
43 # provide the same packages, making it
@@ -192,7 +193,7 @@ let
192
193
193 replaceSourceRepos = projectFile:
194 replaceSourceRepos = projectFile:
194 let
195 let
195− fetchRepo = fetchgit: repoData:
196+ fetchPackageRepo = fetchgit: repoData:
196 let
197 let
197 fetched =
198 fetched =
198 if repoData.sha256 != null
199 if repoData.sha256 != null
@@ -200,7 +201,7 @@ let
200 else
201 else
201 let drv = builtins.fetchGit { inherit (repoData) url ref; };
202 let drv = builtins.fetchGit { inherit (repoData) url ref; };
202 in __trace "WARNING: No sha256 found for source-repository-package ${repoData.url} ${repoData.ref} download may fail in restricted mode (hydra)"
203 in __trace "WARNING: No sha256 found for source-repository-package ${repoData.url} ${repoData.ref} download may fail in restricted mode (hydra)"
203− (__trace "Consider adding `--sha256: ${hashPath drv}` to the ${cabalProjectFileName} file or passing in a lookupSha256 argument"
204+ (__trace "Consider adding `--sha256: ${hashPath drv}` to the ${cabalProjectFileName} file or passing in a sha256map argument"
204 drv);
205 drv);
205 in {
206 in {
206 # Download the source-repository-package commit and add it to a minimal git
207 # Download the source-repository-package commit and add it to a minimal git
@@ -221,14 +222,13 @@ let
221 tag = "minimal";
222 tag = "minimal";
222 };
223 };
223
224
224− blocks = pkgs.lib.splitString "\nsource-repository-package\n" ("\n" + projectFile);
225+ # Parse the `source-repository-package` blocks
225− initialText = pkgs.lib.lists.take 1 blocks;
226+ sourceRepoPackageResult = pkgs.haskell-nix.haskellLib.parseSourceRepositoryPackages
226− repoBlocks = builtins.map (pkgs.haskell-nix.haskellLib.parseBlock cabalProjectFileName lookupSha256) (pkgs.lib.lists.drop 1 blocks);
227+ cabalProjectFileName sha256map source-repo-override projectFile;
227− overrideSourceRepo = sourceRepo: (source-repo-override.${sourceRepo.url} or (pkgs.lib.id)) sourceRepo;
228+
228− sourceRepoData = pkgs.lib.lists.map (x: overrideSourceRepo x.sourceRepo) repoBlocks;
229+ # Parse the `repository` blocks
229− otherText = pkgs.evalPackages.writeText "cabal.project" (pkgs.lib.strings.concatStringsSep "\n" (
230+ repoResult = pkgs.haskell-nix.haskellLib.parseRepositories
230− initialText
231+ cabalProjectFileName sha256map cabal-install nix-tools sourceRepoPackageResult.otherText;
231− ++ (builtins.map (x: x.otherText) repoBlocks)));
232
232
233 # we need the repository content twice:
233 # we need the repository content twice:
234 # * at eval time (below to build the fixed project file)
234 # * at eval time (below to build the fixed project file)
@@ -239,12 +239,13 @@ let
239 # on the target system would use, so that the derivation is unaffected
239 # on the target system would use, so that the derivation is unaffected
240 # and, say, a linux release build job can identify the derivation
240 # and, say, a linux release build job can identify the derivation
241 # as built by a darwin builder, and fetch it from a cache
241 # as built by a darwin builder, and fetch it from a cache
242− sourceReposEval = builtins.map (fetchRepo pkgs.evalPackages.fetchgit) sourceRepoData;
242+ sourceReposEval = builtins.map (fetchPackageRepo pkgs.evalPackages.fetchgit) sourceRepoPackageResult.sourceRepos;
243− sourceReposBuild = builtins.map (x: (fetchRepo pkgs.fetchgit x).fetched) sourceRepoData;
243+ sourceReposBuild = builtins.map (x: (fetchPackageRepo pkgs.fetchgit x).fetched) sourceRepoPackageResult.sourceRepos;
244 in {
244 in {
245 sourceRepos = sourceReposBuild;
245 sourceRepos = sourceReposBuild;
246+ inherit (repoResult) tarballs extra-hackages;
246 makeFixedProjectFile = ''
247 makeFixedProjectFile = ''
247− cp -f ${otherText} ./cabal.project
248+ cp -f ${pkgs.evalPackages.writeText "cabal.project" repoResult.updatedText} ./cabal.project
248 '' +
249 '' +
249 pkgs.lib.optionalString (builtins.length sourceReposEval != 0) (''
250 pkgs.lib.optionalString (builtins.length sourceReposEval != 0) (''
250 chmod +w -R ./cabal.project
251 chmod +w -R ./cabal.project
@@ -279,7 +280,7 @@ let
279
280
280 fixedProject =
281 fixedProject =
281 if rawCabalProject == null
282 if rawCabalProject == null
282− then { sourceRepos = []; makeFixedProjectFile = ""; replaceLocations = ""; }
283+ then { sourceRepos = []; tarballs = {}; extra-hackages = []; makeFixedProjectFile = ""; replaceLocations = ""; }
283 else replaceSourceRepos rawCabalProject;
284 else replaceSourceRepos rawCabalProject;
284
285
285 # The use of the actual GHC can cause significant problems:
286 # The use of the actual GHC can cause significant problems:
@@ -524,7 +525,8 @@ let
524 # some packages that will be excluded by `index-state-found`
525 # some packages that will be excluded by `index-state-found`
525 # which is used by cabal (cached-index-state >= index-state-found).
526 # which is used by cabal (cached-index-state >= index-state-found).
526 dotCabal {
527 dotCabal {
527− inherit cabal-install nix-tools extra-hackage-tarballs;
528+ inherit cabal-install nix-tools;
529+ extra-hackage-tarballs = fixedProject.tarballs // extra-hackage-tarballs;
528 index-state = cached-index-state;
530 index-state = cached-index-state;
529 sha256 = index-sha256-found;
531 sha256 = index-sha256-found;
530 }
532 }
@@ -610,5 +612,5 @@ in {
610 projectNix = plan-nix;
612 projectNix = plan-nix;
611 index-state = index-state-found;
613 index-state = index-state-found;
612 inherit src;
614 inherit src;
613− inherit (fixedProject) sourceRepos;
615+ inherit (fixedProject) sourceRepos extra-hackages;
614}
616}
lib/default.nix+1−1
@@ -275,7 +275,7 @@ in {
275
275
276 inherit (import ./cabal-project-parser.nix {
276 inherit (import ./cabal-project-parser.nix {
277 inherit pkgs;
277 inherit pkgs;
278− }) parseIndexState parseBlock;
278+ }) parseIndexState parseSourceRepositoryPackages parseRepositories parseSourceRepositoryPackageBlock parseRepositoryBlock;
279
279
280
280
281 cabalToNixpkgsLicense = import ./spdx/cabal.nix pkgs;
281 cabalToNixpkgsLicense = import ./spdx/cabal.nix pkgs;
lib/stack-cache-generator.nix+4−10
@@ -9,10 +9,6 @@
9 # sha256map =
9 # sha256map =
10 # { "https://github.com/jgm/pandoc-citeproc"."0.17"
10 # { "https://github.com/jgm/pandoc-citeproc"."0.17"
11 # = "0dxx8cp2xndpw3jwiawch2dkrkp15mil7pyx7dvd810pwc22pm2q"; };
11 # = "0dxx8cp2xndpw3jwiawch2dkrkp15mil7pyx7dvd810pwc22pm2q"; };
12−, lookupSha256 ?
13− if sha256map != null
14− then { location, tag, ...}: sha256map."${location}"."${tag}"
15− else _: null
16, branchMap ? null
12, branchMap ? null
17 # A way to specify in which branch a git commit can
13 # A way to specify in which branch a git commit can
18 # be found
14 # be found
@@ -85,12 +81,10 @@ in with pkgs.lib;
85concatMap (dep:
81concatMap (dep:
86 let
82 let
87 is-private = private dep.url;
83 is-private = private dep.url;
88− sha256 = if dep.sha256 != null
84+ sha256 =
89− then dep.sha256
85+ if dep.sha256 != null then dep.sha256
90− else lookupSha256 {
91− location = dep.url;
86+ else if sha256map != null then { location, tag, ...}: sha256map."${dep.url}"."${dep.rev}"
92− tag = dep.rev;
87+ else null;
93− };
94 branch = lookupBranch {
88 branch = lookupBranch {
95 location = dep.url;
89 location = dep.url;
96 tag = dep.rev;
90 tag = dep.rev;
mk-local-hackage-repo/default.nix+9−9
@@ -17,13 +17,13 @@
17pkgs:
17pkgs:
18{ name, index }:
18{ name, index }:
19
19
20−pkgs.evalPackages.runCommandLocal "hackage-repo-${name}" { nativeBuildInputs = [ pkgs.evalPackages.nix ]; } ''
20+pkgs.evalPackages.runCommandLocal "hackage-repo-${name}" {} ''
21mkdir -p $out
21mkdir -p $out
22export expires="4000-01-01T00:00:00Z"
22export expires="4000-01-01T00:00:00Z"
23
23
24ln -sf ${index} $out/01-index.tar.gz
24ln -sf ${index} $out/01-index.tar.gz
25−export index_md5=$(nix-hash --flat --type md5 ${index})
25+export index_md5=$(md5sum ${index} | awk '{ print $1 }')
26−export index_sha256=$(nix-hash --flat --type sha256 ${index})
26+export index_sha256=$(sha256sum ${index} | awk '{ print $1 }')
27${
27${
28 # When possible check the hash we calculate here against the `outputHash`
28 # When possible check the hash we calculate here against the `outputHash`
29 # of the index derivation (when the `extra-hackages` feature is used the index
29 # of the index derivation (when the `extra-hackages` feature is used the index
@@ -37,18 +37,18 @@ ${
37export index_length=$(stat --printf="%s" ${index})
37export index_length=$(stat --printf="%s" ${index})
38
38
39substituteAll ${./root.json} $out/root.json
39substituteAll ${./root.json} $out/root.json
40−export root_md5=$(nix-hash --flat --type md5 $out/root.json)
40+export root_md5=$(md5sum $out/root.json | awk '{ print $1 }')
41−export root_sha256=$(nix-hash --flat --type sha256 $out/root.json)
41+export root_sha256=$(sha256sum $out/root.json | awk '{ print $1 }')
42export root_length=$(stat --printf="%s" $out/root.json)
42export root_length=$(stat --printf="%s" $out/root.json)
43
43
44substituteAll ${./mirrors.json} $out/mirrors.json
44substituteAll ${./mirrors.json} $out/mirrors.json
45−export mirrors_md5=$(nix-hash --flat --type md5 $out/mirrors.json)
45+export mirrors_md5=$(md5sum $out/mirrors.json | awk '{ print $1 }')
46−export mirrors_sha256=$(nix-hash --flat --type sha256 $out/mirrors.json)
46+export mirrors_sha256=$(sha256sum $out/mirrors.json | awk '{ print $1 }')
47export mirrors_length=$(stat --printf="%s" $out/mirrors.json)
47export mirrors_length=$(stat --printf="%s" $out/mirrors.json)
48
48
49substituteAll ${./snapshot.json} $out/snapshot.json
49substituteAll ${./snapshot.json} $out/snapshot.json
50−export snapshot_md5=$(nix-hash --flat --type md5 $out/snapshot.json)
50+export snapshot_md5=$(md5sum $out/snapshot.json | awk '{ print $1 }')
51−export snapshot_sha256=$(nix-hash --flat --type sha256 $out/snapshot.json)
51+export snapshot_sha256=$(sha256sum $out/snapshot.json | awk '{ print $1 }')
52export snapshot_length=$(stat --printf="%s" $out/snapshot.json)
52export snapshot_length=$(stat --printf="%s" $out/snapshot.json)
53
53
54substituteAll ${./timestamp.json} $out/timestamp.json
54substituteAll ${./timestamp.json} $out/timestamp.json
modules/cabal-project.nix+2−8
@@ -105,15 +105,9 @@ in {
105 = "0dxx8cp2xndpw3jwiawch2dkrkp15mil7pyx7dvd810pwc22pm2q"; };
105 = "0dxx8cp2xndpw3jwiawch2dkrkp15mil7pyx7dvd810pwc22pm2q"; };
106 '';
106 '';
107 };
107 };
108− lookupSha256 = mkOption {
109− type = nullOr unspecified;
110− default = if config.sha256map != null
111− then { location, tag, ...}: config.sha256map.${location}.${tag}
112− else _: null;
113− };
114 extra-hackage-tarballs = mkOption {
108 extra-hackage-tarballs = mkOption {
115− type = nullOr (listOf unspecified);
109+ type = nullOr attrs;
116− default = [];
110+ default = {};
117 };
111 };
118 source-repo-override = mkOption {
112 source-repo-override = mkOption {
119 type = attrsOf (functionTo attrs);
113 type = attrsOf (functionTo attrs);
modules/stack-project.nix−6
@@ -72,12 +72,6 @@ with types;
72 = "0dxx8cp2xndpw3jwiawch2dkrkp15mil7pyx7dvd810pwc22pm2q"; };
72 = "0dxx8cp2xndpw3jwiawch2dkrkp15mil7pyx7dvd810pwc22pm2q"; };
73 '';
73 '';
74 };
74 };
75− lookupSha256 = mkOption {
76− type = nullOr unspecified;
77− default = if config.sha256map != null
78− then { location, tag, ...}: config.sha256map.${location}.${tag}
79− else _: null;
80− };
81 branchMap = mkOption {
75 branchMap = mkOption {
82 type = nullOr unspecified;
76 type = nullOr unspecified;
83 default = null;
77 default = null;
overlays/hackage-quirks.nix+2−3
@@ -43,10 +43,9 @@ in { haskell-nix = prev.haskell-nix // {
43 pandoc = {
43 pandoc = {
44 # Function that returns a sha256 string by looking up the location
44 # Function that returns a sha256 string by looking up the location
45 # and tag in a nested attrset
45 # and tag in a nested attrset
46− lookupSha256 = { location, tag, ... }:
46+ sha256map =
47 { "https://github.com/jgm/pandoc-citeproc"."0.17"
47 { "https://github.com/jgm/pandoc-citeproc"."0.17"
48− = "0dxx8cp2xndpw3jwiawch2dkrkp15mil7pyx7dvd810pwc22pm2q"; }
48+ = "0dxx8cp2xndpw3jwiawch2dkrkp15mil7pyx7dvd810pwc22pm2q"; };
49− ."${location}"."${tag}";
50 };
49 };
51
50
52 # See https://github.com/input-output-hk/haskell.nix/issues/948
51 # See https://github.com/input-output-hk/haskell.nix/issues/948
overlays/haskell.nix+12−13
@@ -189,8 +189,7 @@ final: prev: {
189 hackageTarball = { index-state, sha256, nix-tools ? final.haskell-nix.nix-tools, ... }:
189 hackageTarball = { index-state, sha256, nix-tools ? final.haskell-nix.nix-tools, ... }:
190 assert sha256 != null;
190 assert sha256 != null;
191 let at = builtins.replaceStrings [":"] [""] index-state; in
191 let at = builtins.replaceStrings [":"] [""] index-state; in
192− { name = "hackage.haskell.org-at-${at}";
193− index = final.evalPackages.fetchurl {
192+ { "hackage.haskell.org-at-${at}" = final.evalPackages.fetchurl {
194 name = "01-index.tar.gz-at-${at}";
193 name = "01-index.tar.gz-at-${at}";
195 url = "https://hackage.haskell.org/01-index.tar.gz";
194 url = "https://hackage.haskell.org/01-index.tar.gz";
196 downloadToTemp = true;
195 downloadToTemp = true;
@@ -204,10 +203,10 @@ final: prev: {
204 # Creates Cabal local repository from { name, index } set.
203 # Creates Cabal local repository from { name, index } set.
205 mkLocalHackageRepo = import ../mk-local-hackage-repo final;
204 mkLocalHackageRepo = import ../mk-local-hackage-repo final;
206
205
207− dotCabal = { index-state, sha256, cabal-install, extra-hackage-tarballs ? [], ... }@args:
206+ dotCabal = { index-state, sha256, cabal-install, extra-hackage-tarballs ? {}, ... }@args:
208 let
207 let
209− allTarballs = [ (hackageTarball args) ] ++ extra-hackage-tarballs;
208+ allTarballs = hackageTarball args // extra-hackage-tarballs;
210− allNames = final.lib.concatMapStringsSep "-" (tarball: tarball.name) allTarballs;
209+ allNames = final.lib.concatStringsSep "-" (builtins.attrNames allTarballs);
211 # Main Hackage index-state is embedded in its name and thus will propagate to
210 # Main Hackage index-state is embedded in its name and thus will propagate to
212 # dotCabalName anyway.
211 # dotCabalName anyway.
213 dotCabalName = "dot-cabal-" + allNames;
212 dotCabalName = "dot-cabal-" + allNames;
@@ -217,10 +216,10 @@ final: prev: {
217 mkdir -p $out/.cabal
216 mkdir -p $out/.cabal
218 cat <<EOF > $out/.cabal/config
217 cat <<EOF > $out/.cabal/config
219 ${final.lib.concatStrings (
218 ${final.lib.concatStrings (
220− map (tarball:
219+ final.lib.mapAttrsToList (name: index:
221 ''
220 ''
222− repository ${tarball.name}
221+ repository ${name}
223− url: file:${mkLocalHackageRepo tarball}
222+ url: file:${mkLocalHackageRepo { inherit name index; }}
224 secure: True
223 secure: True
225 root-keys:
224 root-keys:
226 key-threshold: 0
225 key-threshold: 0
@@ -231,13 +230,13 @@ final: prev: {
231
230
232 # All repositories must be mkdir'ed before calling new-update on any repo,
231 # All repositories must be mkdir'ed before calling new-update on any repo,
233 # otherwise it fails.
232 # otherwise it fails.
234− ${final.lib.concatStrings (map ({ name, ... }: ''
233+ ${final.lib.concatStrings (map (name: ''
235 mkdir -p $out/.cabal/packages/${name}
234 mkdir -p $out/.cabal/packages/${name}
236− '') allTarballs)}
235+ '') (builtins.attrNames allTarballs))}
237
236
238− ${final.lib.concatStrings (map ({ name, ... }: ''
237+ ${final.lib.concatStrings (map (name: ''
239 HOME=$out cabal new-update ${name}
238 HOME=$out cabal new-update ${name}
240− '') allTarballs)}
239+ '') (builtins.attrNames allTarballs))}
241 '';
240 '';
242
241
243 # Some of features of haskell.nix rely on using a hackage index
242 # Some of features of haskell.nix rely on using a hackage index
@@ -515,7 +514,7 @@ final: prev: {
515 ++ final.lib.optional (args.ghcOverride != null || args.ghc != null)
514 ++ final.lib.optional (args.ghcOverride != null || args.ghc != null)
516 { ghc.package = if args.ghcOverride != null then args.ghcOverride else args.ghc; }
515 { ghc.package = if args.ghcOverride != null then args.ghcOverride else args.ghc; }
517 ++ [ { compiler.nix-name = final.lib.mkForce args.compiler-nix-name; } ];
516 ++ [ { compiler.nix-name = final.lib.mkForce args.compiler-nix-name; } ];
518− extra-hackages = args.extra-hackages or [];
517+ extra-hackages = args.extra-hackages or [] ++ callProjectResults.extra-hackages;
519 };
518 };
520
519
521 project = addProjectAndPackageAttrs rec {
520 project = addProjectAndPackageAttrs rec {
test/default.nix+3−2
@@ -152,7 +152,7 @@ let
152 # An empty list means success.
152 # An empty list means success.
153 unitTests =
153 unitTests =
154 let
154 let
155− tests = haskell-nix.callPackage ./unit.nix {};
155+ tests = haskell-nix.callPackage ./unit.nix { inherit compiler-nix-name; };
156 testsFailedEcho = lib.concatMapStringsSep "\n" (t: "echo ${t.name} failed") tests;
156 testsFailedEcho = lib.concatMapStringsSep "\n" (t: "echo ${t.name} failed") tests;
157 testsFinalLine = if builtins.length tests == 0 then "\ntouch $out" else "\nexit 1";
157 testsFinalLine = if builtins.length tests == 0 then "\ntouch $out" else "\nexit 1";
158 testsScript = testsFailedEcho + testsFinalLine;
158 testsScript = testsFailedEcho + testsFinalLine;
@@ -186,11 +186,12 @@ let
186 stack-source-repo = callTest ./stack-source-repo { inherit compiler-nix-name; };
186 stack-source-repo = callTest ./stack-source-repo { inherit compiler-nix-name; };
187 cabal-doctests = callTest ./cabal-doctests { inherit util compiler-nix-name; };
187 cabal-doctests = callTest ./cabal-doctests { inherit util compiler-nix-name; };
188 extra-hackage = callTest ./extra-hackage { inherit compiler-nix-name; };
188 extra-hackage = callTest ./extra-hackage { inherit compiler-nix-name; };
189+ ghcjs-overlay = callTest ./ghcjs-overlay { inherit compiler-nix-name; };
189 hls-cabal = callTest ./haskell-language-server/cabal.nix { inherit compiler-nix-name; };
190 hls-cabal = callTest ./haskell-language-server/cabal.nix { inherit compiler-nix-name; };
190 hls-stack = callTest ./haskell-language-server/stack.nix { inherit compiler-nix-name; };
191 hls-stack = callTest ./haskell-language-server/stack.nix { inherit compiler-nix-name; };
191 cabal-hpack = callTest ./cabal-hpack { inherit util compiler-nix-name; };
192 cabal-hpack = callTest ./cabal-hpack { inherit util compiler-nix-name; };
192 index-state = callTest ./index-state { inherit compiler-nix-name; };
193 index-state = callTest ./index-state { inherit compiler-nix-name; };
193− lookup-sha256 = callTest ./lookup-sha256 { inherit compiler-nix-name; };
194+ sha256map = callTest ./sha256map { inherit compiler-nix-name; };
194 # fully-static = callTest ./fully-static { inherit (pkgs) buildPackages; };
195 # fully-static = callTest ./fully-static { inherit (pkgs) buildPackages; };
195 shell-for = callTest ./shell-for { inherit compiler-nix-name; };
196 shell-for = callTest ./shell-for { inherit compiler-nix-name; };
196 cabal-22 = callTest ./cabal-22 { inherit util compiler-nix-name; };
197 cabal-22 = callTest ./cabal-22 { inherit util compiler-nix-name; };
test/extra-hackage/default.nix+3−4
@@ -6,9 +6,8 @@ let
6
6
7 hackage = import ./hackage;
7 hackage = import ./hackage;
8
8
9− tarball = {
9+ tarballs = {
10− name = "extra-hackage-demo";
10+ extra-hackage-demo = ./01-index.tar.gz;
11− index = ./01-index.tar.gz;
12 };
11 };
13
12
14 demo-src = ./external-package-demo-0.1.0.0.tar.gz;
13 demo-src = ./external-package-demo-0.1.0.0.tar.gz;
@@ -18,7 +17,7 @@ let
18 src = testSrc "extra-hackage/external-package-user";
17 src = testSrc "extra-hackage/external-package-user";
19
18
20 extra-hackages = [ hackage ];
19 extra-hackages = [ hackage ];
21− extra-hackage-tarballs = [ tarball ];
20+ extra-hackage-tarballs = tarballs;
22
21
23 modules = [
22 modules = [
24 # To prevent nix-build from trying to download it from the
23 # To prevent nix-build from trying to download it from the
test/extra-hackage/external-package-user/cabal.project+6−2
@@ -1,4 +1,8 @@
1packages: *.cabal
1packages: *.cabal
2
2
3+-- Including `repository` here now actually causes haskell.nix to try
4+-- to download the repository. Luckily this test still works with this
5+-- commented out.
6+-- See the ghcjs-overlays test for an example of how to use `repository` blocks.
3−repository local
7+-- repository local
4− url: http://127.0.0.1:7777
8+-- url: http://127.0.0.1:7777
test/ghcjs-overlay/CHANGELOG.mdnew file+5
@@ -0,0 +1,5 @@
1+# Revision history for external-package-user
2+
3+## 0.1.0.0 -- YYYY-mm-dd
4+
5+* First version. Released on an unsuspecting world.
test/ghcjs-overlay/Main.hsnew file+8
@@ -0,0 +1,8 @@
1+module Main where
2+
3+import qualified MyLib (someFunc)
4+
5+main :: IO ()
6+main = do
7+ putStrLn "Hello, Haskell!"
8+ MyLib.someFunc
test/ghcjs-overlay/MyLib.hsnew file+4
@@ -0,0 +1,4 @@
1+module MyLib (someFunc) where
2+
3+someFunc :: IO ()
4+someFunc = putStrLn "someFunc"
test/ghcjs-overlay/Setup.hsnew file+2
@@ -0,0 +1,2 @@
1+import Distribution.Simple
2+main = defaultMain
test/ghcjs-overlay/cabal.projectnew file+9
@@ -0,0 +1,9 @@
1+packages: *.cabal
2+
3+repository ghcjs-overlay
4+ url: https://raw.githubusercontent.com/input-output-hk/hackage-overlay-ghcjs/bfc363b9f879c360e0a0460ec0c18ec87222ec32
5+ secure: True
6+ root-keys:
7+ key-threshold: 0
8+ --sha256: sha256-g9xGgJqYmiczjxjQ5JOiK5KUUps+9+nlNGI/0SpSOpg=
9+
test/ghcjs-overlay/default.nixnew file+52
@@ -0,0 +1,52 @@
1+{ stdenv, lib, cabalProject', haskellLib, recurseIntoAttrs, testSrc, compiler-nix-name }:
2+
3+with lib;
4+
5+let
6+ project = cabalProject' {
7+ src = testSrc "ghcjs-overlay";
8+ inherit compiler-nix-name;
9+ # Alternative to the --sha256 comment in cabal.project
10+ # sha256map = {
11+ # "https://raw.githubusercontent.com/input-output-hk/hackage-overlay-ghcjs/bfc363b9f879c360e0a0460ec0c18ec87222ec32" =
12+ # "sha256-g9xGgJqYmiczjxjQ5JOiK5KUUps+9+nlNGI/0SpSOpg=";
13+ # };
14+ };
15+ packages = project.hsPkgs;
16+
17+in recurseIntoAttrs {
18+ ifdInputs = {
19+ inherit (project) plan-nix;
20+ };
21+ run = stdenv.mkDerivation {
22+ name = "ghcjs-overlay-test";
23+
24+ buildCommand = ''
25+ exe="${packages.ghcjs-overlay-test.components.exes.ghcjs-overlay-test.exePath}"
26+ size=$(command stat --format '%s' "$exe")
27+ printf "size of executable $exe is $size. \n" >& 2
28+ # fixme: run on target platform when cross-compiled
29+ printf "checking whether executable runs... " >& 2
30+ cat ${haskellLib.check packages.ghcjs-overlay-test.components.exes.ghcjs-overlay-test}/test-stdout
31+ '' + (if stdenv.hostPlatform.isMusl
32+ then ''
33+ printf "checking that executable is statically linked... " >& 2
34+ (ldd $exe 2>&1 || true) | grep -i "not a"
35+ ''
36+ else
37+ # Skip this on aarch as we do not have an `ldd` tool
38+ optionalString (!stdenv.hostPlatform.isAarch32 && !stdenv.hostPlatform.isAarch64) (''
39+ printf "checking that executable is dynamically linked to system libraries... " >& 2
40+ '' + optionalString stdenv.isLinux ''
41+ ldd $exe | grep libpthread
42+ '' + optionalString stdenv.isDarwin ''
43+ otool -L $exe |grep .dylib
44+ '')) + ''
45+ touch $out
46+ '';
47+ meta.platforms = platforms.all;
48+ passthru = {
49+ inherit project;
50+ };
51+ };
52+}
test/ghcjs-overlay/ghcjs-overlay-test.cabalnew file+21
@@ -0,0 +1,21 @@
1+cabal-version: 2.4
2+name: ghcjs-overlay-test
3+version: 0.1.0.0
4+synopsis: User package
5+description: Uses ghcjs-overlay to get patched double-conversion
6+license: BSD-3-Clause
7+author: Hamish Mackenzie
8+maintainer: Hamish.K.Mackenzie@gmail.com
9+extra-source-files: CHANGELOG.md
10+
11+library
12+ exposed-modules: MyLib
13+ build-depends: base < 5,
14+ double-conversion ==2.0.2.0
15+ default-language: Haskell2010
16+
17+executable ghcjs-overlay-test
18+ main-is: Main.hs
19+ other-modules: MyLib
20+ build-depends: base, ghcjs-overlay-test
21+ default-language: Haskell2010
test/lookup-sha256/default.nix → test/sha256map/default.nixrenamed+2−3
@@ -11,10 +11,9 @@
11 version = "2.9.2.1";
11 version = "2.9.2.1";
12 # Function that returns a sha256 string by looking up the location
12 # Function that returns a sha256 string by looking up the location
13 # and tag in a nested attrset
13 # and tag in a nested attrset
14− lookupSha256 = { location, tag, ... }:
14+ sha256map =
15 { "https://github.com/jgm/pandoc-citeproc"."0.17"
15 { "https://github.com/jgm/pandoc-citeproc"."0.17"
16− = "0dxx8cp2xndpw3jwiawch2dkrkp15mil7pyx7dvd810pwc22pm2q"; }
16+ = "0dxx8cp2xndpw3jwiawch2dkrkp15mil7pyx7dvd810pwc22pm2q"; };
17− ."${location}"."${tag}";
18 cabalProjectLocal = ''
17 cabalProjectLocal = ''
19 allow-newer: *:base
18 allow-newer: *:base
20 '';
19 '';
test/unit.nix+124−5
@@ -1,4 +1,4 @@
1−{ pkgs, lib, haskellLib }:
1+{ pkgs, lib, haskellLib, compiler-nix-name }:
2
2
3let
3let
4 emptyConfig = {
4 emptyConfig = {
@@ -58,7 +58,7 @@ lib.runTests {
58 };
58 };
59
59
60 testParseBlock1 = {
60 testParseBlock1 = {
61− expr = __toJSON (haskellLib.parseBlock "cabal.project" (_: null) ''
61+ expr = __toJSON (haskellLib.parseSourceRepositoryPackageBlock "cabal.project" {} ''
62 type: git
62 type: git
63 location: https://github.com/input-output-hk/haskell.nix.git
63 location: https://github.com/input-output-hk/haskell.nix.git
64 tag: 487eea1c249537d34c27f6143dff2b9d5586c657
64 tag: 487eea1c249537d34c27f6143dff2b9d5586c657
@@ -72,7 +72,7 @@ lib.runTests {
72 };
72 };
73
73
74 testParseBlock2 = {
74 testParseBlock2 = {
75− expr = __toJSON (haskellLib.parseBlock "cabal.project" (_: null) ''
75+ expr = __toJSON (haskellLib.parseSourceRepositoryPackageBlock "cabal.project" {} ''
76 type: git
76 type: git
77 location: https://github.com/input-output-hk/haskell.nix.git
77 location: https://github.com/input-output-hk/haskell.nix.git
78 tag: 487eea1c249537d34c27f6143dff2b9d5586c657
78 tag: 487eea1c249537d34c27f6143dff2b9d5586c657
@@ -87,7 +87,7 @@ lib.runTests {
87 };
87 };
88
88
89 testParseBlock3 = {
89 testParseBlock3 = {
90− expr = __toJSON (haskellLib.parseBlock "cabal.project" (_: null) ''
90+ expr = __toJSON (haskellLib.parseSourceRepositoryPackageBlock "cabal.project" {} ''
91 type: git
91 type: git
92 location: https://github.com/input-output-hk/haskell.nix.git
92 location: https://github.com/input-output-hk/haskell.nix.git
93 tag: 487eea1c249537d34c27f6143dff2b9d5586c657
93 tag: 487eea1c249537d34c27f6143dff2b9d5586c657
@@ -102,7 +102,7 @@ lib.runTests {
102 };
102 };
103
103
104 testParseBlock4 = {
104 testParseBlock4 = {
105− expr = __toJSON (haskellLib.parseBlock "cabal.project" (_: null) ''
105+ expr = __toJSON (haskellLib.parseSourceRepositoryPackageBlock "cabal.project" {} ''
106 type: git
106 type: git
107 location: https://github.com/input-output-hk/haskell.nix.git
107 location: https://github.com/input-output-hk/haskell.nix.git
108 tag: 487eea1c249537d34c27f6143dff2b9d5586c657
108 tag: 487eea1c249537d34c27f6143dff2b9d5586c657
@@ -117,4 +117,123 @@ lib.runTests {
117 sourceRepo = testRepoData // { subdirs = ["dir1" "dir2"]; };
117 sourceRepo = testRepoData // { subdirs = ["dir1" "dir2"]; };
118 };
118 };
119 };
119 };
120+
121+ testParseRepositoryBlock = {
122+ expr = __toJSON (haskellLib.parseRepositoryBlock "cabal.project" {}
123+ pkgs.evalPackages.haskell-nix.cabal-install.${compiler-nix-name}
124+ pkgs.evalPackages.haskell-nix.nix-tools.${compiler-nix-name} ''
125+ ghcjs-overlay
126+ url: https://raw.githubusercontent.com/input-output-hk/hackage-overlay-ghcjs/bfc363b9f879c360e0a0460ec0c18ec87222ec32
127+ secure: True
128+ root-keys:
129+ key-threshold: 0
130+ --sha256: sha256-g9xGgJqYmiczjxjQ5JOiK5KUUps+9+nlNGI/0SpSOpg=
131+ -- end of block
132+ '');
133+ expected = __toJSON {
134+ name = "ghcjs-overlay";
135+ updatedText = ''
136+ repository ghcjs-overlay
137+ url: file:/nix/store/0lx8536b53bqssqzzbyzi22j117a7q2g-ghcjs-overlay/.cabal/packages/ghcjs-overlay
138+ secure: True
139+ root-keys:
140+ key-threshold: 0
141+ -- end of block
142+ '';
143+ home = "/nix/store/0lx8536b53bqssqzzbyzi22j117a7q2g-ghcjs-overlay";
144+ tarball = {
145+ ghcjs-overlay = "/nix/store/0lx8536b53bqssqzzbyzi22j117a7q2g-ghcjs-overlay/.cabal/packages/ghcjs-overlay/01-index.tar.gz";
146+ };
147+ hackage = {
148+ Cabal = {
149+ "3.2.1.0" = {
150+ revisions = {
151+ default = "/nix/store/3ndxx3k43gmjkfl1qn1x39g15hz5amad-Cabal-3.2.1.0-r0-2b5309e942658e3b16e6938115867538e70a647d98e3dc967f2be20d6b886e61.nix";
152+ r0 = "/nix/store/3ndxx3k43gmjkfl1qn1x39g15hz5amad-Cabal-3.2.1.0-r0-2b5309e942658e3b16e6938115867538e70a647d98e3dc967f2be20d6b886e61.nix";
153+ };
154+ sha256 = "826970f742b63d751f6fe3be7f862b7b1e419ddfafef3014c01de54f12874a4a";
155+ };
156+ };
157+ basement = {
158+ "0.0.12"= {
159+ revisions = {
160+ default = "/nix/store/3h1xwcij240kj243f23siw3p30hdbnrj-basement-0.0.12-r0-600669787199915545f99754496f13f955203b94dbb31de50093362c03367bb7.nix";
161+ r0 = "/nix/store/3h1xwcij240kj243f23siw3p30hdbnrj-basement-0.0.12-r0-600669787199915545f99754496f13f955203b94dbb31de50093362c03367bb7.nix";
162+ };
163+ sha256 = "cf8f96fd92438739a516881abb7e14747118e82a12634d44acc83173fb87f535";
164+ };
165+ };
166+ clock = {
167+ "0.8.2" = {
168+ revisions = {
169+ default = "/nix/store/mdsf1fgbpi4m1yvsg5z8z4hk5w7i63x7-clock-0.8.2-r0-2a8441d9f531bb51bb1806e56e9e9a43e5f0214faea4f31219c15120128ca43a.nix";
170+ r0 = "/nix/store/mdsf1fgbpi4m1yvsg5z8z4hk5w7i63x7-clock-0.8.2-r0-2a8441d9f531bb51bb1806e56e9e9a43e5f0214faea4f31219c15120128ca43a.nix";
171+ };
172+ sha256 = "57715a01df74568c638f1138b53642094de420bafd519e9f53ec7fe92876121e";
173+ };
174+ };
175+ cryptonite = {
176+ "0.29" = {
177+ revisions = {
178+ default = "/nix/store/i84rvw53j9b6p53dalg6xq85blrkrk01-cryptonite-0.29-r0-231db2acdaefc978865af9b72a6e65c4ebc70238174a7ad9076d68900f3d866d.nix";
179+ r0 = "/nix/store/i84rvw53j9b6p53dalg6xq85blrkrk01-cryptonite-0.29-r0-231db2acdaefc978865af9b72a6e65c4ebc70238174a7ad9076d68900f3d866d.nix";
180+ };
181+ sha256 = "f104836bdaeed5243ff7e9fc0757d7255778f0af22976eef2b7789e7e1094283";
182+ };
183+ };
184+ double-conversion = {
185+ "2.0.2.0" = {
186+ revisions = {
187+ default = "/nix/store/cb41xbmf6abcq30sj2a1b00qim8nyhqx-double-conversion-2.0.2.0-r0-698f94e66b6263a1049b56ede47aa48e224c764f345c3130265742513443595b.nix";
188+ r0 = "/nix/store/cb41xbmf6abcq30sj2a1b00qim8nyhqx-double-conversion-2.0.2.0-r0-698f94e66b6263a1049b56ede47aa48e224c764f345c3130265742513443595b.nix";
189+ };
190+ sha256 = "67c83bf4619624ef6b950578664cbcd3bc12eaed0d7a387997db5e0ba29fb140";
191+ };
192+ };
193+ foundation = {
194+ "0.0.26.1" = {
195+ revisions = {
196+ default = "/nix/store/5vw12rxa3as8b82kz1arddwzs45fzj6q-foundation-0.0.26.1-r0-9a2f63a33dc6b3c1425c4755522b8e619d04fdfcfef72e358155b965b28745a8.nix";
197+ r0 = "/nix/store/5vw12rxa3as8b82kz1arddwzs45fzj6q-foundation-0.0.26.1-r0-9a2f63a33dc6b3c1425c4755522b8e619d04fdfcfef72e358155b965b28745a8.nix";
198+ };
199+ sha256 = "3c588f6bcf875762ac18b03b17a7ee3c0c60c8e2c884c0192269b0a97e89d526";
200+ };
201+ };
202+ network = {
203+ "3.1.2.1" = {
204+ revisions = {
205+ default = "/nix/store/sfc02hqr02pa3rwhha1skvlkiwmgvsf7-network-3.1.2.1-r0-ed4b1bb733613df5a2ebecd5533d08f20bacb0dc59ed207fd4b4670fe718713f.nix";
206+ r0 = "/nix/store/sfc02hqr02pa3rwhha1skvlkiwmgvsf7-network-3.1.2.1-r0-ed4b1bb733613df5a2ebecd5533d08f20bacb0dc59ed207fd4b4670fe718713f.nix";
207+ };
208+ sha256 = "21869fd942cb9996ba26ba9418cdd44ac869f81caba08e5a2b2cdfe792ae4518";
209+ };
210+ "3.1.2.5" = {
211+ revisions = {
212+ default = "/nix/store/rrh5f3hb8g5bwgd6y7lwfky3nrgsg5b2-network-3.1.2.5-r0-433a5e076aaa8eb3e4158abae78fb409c6bd754e9af99bc2e87583d2bcd8404a.nix";
213+ r0 = "/nix/store/rrh5f3hb8g5bwgd6y7lwfky3nrgsg5b2-network-3.1.2.5-r0-433a5e076aaa8eb3e4158abae78fb409c6bd754e9af99bc2e87583d2bcd8404a.nix";
214+ };
215+ sha256 = "ee914e9b43bfb0f415777eb0473236803b14a35d48f6172079260c92c6ceb335";
216+ };
217+ };
218+ terminal-size = {
219+ "0.3.2.1" = {
220+ revisions = {
221+ default = "/nix/store/k9gk020ygp6j94sa3xv46fkgrc8jl5zn-terminal-size-0.3.2.1-r0-7b2d8e0475a46961d07ddfb91dee618de70eff55d9ba0402ebeac1f9dcf9b18b.nix";
222+ r0 = "/nix/store/k9gk020ygp6j94sa3xv46fkgrc8jl5zn-terminal-size-0.3.2.1-r0-7b2d8e0475a46961d07ddfb91dee618de70eff55d9ba0402ebeac1f9dcf9b18b.nix";
223+ };
224+ sha256 = "8e4fbfea182f3bf5769744196ca88bb2cb1c80caa617debe34336f90db27131e";
225+ };
226+ };
227+ unix-compat = {
228+ "0.5.3" = {
229+ revisions = {
230+ default = "/nix/store/mc1vh6wzg0vp1c1srxrqmpv9fsqay6dw-unix-compat-0.5.3-r0-9c6d68f9afb5baa6be55e8415dd401835ce0d4dfc2090f1c169fcd61c152ebac.nix";
231+ r0 = "/nix/store/mc1vh6wzg0vp1c1srxrqmpv9fsqay6dw-unix-compat-0.5.3-r0-9c6d68f9afb5baa6be55e8415dd401835ce0d4dfc2090f1c169fcd61c152ebac.nix";
232+ };
233+ sha256 = "2fe56781422d5caf47dcbbe82c998bd33f429f8c7093483fad36cd2d31dbdceb";
234+ };
235+ };
236+ };
237+ };
238+ };
120}
239}