on iko/ghcjs-patch-master help sign in
Avoid filtering repo to just 01-index.tar.gz file (#1432)
e81f3bbHamish Mackenzie
lib/cabal-project-parser.nix+34−27
@@ -122,7 +122,7 @@ let
122 # This works because `cabal configure` does not include any of the `/nix/sore/`
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).
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.
124 # See tests/unit.nix for examples of input and output.
125− parseRepositoryBlock = cabalProjectFileName: sha256map: cabal-install: nix-tools: block:
125+ parseRepositoryBlock = cabalProjectFileName: sha256map: inputMap: cabal-install: nix-tools: block:
126 let
126 let
127 lines = pkgs.lib.splitString "\n" block;
127 lines = pkgs.lib.splitString "\n" block;
128 # The first line will contain the repository name.
128 # The first line will contain the repository name.
@@ -135,9 +135,27 @@ let
135 in rec {
135 in rec {
136 # This is `some-name` from the `repository some-name` line in the `cabal.project` file.
136 # This is `some-name` from the `repository some-name` line in the `cabal.project` file.
137 name = __head lines;
137 name = __head lines;
138− # The $HOME dir with `.cabal` sub directory after running `cabal new-update` to download the repository
138+ # The $HOME/.cabal/packages/${name} after running `cabal v2-update` to download the repository
139− home =
139+ repoContents = if inputMap ? ${attrs.url}
140+ # If there is an input use it to make `file:` url and create a suitable `.cabal/packages/${name}` directory
141+ then pkgs.evalPackages.runCommand name ({
142+ nativeBuildInputs = [ cabal-install ];
143+ preferLocalBuild = true;
144+ }) ''
145+ HOME=$(mktemp -d)
146+ mkdir -p $HOME/.cabal/packages/${name}
147+ cat <<EOF > $HOME/.cabal/config
148+ repository ${name}
149+ url: file:${inputMap.${attrs.url}}
150+ ${pkgs.lib.optionalString (attrs ? secure) "secure: ${attrs.secure}"}
151+ ${pkgs.lib.optionalString (attrs ? root-keys) "root-keys: ${attrs.root-keys}"}
152+ ${pkgs.lib.optionalString (attrs ? key-threshold) "key-threshold: ${attrs.key-threshold}"}
153+ EOF
154+
155+ cabal v2-update ${name}
156+ cp -r $HOME/.cabal/packages/${name} $out
157+ ''
140− pkgs.evalPackages.runCommand name ({
158+ else pkgs.evalPackages.runCommand name ({
141 nativeBuildInputs = [ cabal-install pkgs.evalPackages.curl nix-tools ];
159 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";
160 LOCALE_ARCHIVE = pkgs.lib.optionalString (pkgs.evalPackages.stdenv.buildPlatform.libc == "glibc") "${pkgs.evalPackages.glibcLocales}/lib/locale/locale-archive";
143 LANG = "en_US.UTF-8";
161 LANG = "en_US.UTF-8";
@@ -147,8 +165,9 @@ let
147 outputHashAlgo = "sha256";
165 outputHashAlgo = "sha256";
148 outputHash = sha256;
166 outputHash = sha256;
149 }) ''
167 }) ''
168+ HOME=$(mktemp -d)
150− mkdir -p $out/.cabal
169+ mkdir -p $HOME/.cabal/packages/${name}
151− cat <<EOF > $out/.cabal/config
170+ cat <<EOF > $HOME/.cabal/config
152 repository ${name}
171 repository ${name}
153 url: ${attrs.url}
172 url: ${attrs.url}
154 ${pkgs.lib.optionalString (attrs ? secure) "secure: ${attrs.secure}"}
173 ${pkgs.lib.optionalString (attrs ? secure) "secure: ${attrs.secure}"}
@@ -157,8 +176,8 @@ let
157 EOF
176 EOF
158
177
159 export SSL_CERT_FILE=${pkgs.evalPackages.cacert}/etc/ssl/certs/ca-bundle.crt
178 export SSL_CERT_FILE=${pkgs.evalPackages.cacert}/etc/ssl/certs/ca-bundle.crt
179+ cabal v2-update ${name}
160− mkdir -p $out/.cabal/packages/${name}
180+ cp -r $HOME/.cabal/packages/${name} $out
161− HOME=$out cabal new-update ${name}
162 '';
181 '';
163 # Output of hackage-to-nix
182 # Output of hackage-to-nix
164 hackage = import (
183 hackage = import (
@@ -169,34 +188,22 @@ let
169 preferLocalBuild = true;
188 preferLocalBuild = true;
170 } ''
189 } ''
171 mkdir -p $out
190 mkdir -p $out
172− hackage-to-nix $out ${home}/.cabal/packages/${name}/01-index.tar ${attrs.url}
191+ hackage-to-nix $out ${repoContents}/01-index.tar ${attrs.url}
173 '');
192 '');
174− # Tarball info in the same format as `extra-hackage-tarballs` passed in to cabalProject
193+ # Directory to `lndir` when constructing a suitable $HOME/.cabal dir
175− tarball = {
194+ repo = {
176− ${name} = home + "/.cabal/packages/${name}/01-index.tar.gz";
195+ ${name} = repoContents;
177 };
196 };
178− # Replacement `repository` block using `file:` uri and the remaining text (text that was not part of the attribute block).
179− updatedText = ''
180− repository ${name}
181− url: file:${home + "/.cabal/packages/${name}"}
182− secure: True
183− root-keys:
184− key-threshold: 0
185− '' + pkgs.lib.strings.concatStringsSep "\n" x.snd;
186 };
197 };
187
198
188− parseRepositories = cabalProjectFileName: sha256map: cabal-install: nix-tools: projectFile:
199+ parseRepositories = cabalProjectFileName: sha256map: inputMap: cabal-install: nix-tools: projectFile:
189 let
200 let
190 # This will leave the name of repository in the first line of each block
201 # This will leave the name of repository in the first line of each block
191 blocks = pkgs.lib.splitString "\nrepository " ("\n" + projectFile);
202 blocks = pkgs.lib.splitString "\nrepository " ("\n" + projectFile);
192− initialText = pkgs.lib.lists.take 1 blocks;
193− repoBlocks = builtins.map (parseRepositoryBlock cabalProjectFileName sha256map cabal-install nix-tools) (pkgs.lib.lists.drop 1 blocks);
203+ repoBlocks = builtins.map (parseRepositoryBlock cabalProjectFileName sha256map inputMap cabal-install nix-tools) (pkgs.lib.lists.drop 1 blocks);
194 in {
204 in {
195 extra-hackages = pkgs.lib.lists.map (block: block.hackage) repoBlocks;
205 extra-hackages = pkgs.lib.lists.map (block: block.hackage) repoBlocks;
196− tarballs = pkgs.lib.lists.foldl' (x: block: x // block.tarball) {} repoBlocks;
206+ repos = pkgs.lib.lists.foldl' (x: block: x // block.repo) {} repoBlocks;
197− updatedText = pkgs.lib.strings.concatStringsSep "\n" (
198− initialText
199− ++ (builtins.map (x: x.updatedText) repoBlocks));
200 };
207 };
201
208
202in {
209in {
lib/call-cabal-project-to-nix.nix+23−8
@@ -37,6 +37,14 @@ in
37 # "https://raw.githubusercontent.com/input-output-hk/hackage-overlay-ghcjs/bfc363b9f879c360e0a0460ec0c18ec87222ec32"
37 # "https://raw.githubusercontent.com/input-output-hk/hackage-overlay-ghcjs/bfc363b9f879c360e0a0460ec0c18ec87222ec32"
38 # = "sha256-g9xGgJqYmiczjxjQ5JOiK5KUUps+9+nlNGI/0SpSOpg=";
38 # = "sha256-g9xGgJqYmiczjxjQ5JOiK5KUUps+9+nlNGI/0SpSOpg=";
39 # };
39 # };
40+, inputMap ? {}
41+ # An alternative to providing a `sha256` handy for flakes
42+ # cabal.project file:
43+ # inputs.pandoc-citeproc.url = "github:jgm/pandoc-citeproc/0.17";
44+ # inputs.pandoc-citeproc.flake = false;
45+ # outputs = inputs:
46+ # ...
47+ # inputMap."https://github.com/jgm/pandoc-citeproc" = inputs.inputs.pandoc-citeproc;
40, extra-hackage-tarballs ? {}
48, extra-hackage-tarballs ? {}
41, source-repo-override ? {} # Cabal seems to behave incoherently when
49, source-repo-override ? {} # Cabal seems to behave incoherently when
42 # two source-repository-package entries
50 # two source-repository-package entries
@@ -194,8 +202,15 @@ let
194 fetchPackageRepo = fetchgit: repoData:
202 fetchPackageRepo = fetchgit: repoData:
195 let
203 let
196 fetched =
204 fetched =
205+ if inputMap ? "${repoData.url}/${repoData.ref}"
206+ then inputMap."${repoData.url}/${repoData.ref}"
207+ else if inputMap ? ${repoData.url}
208+ then
209+ (if inputMap.${repoData.url}.rev != repoData.ref
210+ then throw "${inputMap.${repoData.url}.rev} may not match ${repoData.ref} for ${repoData.url} use \"${repoData.url}/${repoData.ref}\" as the inputMap key if ${repoData.ref} is a branch or tag that points to ${inputMap.${repoData.url}.rev}."
211+ else inputMap.${repoData.url})
197− if repoData.sha256 != null
212+ else if repoData.sha256 != null
198− then fetchgit { inherit (repoData) url sha256; rev = repoData.ref; }
213+ then fetchgit { inherit (repoData) url sha256; rev = repoData.ref; }
199 else
214 else
200 let drv = builtins.fetchGit { inherit (repoData) url ref; };
215 let drv = builtins.fetchGit { inherit (repoData) url ref; };
201 in __trace "WARNING: No sha256 found for source-repository-package ${repoData.url} ${repoData.ref} download may fail in restricted mode (hydra)"
216 in __trace "WARNING: No sha256 found for source-repository-package ${repoData.url} ${repoData.ref} download may fail in restricted mode (hydra)"
@@ -226,7 +241,7 @@ let
226
241
227 # Parse the `repository` blocks
242 # Parse the `repository` blocks
228 repoResult = pkgs.haskell-nix.haskellLib.parseRepositories
243 repoResult = pkgs.haskell-nix.haskellLib.parseRepositories
229− cabalProjectFileName sha256map cabal-install nix-tools sourceRepoPackageResult.otherText;
244+ cabalProjectFileName sha256map inputMap cabal-install nix-tools sourceRepoPackageResult.otherText;
230
245
231 # we need the repository content twice:
246 # we need the repository content twice:
232 # * at eval time (below to build the fixed project file)
247 # * at eval time (below to build the fixed project file)
@@ -241,9 +256,9 @@ let
241 sourceReposBuild = builtins.map (x: (fetchPackageRepo pkgs.fetchgit x).fetched) sourceRepoPackageResult.sourceRepos;
256 sourceReposBuild = builtins.map (x: (fetchPackageRepo pkgs.fetchgit x).fetched) sourceRepoPackageResult.sourceRepos;
242 in {
257 in {
243 sourceRepos = sourceReposBuild;
258 sourceRepos = sourceReposBuild;
244− inherit (repoResult) tarballs extra-hackages;
259+ inherit (repoResult) repos extra-hackages;
245 makeFixedProjectFile = ''
260 makeFixedProjectFile = ''
246− cp -f ${pkgs.evalPackages.writeText "cabal.project" repoResult.updatedText} ./cabal.project
261+ cp -f ${pkgs.evalPackages.writeText "cabal.project" sourceRepoPackageResult.otherText} ./cabal.project
247 '' +
262 '' +
248 pkgs.lib.optionalString (builtins.length sourceReposEval != 0) (''
263 pkgs.lib.optionalString (builtins.length sourceReposEval != 0) (''
249 chmod +w -R ./cabal.project
264 chmod +w -R ./cabal.project
@@ -278,7 +293,7 @@ let
278
293
279 fixedProject =
294 fixedProject =
280 if rawCabalProject == null
295 if rawCabalProject == null
281− then { sourceRepos = []; tarballs = {}; extra-hackages = []; makeFixedProjectFile = ""; replaceLocations = ""; }
296+ then { sourceRepos = []; repos = {}; extra-hackages = []; makeFixedProjectFile = ""; replaceLocations = ""; }
282 else replaceSourceRepos rawCabalProject;
297 else replaceSourceRepos rawCabalProject;
283
298
284 # The use of the actual GHC can cause significant problems:
299 # The use of the actual GHC can cause significant problems:
@@ -523,8 +538,8 @@ let
523 # some packages that will be excluded by `index-state-found`
538 # some packages that will be excluded by `index-state-found`
524 # which is used by cabal (cached-index-state >= index-state-found).
539 # which is used by cabal (cached-index-state >= index-state-found).
525 dotCabal {
540 dotCabal {
526− inherit cabal-install nix-tools;
541+ inherit cabal-install nix-tools extra-hackage-tarballs;
527− extra-hackage-tarballs = fixedProject.tarballs // extra-hackage-tarballs;
542+ extra-hackage-repos = fixedProject.repos;
528 index-state = cached-index-state;
543 index-state = cached-index-state;
529 sha256 = index-sha256-found;
544 sha256 = index-sha256-found;
530 }
545 }
modules/cabal-project.nix+8
@@ -105,6 +105,14 @@ in {
105 = "0dxx8cp2xndpw3jwiawch2dkrkp15mil7pyx7dvd810pwc22pm2q"; };
105 = "0dxx8cp2xndpw3jwiawch2dkrkp15mil7pyx7dvd810pwc22pm2q"; };
106 '';
106 '';
107 };
107 };
108+ inputMap = mkOption {
109+ type = nullOr attrs;
110+ default = {};
111+ description = ''
112+ Specifies the contents of urls in the cabal.project file.
113+ The `.rev` attribute is checked against the `tag` for `source-repository-packages`.
114+ '';
115+ };
108 extra-hackage-tarballs = mkOption {
116 extra-hackage-tarballs = mkOption {
109 type = nullOr attrs;
117 type = nullOr attrs;
110 default = {};
118 default = {};
overlays/haskell.nix+14−4
@@ -203,16 +203,15 @@ final: prev: {
203 # Creates Cabal local repository from { name, index } set.
203 # Creates Cabal local repository from { name, index } set.
204 mkLocalHackageRepo = import ../mk-local-hackage-repo final;
204 mkLocalHackageRepo = import ../mk-local-hackage-repo final;
205
205
206− dotCabal = { index-state, sha256, cabal-install, extra-hackage-tarballs ? {}, ... }@args:
206+ dotCabal = { index-state, sha256, cabal-install, extra-hackage-tarballs ? {}, extra-hackage-repos ? {}, ... }@args:
207 let
207 let
208 allTarballs = hackageTarball args // extra-hackage-tarballs;
208 allTarballs = hackageTarball args // extra-hackage-tarballs;
209 allNames = final.lib.concatStringsSep "-" (builtins.attrNames allTarballs);
209 allNames = final.lib.concatStringsSep "-" (builtins.attrNames allTarballs);
210 # 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
211 # dotCabalName anyway.
211 # dotCabalName anyway.
212 dotCabalName = "dot-cabal-" + allNames;
212 dotCabalName = "dot-cabal-" + allNames;
213− in
214− # This is very big, and cheap to build: prefer building it locally
213+ # This is very big, and cheap to build: prefer building it locally
215− final.evalPackages.runCommand dotCabalName { nativeBuildInputs = [ cabal-install ]; preferLocalBuild = true; } ''
214+ tarballRepos = final.evalPackages.runCommand dotCabalName { nativeBuildInputs = [ cabal-install ]; preferLocalBuild = true; } ''
216 mkdir -p $out/.cabal
215 mkdir -p $out/.cabal
217 cat <<EOF > $out/.cabal/config
216 cat <<EOF > $out/.cabal/config
218 ${final.lib.concatStrings (
217 ${final.lib.concatStrings (
@@ -237,6 +236,17 @@ final: prev: {
237 ${final.lib.concatStrings (map (name: ''
236 ${final.lib.concatStrings (map (name: ''
238 HOME=$out cabal new-update ${name}
237 HOME=$out cabal new-update ${name}
239 '') (builtins.attrNames allTarballs))}
238 '') (builtins.attrNames allTarballs))}
239+ '';
240+ in
241+ # Add the extra-hackage-repos where we have all the files needed.
242+ final.evalPackages.runCommand dotCabalName { nativeBuildInputs = [ final.evalPackages.xorg.lndir ]; } ''
243+ mkdir $out
244+ lndir ${tarballRepos} $out
245+
246+ ${final.lib.concatStrings (final.lib.mapAttrsToList (name: repo: ''
247+ mkdir -p $out/.cabal/packages/${name}
248+ lndir ${repo} $out/.cabal/packages/${name}
249+ '') extra-hackage-repos)}
240 '';
250 '';
241
251
242 # Some of features of haskell.nix rely on using a hackage index
252 # Some of features of haskell.nix rely on using a hackage index
test/ghcjs-overlay/cabal.project+1−1
@@ -5,5 +5,5 @@ repository ghcjs-overlay
5 secure: True
5 secure: True
6 root-keys:
6 root-keys:
7 key-threshold: 0
7 key-threshold: 0
8− --sha256: sha256-g9xGgJqYmiczjxjQ5JOiK5KUUps+9+nlNGI/0SpSOpg=
8+ --sha256: sha256-y1vQnXI1XzkjnC4h66tVDmu2TZjZPcMrZEnE3m0XOfg=
9
9
test/unit.nix+5−13
@@ -119,7 +119,7 @@ lib.runTests {
119 };
119 };
120
120
121 testParseRepositoryBlock = {
121 testParseRepositoryBlock = {
122− expr = __toJSON (haskellLib.parseRepositoryBlock "cabal.project" {}
122+ expr = __toJSON (haskellLib.parseRepositoryBlock "cabal.project" {} {}
123 pkgs.evalPackages.haskell-nix.cabal-install.${compiler-nix-name}
123 pkgs.evalPackages.haskell-nix.cabal-install.${compiler-nix-name}
124 pkgs.evalPackages.haskell-nix.nix-tools.${compiler-nix-name} ''
124 pkgs.evalPackages.haskell-nix.nix-tools.${compiler-nix-name} ''
125 ghcjs-overlay
125 ghcjs-overlay
@@ -127,22 +127,14 @@ lib.runTests {
127 secure: True
127 secure: True
128 root-keys:
128 root-keys:
129 key-threshold: 0
129 key-threshold: 0
130− --sha256: sha256-g9xGgJqYmiczjxjQ5JOiK5KUUps+9+nlNGI/0SpSOpg=
130+ --sha256: sha256-y1vQnXI1XzkjnC4h66tVDmu2TZjZPcMrZEnE3m0XOfg=
131 -- end of block
131 -- end of block
132 '');
132 '');
133 expected = __toJSON {
133 expected = __toJSON {
134 name = "ghcjs-overlay";
134 name = "ghcjs-overlay";
135− updatedText = ''
135+ repoContents = "/nix/store/gzjj6rjjgvkm5midldy292ghbq7hszna-ghcjs-overlay";
136− repository ghcjs-overlay
136+ repo = {
137− url: file:/nix/store/0lx8536b53bqssqzzbyzi22j117a7q2g-ghcjs-overlay/.cabal/packages/ghcjs-overlay
137+ ghcjs-overlay = "/nix/store/gzjj6rjjgvkm5midldy292ghbq7hszna-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 };
138 };
147 hackage = {
139 hackage = {
148 Cabal = {
140 Cabal = {