Skip to content

Commit c773606

Browse files
authored
download stack resolver if a sha256 is provided (#748)
This change allows a resolverSha256 to be passed to stackProject. When provided the resolver found in the stack.yaml is fetched using this sha256 and the uri string is replaced with the path to the fetched version.
1 parent 393678f commit c773606

File tree

11 files changed

+111
-24
lines changed

11 files changed

+111
-24
lines changed

lib/call-stack-to-nix.nix

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,26 @@
55
*
66
* see also `call-cabal-project-to-nix`!
77
*/
8-
{ runCommand, nix-tools, pkgs, mkCacheFile, materialize }:
8+
{ runCommand, nix-tools, pkgs, mkCacheFile, materialize, haskellLib }:
99
{ name ? src.name or null # optional name for better error messages
1010
, src
11-
, stackYaml ? null
11+
, stackYaml ? "stack.yaml"
1212
, ignorePackageYaml ? false
1313
, cache ? null
1414
, stack-sha256 ? null
15+
, resolverSha256 ? null
1516
, materialized ? null # Location of a materialized copy of the nix files
1617
, checkMaterialization ? null # If true the nix files will be generated used to check plan-sha256 and material
1718
, ... }:
1819
let
20+
inherit (haskellLib.fetchResolver {
21+
inherit src stackYaml resolverSha256;
22+
}) resolver fetchedResolver;
23+
1924
subDir' = src.origSubDir or "";
2025
stackToNixArgs = builtins.concatStringsSep " " [
2126
"--full"
22-
"--stack-yaml=${src}/${if stackYaml == null then "stack.yaml" else stackYaml}"
27+
"--stack-yaml=$SRC/${stackYaml}"
2328
(if ignorePackageYaml then "--ignore-package-yaml" else "")
2429
"-o ."
2530
];
@@ -31,23 +36,40 @@ let
3136
} // pkgs.lib.optionalAttrs (checkMaterialization != null) {
3237
inherit checkMaterialization;
3338
}) (runCommand (if name == null then "stack-to-nix-pkgs" else name + "-stack-to-nix-pkgs") {
34-
nativeBuildInputs = [ nix-tools pkgs.nix-prefetch-git pkgs.cacert ];
39+
nativeBuildInputs = [ nix-tools pkgs.nix-prefetch-git pkgs.cacert pkgs.xorg.lndir ];
3540
# Needed or stack-to-nix will die on unicode inputs
3641
LOCALE_ARCHIVE = pkgs.lib.optionalString (pkgs.stdenv.hostPlatform.libc == "glibc") "${pkgs.glibcLocales}/lib/locale/locale-archive";
3742
LANG = "en_US.UTF-8";
3843
LC_ALL = "en_US.UTF-8";
3944
preferLocalBuild = false;
4045
} (''
4146
mkdir -p $out${subDir'}
42-
'' + pkgs.lib.optionalString (cache != null) ''
43-
cp ${mkCacheFile cache}/.stack-to-nix.cache* $out${subDir'}
44-
'' + ''
47+
${
48+
# If no resolver was fetched use the original stack.yaml
49+
if fetchedResolver == null
50+
then ''
51+
SRC=${src}
52+
''
53+
else
54+
# Replace the resolver path in the stack.yaml with the fetched version
55+
''
56+
SRC=$(mktemp -d)
57+
cd $SRC
58+
lndir -silent "${src}/." $SRC
59+
rm ${stackYaml}
60+
cp ${src}/${stackYaml} .
61+
chmod +w ${stackYaml}
62+
substituteInPlace ${stackYaml} --replace "${resolver}" "${fetchedResolver}"
63+
''}
64+
${pkgs.lib.optionalString (cache != null) ''
65+
cp ${mkCacheFile cache}/.stack-to-nix.cache* $out${subDir'}
66+
''}
4567
(cd $out${subDir'} && stack-to-nix ${stackToNixArgs})
4668
4769
# We need to strip out any references to $src, as those won't
4870
# be accessable in restricted mode.
4971
for nixf in $(find $out -name "*.nix" -type f); do
50-
substituteInPlace $nixf --replace "${src}" "."
72+
substituteInPlace $nixf --replace "$SRC" "."
5173
done
5274
5375
# move pkgs.nix to default.nix ensure we can just nix `import` the result.

lib/default.nix

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,4 +261,9 @@ in {
261261
if lib.isAttrs versionOrArgs
262262
then versionOrArgs
263263
else { version = versionOrArgs; };
264+
265+
# Find the resolver in the stack.yaml file and fetch it if a sha256 value is provided
266+
fetchResolver = import ./fetch-resolver.nix {
267+
inherit (pkgs.evalPackages) pkgs;
268+
};
264269
}

lib/fetch-resolver.nix

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Find the resolver in the stack.yaml file and fetch it if a sha256 value is provided
2+
{ pkgs }:
3+
{ src
4+
, stackYaml ? "stack.yaml"
5+
, resolverSha256 ? null
6+
}:
7+
let
8+
# Using origSrcSubDir bypasses any cleanSourceWith so that it will work when
9+
# access to the store is restricted. If origSrc was already in the store
10+
# you can pass the project in as a string.
11+
rawStackYaml = builtins.readFile ((src.origSrcSubDir or src) + ("/" + stackYaml));
12+
13+
# Determine the resolver as it may point to another file we need
14+
# to look at.
15+
resolver =
16+
let
17+
rs = pkgs.lib.lists.concatLists (
18+
pkgs.lib.lists.filter (l: l != null)
19+
(builtins.map (l: builtins.match "^resolver: *(.*)" l)
20+
(pkgs.lib.splitString "\n" rawStackYaml)));
21+
in
22+
pkgs.lib.lists.head (rs ++ [ null ]);
23+
24+
# If we found a resolver andwe have a resolverSha256 then we should download it.
25+
fetchedResolver =
26+
if resolver != null && resolverSha256 != null
27+
then pkgs.fetchurl {
28+
url = resolver;
29+
sha256 = resolverSha256;
30+
}
31+
else null;
32+
33+
in { inherit resolver fetchedResolver; }

lib/stack-cache-generator.nix

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,28 +13,17 @@
1313
if sha256map != null
1414
then { location, tag, ...}: sha256map."${location}"."${tag}"
1515
else _: null
16+
, resolverSha256 ? null
1617
, ...
1718
}:
1819
let
1920
# We only care about the stackYaml file. If src is a local directory
2021
# we want to avoid recalculating the cache unless the stack.yaml file
2122
# changes.
2223

23-
# Using origSrcSubDir bypasses any cleanSourceWith so that it will work when
24-
# access to the store is restricted. If origSrc was already in the store
25-
# you can pass the project in as a string.
26-
rawStackYaml = builtins.readFile ((src.origSrcSubDir or src) + ("/" + stackYaml));
27-
28-
# Determine the resolver as it may point to another file we need
29-
# to look at.
30-
resolver =
31-
let
32-
rs = pkgs.lib.lists.concatLists (
33-
pkgs.lib.lists.filter (l: l != null)
34-
(builtins.map (l: builtins.match "^resolver: *(.*)" l)
35-
(pkgs.lib.splitString "\n" rawStackYaml)));
36-
in
37-
pkgs.lib.lists.head (rs ++ [ null ]);
24+
inherit (haskellLib.fetchResolver {
25+
inherit src stackYaml resolverSha256;
26+
}) resolver fetchedResolver;
3827

3928
# Filter just the stack yaml file and any reolver yaml file it points to.
4029
maybeCleanedSource =
@@ -58,6 +47,9 @@ let
5847
cp -r "${maybeCleanedSource}/." $TMP
5948
chmod -R +w $TMP
6049
substituteInPlace ${stackYaml} --replace "# nix-sha256:" "nix-sha256:"
50+
${pkgs.lib.optionalString (fetchedResolver != null) ''
51+
substituteInPlace ${stackYaml} --replace "${resolver}" "${fetchedResolver}"
52+
''}
6153
stack-repos --stack-yaml ${stackYaml}
6254
cp repos.json $out
6355
''));

overlays/haskell.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ final: prev: {
260260
callStackToNix = import ../lib/call-stack-to-nix.nix {
261261
pkgs = final.evalPackages.pkgs;
262262
inherit (final.evalPackages.pkgs) runCommand;
263-
inherit (final.evalPackages.haskell-nix) nix-tools mkCacheFile materialize;
263+
inherit (final.evalPackages.haskell-nix) nix-tools mkCacheFile materialize haskellLib;
264264
};
265265

266266
# given a source location call `cabal-to-nix` (from nix-tools) on it

test/default.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ let
159159
builder-haddock = callTest ./builder-haddock {};
160160
stack-simple = callTest ./stack-simple {};
161161
stack-local-resolver = callTest ./stack-local-resolver {};
162+
stack-remote-resolver = callTest ./stack-remote-resolver {};
162163
snapshots = callTest ./snapshots {};
163164
shell-for = callTest ./shell-for {};
164165
shell-for-setup-deps = callTest ./shell-for-setup-deps {};

test/stack-remote-resolver/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/.stack-work/
2+
/*.cabal
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{ project', recurseIntoAttrs, testSrc }:
2+
3+
let
4+
project = project' {
5+
src = testSrc "stack-remote-resolver";
6+
resolverSha256 = "1rldkqqsxd8zxybrkqhc25bcxinhz212kz45jcz8jinfihc91jl7";
7+
};
8+
packages = project.hsPkgs;
9+
10+
in recurseIntoAttrs {
11+
ifdInputs = {
12+
inherit (project) stack-nix;
13+
};
14+
inherit (packages.stack-remote-resolver.components) library;
15+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
name: stack-remote-resolver
2+
3+
dependencies:
4+
- base
5+
6+
library:
7+
source-dirs: src

test/stack-remote-resolver/src/Lib.hs

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

test/stack-remote-resolver/stack.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
resolver: https://raw.githubusercontent.com/input-output-hk/haskell.nix/master/test/stack-local-resolver/snapshot.yaml
2+
3+
packages:
4+
- .

0 commit comments

Comments
 (0)