Skip to content

Commit 2f4155e

Browse files
Try #1370:
2 parents c2677de + 77726b4 commit 2f4155e

File tree

15 files changed

+227
-31
lines changed

15 files changed

+227
-31
lines changed

lib/cabal-project-parser.nix

Lines changed: 83 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ let
7474
# --shar256: 003lm3pm0000hbfmii7xcdd9v20000flxf7gdl2pyxia7p014i8z
7575
# will be trated like a field and returned here
7676
# (used in call-cabal-project-to-nix.nix to create a fixed-output derivation)
77-
extractRepoData = cabalProjectFileName: lookupSha256: repo: {
77+
extractSourceRepoPackageData = cabalProjectFileName: lookupSha256: repo: {
7878
url = repo.location;
7979
ref = repo.tag;
8080
sha256 = repo."--sha256" or (lookupSha256 repo);
@@ -95,10 +95,90 @@ let
9595
otherText = "\nsource-repository-package\n" + block;
9696
}
9797
else {
98-
sourceRepo = extractRepoData cabalProjectFileName lookupSha256 attrs;
98+
sourceRepo = extractSourceRepoPackageData cabalProjectFileName lookupSha256 attrs;
9999
otherText = pkgs.lib.strings.concatStringsSep "\n" x.snd;
100100
};
101101

102+
parseSourceRepositoryPackages = cabalProjectFileName: lookupSha256: source-repo-override: projectFile:
103+
let
104+
blocks = pkgs.lib.splitString "\nsource-repository-package\n" ("\n" + projectFile);
105+
initialText = pkgs.lib.lists.take 1 blocks;
106+
repoBlocks = builtins.map (parseBlock cabalProjectFileName lookupSha256) (pkgs.lib.lists.drop 1 blocks);
107+
overrideSourceRepo = sourceRepo: (source-repo-override.${sourceRepo.url} or (pkgs.lib.id)) sourceRepo;
108+
in {
109+
sourceRepos = pkgs.lib.lists.map (block: overrideSourceRepo block.sourceRepo) repoBlocks;
110+
otherText = pkgs.lib.strings.concatStringsSep "\n" (
111+
initialText
112+
++ (builtins.map (x: x.otherText) repoBlocks));
113+
};
114+
115+
# Parse a repository
116+
parseRepositoryBlock = cabalProjectFileName: lookupSha256: cabal-install: nix-tools: block:
117+
let
118+
lines = pkgs.lib.splitString "\n" block;
119+
x = span (pkgs.lib.strings.hasPrefix " ") (__tail lines);
120+
attrs = parseBlockLines x.fst;
121+
in rec {
122+
name = __head lines;
123+
repo = attrs;
124+
home =
125+
pkgs.evalPackages.runCommandLocal name {
126+
nativeBuildInputs = [ cabal-install pkgs.evalPackages.curl nix-tools ];
127+
LOCALE_ARCHIVE = pkgs.lib.optionalString (pkgs.evalPackages.stdenv.buildPlatform.libc == "glibc") "${pkgs.evalPackages.glibcLocales}/lib/locale/locale-archive";
128+
LANG = "en_US.UTF-8";
129+
outputHashMode = "recursive";
130+
outputHashAlgo = "sha256";
131+
outputHash = attrs."--sha256" or (lookupSha256 attrs);
132+
} ''
133+
mkdir -p $out/.cabal
134+
cat <<EOF > $out/.cabal/config
135+
repository ${name}
136+
url: ${attrs.url}
137+
${pkgs.lib.optionalString (attrs ? secure) "secure: ${attrs.secure}"}
138+
${pkgs.lib.optionalString (attrs ? root-keys) "root-keys: ${attrs.root-keys}"}
139+
${pkgs.lib.optionalString (attrs ? key-threshold) "key-threshold: ${attrs.key-threshold}"}
140+
EOF
141+
142+
export SSL_CERT_FILE=${pkgs.evalPackages.cacert}/etc/ssl/certs/ca-bundle.crt
143+
mkdir -p $out/.cabal/packages/${name}
144+
HOME=$out cabal new-update ${name}
145+
ls -ld $out/.cabal
146+
'';
147+
hackage = import (
148+
pkgs.evalPackages.runCommandLocal ("hackageg-to-nix-" + name) {
149+
nativeBuildInputs = [ cabal-install pkgs.evalPackages.curl nix-tools ];
150+
LOCALE_ARCHIVE = pkgs.lib.optionalString (pkgs.evalPackages.stdenv.buildPlatform.libc == "glibc") "${pkgs.evalPackages.glibcLocales}/lib/locale/locale-archive";
151+
LANG = "en_US.UTF-8";
152+
} ''
153+
mkdir -p $out
154+
hackage-to-nix $out ${home}/.cabal/packages/${name}/01-index.tar ${attrs.url}
155+
'');
156+
tarball = {
157+
inherit name;
158+
index = home + "/.cabal/packages/${name}/01-index.tar.gz";
159+
};
160+
otherText = ''
161+
repository ${name}
162+
url: file:${home + "/.cabal/packages/${name}"}
163+
secure: True
164+
root-keys:
165+
key-threshold: 0
166+
'' + pkgs.lib.strings.concatStringsSep "\n" x.snd;
167+
};
168+
169+
parseRepositories = cabalProjectFileName: lookupSha256: cabal-install: nix-tools: projectFile:
170+
let
171+
blocks = pkgs.lib.splitString "\nrepository " ("\n" + projectFile);
172+
initialText = pkgs.lib.lists.take 1 blocks;
173+
repoBlocks = builtins.map (parseRepositoryBlock cabalProjectFileName lookupSha256 cabal-install nix-tools) (pkgs.lib.lists.drop 1 blocks);
174+
in {
175+
extra-hackages = pkgs.lib.lists.map (block: block.hackage) repoBlocks;
176+
tarballs = pkgs.lib.lists.map (block: block.tarball) repoBlocks;
177+
otherText = pkgs.lib.strings.concatStringsSep "\n" (
178+
initialText
179+
++ (builtins.map (x: x.otherText) repoBlocks));
180+
};
181+
102182
in {
103-
inherit parseIndexState parseBlockLines parseBlock;
183+
inherit parseIndexState parseSourceRepositoryPackages parseRepositories parseBlock;
104184
}

lib/call-cabal-project-to-nix.nix

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ let
192192

193193
replaceSourceRepos = projectFile:
194194
let
195-
fetchRepo = fetchgit: repoData:
195+
fetchPackageRepo = fetchgit: repoData:
196196
let
197197
fetched =
198198
if repoData.sha256 != null
@@ -221,14 +221,13 @@ let
221221
tag = "minimal";
222222
};
223223

224-
blocks = pkgs.lib.splitString "\nsource-repository-package\n" ("\n" + projectFile);
225-
initialText = pkgs.lib.lists.take 1 blocks;
226-
repoBlocks = builtins.map (pkgs.haskell-nix.haskellLib.parseBlock cabalProjectFileName lookupSha256) (pkgs.lib.lists.drop 1 blocks);
227-
overrideSourceRepo = sourceRepo: (source-repo-override.${sourceRepo.url} or (pkgs.lib.id)) sourceRepo;
228-
sourceRepoData = pkgs.lib.lists.map (x: overrideSourceRepo x.sourceRepo) repoBlocks;
229-
otherText = pkgs.evalPackages.writeText "cabal.project" (pkgs.lib.strings.concatStringsSep "\n" (
230-
initialText
231-
++ (builtins.map (x: x.otherText) repoBlocks)));
224+
# Parse the `source-repository-package` blocks
225+
sourceRepoPackageResult = pkgs.haskell-nix.haskellLib.parseSourceRepositoryPackages
226+
cabalProjectFileName lookupSha256 source-repo-override projectFile;
227+
228+
# Parse the `repository` blocks
229+
repoResult = pkgs.haskell-nix.haskellLib.parseRepositories
230+
cabalProjectFileName lookupSha256 cabal-install nix-tools sourceRepoPackageResult.otherText;
232231

233232
# we need the repository content twice:
234233
# * at eval time (below to build the fixed project file)
@@ -239,12 +238,13 @@ let
239238
# on the target system would use, so that the derivation is unaffected
240239
# and, say, a linux release build job can identify the derivation
241240
# as built by a darwin builder, and fetch it from a cache
242-
sourceReposEval = builtins.map (fetchRepo pkgs.evalPackages.fetchgit) sourceRepoData;
243-
sourceReposBuild = builtins.map (x: (fetchRepo pkgs.fetchgit x).fetched) sourceRepoData;
241+
sourceReposEval = builtins.map (fetchPackageRepo pkgs.evalPackages.fetchgit) sourceRepoPackageResult.sourceRepos;
242+
sourceReposBuild = builtins.map (x: (fetchPackageRepo pkgs.fetchgit x).fetched) sourceRepoPackageResult.sourceRepos;
244243
in {
245244
sourceRepos = sourceReposBuild;
245+
inherit (repoResult) tarballs extra-hackages;
246246
makeFixedProjectFile = ''
247-
cp -f ${otherText} ./cabal.project
247+
cp -f ${pkgs.evalPackages.writeText "cabal.project" repoResult.otherText} ./cabal.project
248248
'' +
249249
pkgs.lib.optionalString (builtins.length sourceReposEval != 0) (''
250250
chmod +w -R ./cabal.project
@@ -279,7 +279,7 @@ let
279279

280280
fixedProject =
281281
if rawCabalProject == null
282-
then { sourceRepos = []; makeFixedProjectFile = ""; replaceLocations = ""; }
282+
then { sourceRepos = []; tarballs = []; extra-hackages = []; makeFixedProjectFile = ""; replaceLocations = ""; }
283283
else replaceSourceRepos rawCabalProject;
284284

285285
# The use of the actual GHC can cause significant problems:
@@ -524,7 +524,11 @@ let
524524
# some packages that will be excluded by `index-state-found`
525525
# which is used by cabal (cached-index-state >= index-state-found).
526526
dotCabal {
527-
inherit cabal-install nix-tools extra-hackage-tarballs;
527+
inherit cabal-install nix-tools;
528+
extra-hackage-tarballs =
529+
if __length extra-hackage-tarballs != 0
530+
then extra-hackage-tarballs
531+
else fixedProject.tarballs;
528532
index-state = cached-index-state;
529533
sha256 = index-sha256-found;
530534
}
@@ -610,5 +614,5 @@ in {
610614
projectNix = plan-nix;
611615
index-state = index-state-found;
612616
inherit src;
613-
inherit (fixedProject) sourceRepos;
617+
inherit (fixedProject) sourceRepos extra-hackages;
614618
}

lib/default.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ in {
275275

276276
inherit (import ./cabal-project-parser.nix {
277277
inherit pkgs;
278-
}) parseIndexState parseBlock;
278+
}) parseIndexState parseSourceRepositoryPackages parseRepositories parseBlock;
279279

280280

281281
cabalToNixpkgsLicense = import ./spdx/cabal.nix pkgs;

mk-local-hackage-repo/default.nix

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@
1717
pkgs:
1818
{ name, index }:
1919

20-
pkgs.evalPackages.runCommandLocal "hackage-repo-${name}" { nativeBuildInputs = [ pkgs.evalPackages.nix ]; } ''
20+
pkgs.evalPackages.runCommandLocal "hackage-repo-${name}" {} ''
2121
mkdir -p $out
2222
export expires="4000-01-01T00:00:00Z"
2323
2424
ln -sf ${index} $out/01-index.tar.gz
25-
export index_md5=$(nix-hash --flat --type md5 ${index})
26-
export index_sha256=$(nix-hash --flat --type sha256 ${index})
25+
export index_md5=$(md5sum ${index} | awk '{ print $1 }')
26+
export index_sha256=$(sha256sum ${index} | awk '{ print $1 }')
2727
${
2828
# When possible check the hash we calculate here against the `outputHash`
2929
# of the index derivation (when the `extra-hackages` feature is used the index
@@ -37,18 +37,18 @@ ${
3737
export index_length=$(stat --printf="%s" ${index})
3838
3939
substituteAll ${./root.json} $out/root.json
40-
export root_md5=$(nix-hash --flat --type md5 $out/root.json)
41-
export root_sha256=$(nix-hash --flat --type sha256 $out/root.json)
40+
export root_md5=$(md5sum $out/root.json | awk '{ print $1 }')
41+
export root_sha256=$(sha256sum $out/root.json | awk '{ print $1 }')
4242
export root_length=$(stat --printf="%s" $out/root.json)
4343
4444
substituteAll ${./mirrors.json} $out/mirrors.json
45-
export mirrors_md5=$(nix-hash --flat --type md5 $out/mirrors.json)
46-
export mirrors_sha256=$(nix-hash --flat --type sha256 $out/mirrors.json)
45+
export mirrors_md5=$(md5sum $out/mirrors.json | awk '{ print $1 }')
46+
export mirrors_sha256=$(sha256sum $out/mirrors.json | awk '{ print $1 }')
4747
export mirrors_length=$(stat --printf="%s" $out/mirrors.json)
4848
4949
substituteAll ${./snapshot.json} $out/snapshot.json
50-
export snapshot_md5=$(nix-hash --flat --type md5 $out/snapshot.json)
51-
export snapshot_sha256=$(nix-hash --flat --type sha256 $out/snapshot.json)
50+
export snapshot_md5=$(md5sum $out/snapshot.json | awk '{ print $1 }')
51+
export snapshot_sha256=$(sha256sum $out/snapshot.json | awk '{ print $1 }')
5252
export snapshot_length=$(stat --printf="%s" $out/snapshot.json)
5353
5454
substituteAll ${./timestamp.json} $out/timestamp.json

overlays/haskell.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ final: prev: {
515515
++ final.lib.optional (args.ghcOverride != null || args.ghc != null)
516516
{ ghc.package = if args.ghcOverride != null then args.ghcOverride else args.ghc; }
517517
++ [ { compiler.nix-name = final.lib.mkForce args.compiler-nix-name; } ];
518-
extra-hackages = args.extra-hackages or [];
518+
extra-hackages = args.extra-hackages or [] ++ callProjectResults.extra-hackages;
519519
};
520520

521521
project = addProjectAndPackageAttrs rec {

test/default.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ let
186186
stack-source-repo = callTest ./stack-source-repo { inherit compiler-nix-name; };
187187
cabal-doctests = callTest ./cabal-doctests { inherit util compiler-nix-name; };
188188
extra-hackage = callTest ./extra-hackage { inherit compiler-nix-name; };
189+
ghcjs-overlay = callTest ./ghcjs-overlay { inherit compiler-nix-name; };
189190
hls-cabal = callTest ./haskell-language-server/cabal.nix { inherit compiler-nix-name; };
190191
hls-stack = callTest ./haskell-language-server/stack.nix { inherit compiler-nix-name; };
191192
cabal-hpack = callTest ./cabal-hpack { inherit util compiler-nix-name; };
Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
packages: *.cabal
22

3-
repository local
4-
url: http://127.0.0.1:7777
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.
7+
-- repository local
8+
-- url: http://127.0.0.1:7777

test/ghcjs-overlay/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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.hs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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.hs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module MyLib (someFunc) where
2+
3+
someFunc :: IO ()
4+
someFunc = putStrLn "someFunc"

0 commit comments

Comments
 (0)