mirror of
https://github.com/ilyakooo0/haskell.nix.git
synced 2024-09-11 06:55:40 +03:00
Improve support for external Hackage repositories (#1370)
* Improve support for external Hackage repositories This change builds #535. `repository` blocks in `cabal.project` parsed and `cabal` is used to automatically downloaded them. Then `hackage-to-nix` is used to produce the nix required. To make it work with restricted eval (on hydra for instance) we need to include a sha256 like this: ``` repository ghcjs-overlay url: https://input-output-hk.github.io/hackage-overlay-ghcjs secure: True root-keys: key-threshold: 0 --sha256: sha256-EPlLYPmIGtxeahlOspRzwJv+60N5mqrNC2BY4jZKceE= ``` To find the correct `sha256` put in an invalid one and attempt a build.
This commit is contained in:
parent
6b891ba383
commit
2576a948b5
@ -1,6 +1,13 @@
|
||||
This file contains a summary of changes to Haskell.nix and `nix-tools`
|
||||
that will impact users.
|
||||
|
||||
## Feb 16, 2022
|
||||
* Removed lookupSha256 argument from project functions.
|
||||
Pass a `sha256map` instead.
|
||||
* Added better support for `repository` in `cabal.project`. These
|
||||
blocks should now work without the need for passing `extra-hackages` and
|
||||
`extra-hackage-tarballs`.
|
||||
|
||||
## Aug 6, 2021
|
||||
* Included dependencies of haskell.nix that were tracked in `nix/sources.json`
|
||||
as flake inputs (`flake.lock` replaces `nix/sources.json`).
|
||||
|
@ -74,17 +74,21 @@ let
|
||||
# --shar256: 003lm3pm0000hbfmii7xcdd9v20000flxf7gdl2pyxia7p014i8z
|
||||
# will be trated like a field and returned here
|
||||
# (used in call-cabal-project-to-nix.nix to create a fixed-output derivation)
|
||||
extractRepoData = cabalProjectFileName: lookupSha256: repo: {
|
||||
extractSourceRepoPackageData = cabalProjectFileName: sha256map: repo: {
|
||||
url = repo.location;
|
||||
ref = repo.tag;
|
||||
sha256 = repo."--sha256" or (lookupSha256 repo);
|
||||
sha256 = repo."--sha256" or (
|
||||
if sha256map != null
|
||||
then sha256map."${repo.location}"."${repo.tag}"
|
||||
else null);
|
||||
subdirs = if repo ? subdir
|
||||
then pkgs.lib.filter (x: x != "") (pkgs.lib.splitString " " repo.subdir)
|
||||
else ["."];
|
||||
};
|
||||
|
||||
# Parse a source-repository-package and return data of `type: git` repositories
|
||||
parseBlock = cabalProjectFileName: lookupSha256: block:
|
||||
# See tests/unit.nix for examples of input and output.
|
||||
parseSourceRepositoryPackageBlock = cabalProjectFileName: sha256map: block:
|
||||
let
|
||||
x = span (pkgs.lib.strings.hasPrefix " ") (pkgs.lib.splitString "\n" block);
|
||||
attrs = parseBlockLines x.fst;
|
||||
@ -95,10 +99,106 @@ let
|
||||
otherText = "\nsource-repository-package\n" + block;
|
||||
}
|
||||
else {
|
||||
sourceRepo = extractRepoData cabalProjectFileName lookupSha256 attrs;
|
||||
sourceRepo = extractSourceRepoPackageData cabalProjectFileName sha256map attrs;
|
||||
otherText = pkgs.lib.strings.concatStringsSep "\n" x.snd;
|
||||
};
|
||||
|
||||
parseSourceRepositoryPackages = cabalProjectFileName: sha256map: source-repo-override: projectFile:
|
||||
let
|
||||
blocks = pkgs.lib.splitString "\nsource-repository-package\n" ("\n" + projectFile);
|
||||
initialText = pkgs.lib.lists.take 1 blocks;
|
||||
repoBlocks = builtins.map (parseSourceRepositoryPackageBlock cabalProjectFileName sha256map) (pkgs.lib.lists.drop 1 blocks);
|
||||
overrideSourceRepo = sourceRepo: (source-repo-override.${sourceRepo.url} or (pkgs.lib.id)) sourceRepo;
|
||||
in {
|
||||
sourceRepos = pkgs.lib.lists.map (block: overrideSourceRepo block.sourceRepo) repoBlocks;
|
||||
otherText = pkgs.lib.strings.concatStringsSep "\n" (
|
||||
initialText
|
||||
++ (builtins.map (x: x.otherText) repoBlocks));
|
||||
};
|
||||
|
||||
# Parse and replace repository
|
||||
# This works in a similar way to the `source-repository-package` but we are
|
||||
# able to simply replace the `repository` blocks with local `file:/nix/store` ones.
|
||||
# This works because `cabal configure` does not include any of the `/nix/sore/`
|
||||
# paths in the `plan.json` (so materialized plan-nix will still work as expeced).
|
||||
# See tests/unit.nix for examples of input and output.
|
||||
parseRepositoryBlock = cabalProjectFileName: sha256map: cabal-install: nix-tools: block:
|
||||
let
|
||||
lines = pkgs.lib.splitString "\n" block;
|
||||
# The first line will contain the repository name.
|
||||
x = span (pkgs.lib.strings.hasPrefix " ") (__tail lines);
|
||||
attrs = parseBlockLines x.fst;
|
||||
sha256 = attrs."--sha256" or (
|
||||
if sha256map != null
|
||||
then sha256map."${attrs.url}"
|
||||
else null);
|
||||
in rec {
|
||||
# This is `some-name` from the `repository some-name` line in the `cabal.project` file.
|
||||
name = __head lines;
|
||||
# The $HOME dir with `.cabal` sub directory after running `cabal new-update` to download the repository
|
||||
home =
|
||||
pkgs.evalPackages.runCommandLocal name ({
|
||||
nativeBuildInputs = [ cabal-install pkgs.evalPackages.curl nix-tools ];
|
||||
LOCALE_ARCHIVE = pkgs.lib.optionalString (pkgs.evalPackages.stdenv.buildPlatform.libc == "glibc") "${pkgs.evalPackages.glibcLocales}/lib/locale/locale-archive";
|
||||
LANG = "en_US.UTF-8";
|
||||
} // pkgs.lib.optionalAttrs (sha256 != null) {
|
||||
outputHashMode = "recursive";
|
||||
outputHashAlgo = "sha256";
|
||||
outputHash = sha256;
|
||||
}) ''
|
||||
mkdir -p $out/.cabal
|
||||
cat <<EOF > $out/.cabal/config
|
||||
repository ${name}
|
||||
url: ${attrs.url}
|
||||
${pkgs.lib.optionalString (attrs ? secure) "secure: ${attrs.secure}"}
|
||||
${pkgs.lib.optionalString (attrs ? root-keys) "root-keys: ${attrs.root-keys}"}
|
||||
${pkgs.lib.optionalString (attrs ? key-threshold) "key-threshold: ${attrs.key-threshold}"}
|
||||
EOF
|
||||
|
||||
export SSL_CERT_FILE=${pkgs.evalPackages.cacert}/etc/ssl/certs/ca-bundle.crt
|
||||
mkdir -p $out/.cabal/packages/${name}
|
||||
HOME=$out cabal new-update ${name}
|
||||
'';
|
||||
# Output of hackage-to-nix
|
||||
hackage = import (
|
||||
pkgs.evalPackages.runCommandLocal ("hackage-to-nix-" + name) {
|
||||
nativeBuildInputs = [ cabal-install pkgs.evalPackages.curl nix-tools ];
|
||||
LOCALE_ARCHIVE = pkgs.lib.optionalString (pkgs.evalPackages.stdenv.buildPlatform.libc == "glibc") "${pkgs.evalPackages.glibcLocales}/lib/locale/locale-archive";
|
||||
LANG = "en_US.UTF-8";
|
||||
} ''
|
||||
mkdir -p $out
|
||||
hackage-to-nix $out ${home}/.cabal/packages/${name}/01-index.tar ${attrs.url}
|
||||
'');
|
||||
# Tarball info in the same format as `extra-hackage-tarballs` passed in to cabalProject
|
||||
tarball = {
|
||||
${name} = home + "/.cabal/packages/${name}/01-index.tar.gz";
|
||||
};
|
||||
# Replacement `repository` block using `file:` uri and the remaining text (text that was not part of the attribute block).
|
||||
updatedText = ''
|
||||
repository ${name}
|
||||
url: file:${home + "/.cabal/packages/${name}"}
|
||||
secure: True
|
||||
root-keys:
|
||||
key-threshold: 0
|
||||
'' + pkgs.lib.strings.concatStringsSep "\n" x.snd;
|
||||
};
|
||||
|
||||
parseRepositories = cabalProjectFileName: sha256map: cabal-install: nix-tools: projectFile:
|
||||
let
|
||||
# This will leave the name of repository in the first line of each block
|
||||
blocks = pkgs.lib.splitString "\nrepository " ("\n" + projectFile);
|
||||
initialText = pkgs.lib.lists.take 1 blocks;
|
||||
repoBlocks = builtins.map (parseRepositoryBlock cabalProjectFileName sha256map cabal-install nix-tools) (pkgs.lib.lists.drop 1 blocks);
|
||||
in {
|
||||
extra-hackages = pkgs.lib.lists.map (block: block.hackage) repoBlocks;
|
||||
tarballs = pkgs.lib.lists.foldl' (x: block: x // block.tarball) {} repoBlocks;
|
||||
updatedText = pkgs.lib.strings.concatStringsSep "\n" (
|
||||
initialText
|
||||
++ (builtins.map (x: x.updatedText) repoBlocks));
|
||||
};
|
||||
|
||||
in {
|
||||
inherit parseIndexState parseBlockLines parseBlock;
|
||||
inherit parseIndexState parseSourceRepositoryPackages parseRepositories
|
||||
# These are only exposed for tests
|
||||
parseSourceRepositoryPackageBlock parseRepositoryBlock;
|
||||
}
|
||||
|
@ -30,13 +30,14 @@ in
|
||||
# An alternative to adding `--sha256` comments into the
|
||||
# cabal.project file:
|
||||
# sha256map =
|
||||
# { "https://github.com/jgm/pandoc-citeproc"."0.17"
|
||||
# = "0dxx8cp2xndpw3jwiawch2dkrkp15mil7pyx7dvd810pwc22pm2q"; };
|
||||
, lookupSha256 ?
|
||||
if sha256map != null
|
||||
then { location, tag, ...}: sha256map."${location}"."${tag}"
|
||||
else _: null
|
||||
, extra-hackage-tarballs ? []
|
||||
# { # For a `source-repository-package` use the `location` and `tag` as the key
|
||||
# "https://github.com/jgm/pandoc-citeproc"."0.17"
|
||||
# = "0dxx8cp2xndpw3jwiawch2dkrkp15mil7pyx7dvd810pwc22pm2q";
|
||||
# # For a `repository` use the `url` as the key
|
||||
# "https://raw.githubusercontent.com/input-output-hk/hackage-overlay-ghcjs/bfc363b9f879c360e0a0460ec0c18ec87222ec32"
|
||||
# = "sha256-g9xGgJqYmiczjxjQ5JOiK5KUUps+9+nlNGI/0SpSOpg=";
|
||||
# };
|
||||
, extra-hackage-tarballs ? {}
|
||||
, source-repo-override ? {} # Cabal seems to behave incoherently when
|
||||
# two source-repository-package entries
|
||||
# provide the same packages, making it
|
||||
@ -192,7 +193,7 @@ let
|
||||
|
||||
replaceSourceRepos = projectFile:
|
||||
let
|
||||
fetchRepo = fetchgit: repoData:
|
||||
fetchPackageRepo = fetchgit: repoData:
|
||||
let
|
||||
fetched =
|
||||
if repoData.sha256 != null
|
||||
@ -200,7 +201,7 @@ let
|
||||
else
|
||||
let drv = builtins.fetchGit { inherit (repoData) url ref; };
|
||||
in __trace "WARNING: No sha256 found for source-repository-package ${repoData.url} ${repoData.ref} download may fail in restricted mode (hydra)"
|
||||
(__trace "Consider adding `--sha256: ${hashPath drv}` to the ${cabalProjectFileName} file or passing in a lookupSha256 argument"
|
||||
(__trace "Consider adding `--sha256: ${hashPath drv}` to the ${cabalProjectFileName} file or passing in a sha256map argument"
|
||||
drv);
|
||||
in {
|
||||
# Download the source-repository-package commit and add it to a minimal git
|
||||
@ -221,14 +222,13 @@ let
|
||||
tag = "minimal";
|
||||
};
|
||||
|
||||
blocks = pkgs.lib.splitString "\nsource-repository-package\n" ("\n" + projectFile);
|
||||
initialText = pkgs.lib.lists.take 1 blocks;
|
||||
repoBlocks = builtins.map (pkgs.haskell-nix.haskellLib.parseBlock cabalProjectFileName lookupSha256) (pkgs.lib.lists.drop 1 blocks);
|
||||
overrideSourceRepo = sourceRepo: (source-repo-override.${sourceRepo.url} or (pkgs.lib.id)) sourceRepo;
|
||||
sourceRepoData = pkgs.lib.lists.map (x: overrideSourceRepo x.sourceRepo) repoBlocks;
|
||||
otherText = pkgs.evalPackages.writeText "cabal.project" (pkgs.lib.strings.concatStringsSep "\n" (
|
||||
initialText
|
||||
++ (builtins.map (x: x.otherText) repoBlocks)));
|
||||
# Parse the `source-repository-package` blocks
|
||||
sourceRepoPackageResult = pkgs.haskell-nix.haskellLib.parseSourceRepositoryPackages
|
||||
cabalProjectFileName sha256map source-repo-override projectFile;
|
||||
|
||||
# Parse the `repository` blocks
|
||||
repoResult = pkgs.haskell-nix.haskellLib.parseRepositories
|
||||
cabalProjectFileName sha256map cabal-install nix-tools sourceRepoPackageResult.otherText;
|
||||
|
||||
# we need the repository content twice:
|
||||
# * at eval time (below to build the fixed project file)
|
||||
@ -239,12 +239,13 @@ let
|
||||
# on the target system would use, so that the derivation is unaffected
|
||||
# and, say, a linux release build job can identify the derivation
|
||||
# as built by a darwin builder, and fetch it from a cache
|
||||
sourceReposEval = builtins.map (fetchRepo pkgs.evalPackages.fetchgit) sourceRepoData;
|
||||
sourceReposBuild = builtins.map (x: (fetchRepo pkgs.fetchgit x).fetched) sourceRepoData;
|
||||
sourceReposEval = builtins.map (fetchPackageRepo pkgs.evalPackages.fetchgit) sourceRepoPackageResult.sourceRepos;
|
||||
sourceReposBuild = builtins.map (x: (fetchPackageRepo pkgs.fetchgit x).fetched) sourceRepoPackageResult.sourceRepos;
|
||||
in {
|
||||
sourceRepos = sourceReposBuild;
|
||||
inherit (repoResult) tarballs extra-hackages;
|
||||
makeFixedProjectFile = ''
|
||||
cp -f ${otherText} ./cabal.project
|
||||
cp -f ${pkgs.evalPackages.writeText "cabal.project" repoResult.updatedText} ./cabal.project
|
||||
'' +
|
||||
pkgs.lib.optionalString (builtins.length sourceReposEval != 0) (''
|
||||
chmod +w -R ./cabal.project
|
||||
@ -279,7 +280,7 @@ let
|
||||
|
||||
fixedProject =
|
||||
if rawCabalProject == null
|
||||
then { sourceRepos = []; makeFixedProjectFile = ""; replaceLocations = ""; }
|
||||
then { sourceRepos = []; tarballs = {}; extra-hackages = []; makeFixedProjectFile = ""; replaceLocations = ""; }
|
||||
else replaceSourceRepos rawCabalProject;
|
||||
|
||||
# The use of the actual GHC can cause significant problems:
|
||||
@ -524,7 +525,8 @@ let
|
||||
# some packages that will be excluded by `index-state-found`
|
||||
# which is used by cabal (cached-index-state >= index-state-found).
|
||||
dotCabal {
|
||||
inherit cabal-install nix-tools extra-hackage-tarballs;
|
||||
inherit cabal-install nix-tools;
|
||||
extra-hackage-tarballs = fixedProject.tarballs // extra-hackage-tarballs;
|
||||
index-state = cached-index-state;
|
||||
sha256 = index-sha256-found;
|
||||
}
|
||||
@ -610,5 +612,5 @@ in {
|
||||
projectNix = plan-nix;
|
||||
index-state = index-state-found;
|
||||
inherit src;
|
||||
inherit (fixedProject) sourceRepos;
|
||||
inherit (fixedProject) sourceRepos extra-hackages;
|
||||
}
|
||||
|
@ -275,7 +275,7 @@ in {
|
||||
|
||||
inherit (import ./cabal-project-parser.nix {
|
||||
inherit pkgs;
|
||||
}) parseIndexState parseBlock;
|
||||
}) parseIndexState parseSourceRepositoryPackages parseRepositories parseSourceRepositoryPackageBlock parseRepositoryBlock;
|
||||
|
||||
|
||||
cabalToNixpkgsLicense = import ./spdx/cabal.nix pkgs;
|
||||
|
@ -9,10 +9,6 @@
|
||||
# sha256map =
|
||||
# { "https://github.com/jgm/pandoc-citeproc"."0.17"
|
||||
# = "0dxx8cp2xndpw3jwiawch2dkrkp15mil7pyx7dvd810pwc22pm2q"; };
|
||||
, lookupSha256 ?
|
||||
if sha256map != null
|
||||
then { location, tag, ...}: sha256map."${location}"."${tag}"
|
||||
else _: null
|
||||
, branchMap ? null
|
||||
# A way to specify in which branch a git commit can
|
||||
# be found
|
||||
@ -85,12 +81,10 @@ in with pkgs.lib;
|
||||
concatMap (dep:
|
||||
let
|
||||
is-private = private dep.url;
|
||||
sha256 = if dep.sha256 != null
|
||||
then dep.sha256
|
||||
else lookupSha256 {
|
||||
location = dep.url;
|
||||
tag = dep.rev;
|
||||
};
|
||||
sha256 =
|
||||
if dep.sha256 != null then dep.sha256
|
||||
else if sha256map != null then { location, tag, ...}: sha256map."${dep.url}"."${dep.rev}"
|
||||
else null;
|
||||
branch = lookupBranch {
|
||||
location = dep.url;
|
||||
tag = dep.rev;
|
||||
|
@ -17,13 +17,13 @@
|
||||
pkgs:
|
||||
{ name, index }:
|
||||
|
||||
pkgs.evalPackages.runCommandLocal "hackage-repo-${name}" { nativeBuildInputs = [ pkgs.evalPackages.nix ]; } ''
|
||||
pkgs.evalPackages.runCommandLocal "hackage-repo-${name}" {} ''
|
||||
mkdir -p $out
|
||||
export expires="4000-01-01T00:00:00Z"
|
||||
|
||||
ln -sf ${index} $out/01-index.tar.gz
|
||||
export index_md5=$(nix-hash --flat --type md5 ${index})
|
||||
export index_sha256=$(nix-hash --flat --type sha256 ${index})
|
||||
export index_md5=$(md5sum ${index} | awk '{ print $1 }')
|
||||
export index_sha256=$(sha256sum ${index} | awk '{ print $1 }')
|
||||
${
|
||||
# When possible check the hash we calculate here against the `outputHash`
|
||||
# of the index derivation (when the `extra-hackages` feature is used the index
|
||||
@ -37,18 +37,18 @@ ${
|
||||
export index_length=$(stat --printf="%s" ${index})
|
||||
|
||||
substituteAll ${./root.json} $out/root.json
|
||||
export root_md5=$(nix-hash --flat --type md5 $out/root.json)
|
||||
export root_sha256=$(nix-hash --flat --type sha256 $out/root.json)
|
||||
export root_md5=$(md5sum $out/root.json | awk '{ print $1 }')
|
||||
export root_sha256=$(sha256sum $out/root.json | awk '{ print $1 }')
|
||||
export root_length=$(stat --printf="%s" $out/root.json)
|
||||
|
||||
substituteAll ${./mirrors.json} $out/mirrors.json
|
||||
export mirrors_md5=$(nix-hash --flat --type md5 $out/mirrors.json)
|
||||
export mirrors_sha256=$(nix-hash --flat --type sha256 $out/mirrors.json)
|
||||
export mirrors_md5=$(md5sum $out/mirrors.json | awk '{ print $1 }')
|
||||
export mirrors_sha256=$(sha256sum $out/mirrors.json | awk '{ print $1 }')
|
||||
export mirrors_length=$(stat --printf="%s" $out/mirrors.json)
|
||||
|
||||
substituteAll ${./snapshot.json} $out/snapshot.json
|
||||
export snapshot_md5=$(nix-hash --flat --type md5 $out/snapshot.json)
|
||||
export snapshot_sha256=$(nix-hash --flat --type sha256 $out/snapshot.json)
|
||||
export snapshot_md5=$(md5sum $out/snapshot.json | awk '{ print $1 }')
|
||||
export snapshot_sha256=$(sha256sum $out/snapshot.json | awk '{ print $1 }')
|
||||
export snapshot_length=$(stat --printf="%s" $out/snapshot.json)
|
||||
|
||||
substituteAll ${./timestamp.json} $out/timestamp.json
|
||||
|
@ -105,15 +105,9 @@ in {
|
||||
= "0dxx8cp2xndpw3jwiawch2dkrkp15mil7pyx7dvd810pwc22pm2q"; };
|
||||
'';
|
||||
};
|
||||
lookupSha256 = mkOption {
|
||||
type = nullOr unspecified;
|
||||
default = if config.sha256map != null
|
||||
then { location, tag, ...}: config.sha256map.${location}.${tag}
|
||||
else _: null;
|
||||
};
|
||||
extra-hackage-tarballs = mkOption {
|
||||
type = nullOr (listOf unspecified);
|
||||
default = [];
|
||||
type = nullOr attrs;
|
||||
default = {};
|
||||
};
|
||||
source-repo-override = mkOption {
|
||||
type = attrsOf (functionTo attrs);
|
||||
|
@ -72,12 +72,6 @@ with types;
|
||||
= "0dxx8cp2xndpw3jwiawch2dkrkp15mil7pyx7dvd810pwc22pm2q"; };
|
||||
'';
|
||||
};
|
||||
lookupSha256 = mkOption {
|
||||
type = nullOr unspecified;
|
||||
default = if config.sha256map != null
|
||||
then { location, tag, ...}: config.sha256map.${location}.${tag}
|
||||
else _: null;
|
||||
};
|
||||
branchMap = mkOption {
|
||||
type = nullOr unspecified;
|
||||
default = null;
|
||||
|
@ -43,10 +43,9 @@ in { haskell-nix = prev.haskell-nix // {
|
||||
pandoc = {
|
||||
# Function that returns a sha256 string by looking up the location
|
||||
# and tag in a nested attrset
|
||||
lookupSha256 = { location, tag, ... }:
|
||||
sha256map =
|
||||
{ "https://github.com/jgm/pandoc-citeproc"."0.17"
|
||||
= "0dxx8cp2xndpw3jwiawch2dkrkp15mil7pyx7dvd810pwc22pm2q"; }
|
||||
."${location}"."${tag}";
|
||||
= "0dxx8cp2xndpw3jwiawch2dkrkp15mil7pyx7dvd810pwc22pm2q"; };
|
||||
};
|
||||
|
||||
# See https://github.com/input-output-hk/haskell.nix/issues/948
|
||||
|
@ -189,8 +189,7 @@ final: prev: {
|
||||
hackageTarball = { index-state, sha256, nix-tools ? final.haskell-nix.nix-tools, ... }:
|
||||
assert sha256 != null;
|
||||
let at = builtins.replaceStrings [":"] [""] index-state; in
|
||||
{ name = "hackage.haskell.org-at-${at}";
|
||||
index = final.evalPackages.fetchurl {
|
||||
{ "hackage.haskell.org-at-${at}" = final.evalPackages.fetchurl {
|
||||
name = "01-index.tar.gz-at-${at}";
|
||||
url = "https://hackage.haskell.org/01-index.tar.gz";
|
||||
downloadToTemp = true;
|
||||
@ -204,10 +203,10 @@ final: prev: {
|
||||
# Creates Cabal local repository from { name, index } set.
|
||||
mkLocalHackageRepo = import ../mk-local-hackage-repo final;
|
||||
|
||||
dotCabal = { index-state, sha256, cabal-install, extra-hackage-tarballs ? [], ... }@args:
|
||||
dotCabal = { index-state, sha256, cabal-install, extra-hackage-tarballs ? {}, ... }@args:
|
||||
let
|
||||
allTarballs = [ (hackageTarball args) ] ++ extra-hackage-tarballs;
|
||||
allNames = final.lib.concatMapStringsSep "-" (tarball: tarball.name) allTarballs;
|
||||
allTarballs = hackageTarball args // extra-hackage-tarballs;
|
||||
allNames = final.lib.concatStringsSep "-" (builtins.attrNames allTarballs);
|
||||
# Main Hackage index-state is embedded in its name and thus will propagate to
|
||||
# dotCabalName anyway.
|
||||
dotCabalName = "dot-cabal-" + allNames;
|
||||
@ -217,10 +216,10 @@ final: prev: {
|
||||
mkdir -p $out/.cabal
|
||||
cat <<EOF > $out/.cabal/config
|
||||
${final.lib.concatStrings (
|
||||
map (tarball:
|
||||
final.lib.mapAttrsToList (name: index:
|
||||
''
|
||||
repository ${tarball.name}
|
||||
url: file:${mkLocalHackageRepo tarball}
|
||||
repository ${name}
|
||||
url: file:${mkLocalHackageRepo { inherit name index; }}
|
||||
secure: True
|
||||
root-keys:
|
||||
key-threshold: 0
|
||||
@ -231,13 +230,13 @@ final: prev: {
|
||||
|
||||
# All repositories must be mkdir'ed before calling new-update on any repo,
|
||||
# otherwise it fails.
|
||||
${final.lib.concatStrings (map ({ name, ... }: ''
|
||||
${final.lib.concatStrings (map (name: ''
|
||||
mkdir -p $out/.cabal/packages/${name}
|
||||
'') allTarballs)}
|
||||
'') (builtins.attrNames allTarballs))}
|
||||
|
||||
${final.lib.concatStrings (map ({ name, ... }: ''
|
||||
${final.lib.concatStrings (map (name: ''
|
||||
HOME=$out cabal new-update ${name}
|
||||
'') allTarballs)}
|
||||
'') (builtins.attrNames allTarballs))}
|
||||
'';
|
||||
|
||||
# Some of features of haskell.nix rely on using a hackage index
|
||||
@ -515,7 +514,7 @@ final: prev: {
|
||||
++ final.lib.optional (args.ghcOverride != null || args.ghc != null)
|
||||
{ ghc.package = if args.ghcOverride != null then args.ghcOverride else args.ghc; }
|
||||
++ [ { compiler.nix-name = final.lib.mkForce args.compiler-nix-name; } ];
|
||||
extra-hackages = args.extra-hackages or [];
|
||||
extra-hackages = args.extra-hackages or [] ++ callProjectResults.extra-hackages;
|
||||
};
|
||||
|
||||
project = addProjectAndPackageAttrs rec {
|
||||
|
@ -152,7 +152,7 @@ let
|
||||
# An empty list means success.
|
||||
unitTests =
|
||||
let
|
||||
tests = haskell-nix.callPackage ./unit.nix {};
|
||||
tests = haskell-nix.callPackage ./unit.nix { inherit compiler-nix-name; };
|
||||
testsFailedEcho = lib.concatMapStringsSep "\n" (t: "echo ${t.name} failed") tests;
|
||||
testsFinalLine = if builtins.length tests == 0 then "\ntouch $out" else "\nexit 1";
|
||||
testsScript = testsFailedEcho + testsFinalLine;
|
||||
@ -186,11 +186,12 @@ let
|
||||
stack-source-repo = callTest ./stack-source-repo { inherit compiler-nix-name; };
|
||||
cabal-doctests = callTest ./cabal-doctests { inherit util compiler-nix-name; };
|
||||
extra-hackage = callTest ./extra-hackage { inherit compiler-nix-name; };
|
||||
ghcjs-overlay = callTest ./ghcjs-overlay { inherit compiler-nix-name; };
|
||||
hls-cabal = callTest ./haskell-language-server/cabal.nix { inherit compiler-nix-name; };
|
||||
hls-stack = callTest ./haskell-language-server/stack.nix { inherit compiler-nix-name; };
|
||||
cabal-hpack = callTest ./cabal-hpack { inherit util compiler-nix-name; };
|
||||
index-state = callTest ./index-state { inherit compiler-nix-name; };
|
||||
lookup-sha256 = callTest ./lookup-sha256 { inherit compiler-nix-name; };
|
||||
sha256map = callTest ./sha256map { inherit compiler-nix-name; };
|
||||
# fully-static = callTest ./fully-static { inherit (pkgs) buildPackages; };
|
||||
shell-for = callTest ./shell-for { inherit compiler-nix-name; };
|
||||
cabal-22 = callTest ./cabal-22 { inherit util compiler-nix-name; };
|
||||
|
@ -6,9 +6,8 @@ let
|
||||
|
||||
hackage = import ./hackage;
|
||||
|
||||
tarball = {
|
||||
name = "extra-hackage-demo";
|
||||
index = ./01-index.tar.gz;
|
||||
tarballs = {
|
||||
extra-hackage-demo = ./01-index.tar.gz;
|
||||
};
|
||||
|
||||
demo-src = ./external-package-demo-0.1.0.0.tar.gz;
|
||||
@ -18,7 +17,7 @@ let
|
||||
src = testSrc "extra-hackage/external-package-user";
|
||||
|
||||
extra-hackages = [ hackage ];
|
||||
extra-hackage-tarballs = [ tarball ];
|
||||
extra-hackage-tarballs = tarballs;
|
||||
|
||||
modules = [
|
||||
# To prevent nix-build from trying to download it from the
|
||||
|
@ -1,4 +1,8 @@
|
||||
packages: *.cabal
|
||||
|
||||
repository local
|
||||
url: http://127.0.0.1:7777
|
||||
-- Including `repository` here now actually causes haskell.nix to try
|
||||
-- to download the repository. Luckily this test still works with this
|
||||
-- commented out.
|
||||
-- See the ghcjs-overlays test for an example of how to use `repository` blocks.
|
||||
-- repository local
|
||||
-- url: http://127.0.0.1:7777
|
||||
|
5
test/ghcjs-overlay/CHANGELOG.md
Normal file
5
test/ghcjs-overlay/CHANGELOG.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Revision history for external-package-user
|
||||
|
||||
## 0.1.0.0 -- YYYY-mm-dd
|
||||
|
||||
* First version. Released on an unsuspecting world.
|
8
test/ghcjs-overlay/Main.hs
Normal file
8
test/ghcjs-overlay/Main.hs
Normal file
@ -0,0 +1,8 @@
|
||||
module Main where
|
||||
|
||||
import qualified MyLib (someFunc)
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
putStrLn "Hello, Haskell!"
|
||||
MyLib.someFunc
|
4
test/ghcjs-overlay/MyLib.hs
Normal file
4
test/ghcjs-overlay/MyLib.hs
Normal file
@ -0,0 +1,4 @@
|
||||
module MyLib (someFunc) where
|
||||
|
||||
someFunc :: IO ()
|
||||
someFunc = putStrLn "someFunc"
|
2
test/ghcjs-overlay/Setup.hs
Normal file
2
test/ghcjs-overlay/Setup.hs
Normal file
@ -0,0 +1,2 @@
|
||||
import Distribution.Simple
|
||||
main = defaultMain
|
9
test/ghcjs-overlay/cabal.project
Normal file
9
test/ghcjs-overlay/cabal.project
Normal file
@ -0,0 +1,9 @@
|
||||
packages: *.cabal
|
||||
|
||||
repository ghcjs-overlay
|
||||
url: https://raw.githubusercontent.com/input-output-hk/hackage-overlay-ghcjs/bfc363b9f879c360e0a0460ec0c18ec87222ec32
|
||||
secure: True
|
||||
root-keys:
|
||||
key-threshold: 0
|
||||
--sha256: sha256-g9xGgJqYmiczjxjQ5JOiK5KUUps+9+nlNGI/0SpSOpg=
|
||||
|
52
test/ghcjs-overlay/default.nix
Normal file
52
test/ghcjs-overlay/default.nix
Normal file
@ -0,0 +1,52 @@
|
||||
{ stdenv, lib, cabalProject', haskellLib, recurseIntoAttrs, testSrc, compiler-nix-name }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
project = cabalProject' {
|
||||
src = testSrc "ghcjs-overlay";
|
||||
inherit compiler-nix-name;
|
||||
# Alternative to the --sha256 comment in cabal.project
|
||||
# sha256map = {
|
||||
# "https://raw.githubusercontent.com/input-output-hk/hackage-overlay-ghcjs/bfc363b9f879c360e0a0460ec0c18ec87222ec32" =
|
||||
# "sha256-g9xGgJqYmiczjxjQ5JOiK5KUUps+9+nlNGI/0SpSOpg=";
|
||||
# };
|
||||
};
|
||||
packages = project.hsPkgs;
|
||||
|
||||
in recurseIntoAttrs {
|
||||
ifdInputs = {
|
||||
inherit (project) plan-nix;
|
||||
};
|
||||
run = stdenv.mkDerivation {
|
||||
name = "ghcjs-overlay-test";
|
||||
|
||||
buildCommand = ''
|
||||
exe="${packages.ghcjs-overlay-test.components.exes.ghcjs-overlay-test.exePath}"
|
||||
size=$(command stat --format '%s' "$exe")
|
||||
printf "size of executable $exe is $size. \n" >& 2
|
||||
# fixme: run on target platform when cross-compiled
|
||||
printf "checking whether executable runs... " >& 2
|
||||
cat ${haskellLib.check packages.ghcjs-overlay-test.components.exes.ghcjs-overlay-test}/test-stdout
|
||||
'' + (if stdenv.hostPlatform.isMusl
|
||||
then ''
|
||||
printf "checking that executable is statically linked... " >& 2
|
||||
(ldd $exe 2>&1 || true) | grep -i "not a"
|
||||
''
|
||||
else
|
||||
# Skip this on aarch as we do not have an `ldd` tool
|
||||
optionalString (!stdenv.hostPlatform.isAarch32 && !stdenv.hostPlatform.isAarch64) (''
|
||||
printf "checking that executable is dynamically linked to system libraries... " >& 2
|
||||
'' + optionalString stdenv.isLinux ''
|
||||
ldd $exe | grep libpthread
|
||||
'' + optionalString stdenv.isDarwin ''
|
||||
otool -L $exe |grep .dylib
|
||||
'')) + ''
|
||||
touch $out
|
||||
'';
|
||||
meta.platforms = platforms.all;
|
||||
passthru = {
|
||||
inherit project;
|
||||
};
|
||||
};
|
||||
}
|
21
test/ghcjs-overlay/ghcjs-overlay-test.cabal
Normal file
21
test/ghcjs-overlay/ghcjs-overlay-test.cabal
Normal file
@ -0,0 +1,21 @@
|
||||
cabal-version: 2.4
|
||||
name: ghcjs-overlay-test
|
||||
version: 0.1.0.0
|
||||
synopsis: User package
|
||||
description: Uses ghcjs-overlay to get patched double-conversion
|
||||
license: BSD-3-Clause
|
||||
author: Hamish Mackenzie
|
||||
maintainer: Hamish.K.Mackenzie@gmail.com
|
||||
extra-source-files: CHANGELOG.md
|
||||
|
||||
library
|
||||
exposed-modules: MyLib
|
||||
build-depends: base < 5,
|
||||
double-conversion ==2.0.2.0
|
||||
default-language: Haskell2010
|
||||
|
||||
executable ghcjs-overlay-test
|
||||
main-is: Main.hs
|
||||
other-modules: MyLib
|
||||
build-depends: base, ghcjs-overlay-test
|
||||
default-language: Haskell2010
|
@ -11,10 +11,9 @@
|
||||
version = "2.9.2.1";
|
||||
# Function that returns a sha256 string by looking up the location
|
||||
# and tag in a nested attrset
|
||||
lookupSha256 = { location, tag, ... }:
|
||||
sha256map =
|
||||
{ "https://github.com/jgm/pandoc-citeproc"."0.17"
|
||||
= "0dxx8cp2xndpw3jwiawch2dkrkp15mil7pyx7dvd810pwc22pm2q"; }
|
||||
."${location}"."${tag}";
|
||||
= "0dxx8cp2xndpw3jwiawch2dkrkp15mil7pyx7dvd810pwc22pm2q"; };
|
||||
cabalProjectLocal = ''
|
||||
allow-newer: *:base
|
||||
'';
|
129
test/unit.nix
129
test/unit.nix
@ -1,4 +1,4 @@
|
||||
{ pkgs, lib, haskellLib }:
|
||||
{ pkgs, lib, haskellLib, compiler-nix-name }:
|
||||
|
||||
let
|
||||
emptyConfig = {
|
||||
@ -58,7 +58,7 @@ lib.runTests {
|
||||
};
|
||||
|
||||
testParseBlock1 = {
|
||||
expr = __toJSON (haskellLib.parseBlock "cabal.project" (_: null) ''
|
||||
expr = __toJSON (haskellLib.parseSourceRepositoryPackageBlock "cabal.project" {} ''
|
||||
type: git
|
||||
location: https://github.com/input-output-hk/haskell.nix.git
|
||||
tag: 487eea1c249537d34c27f6143dff2b9d5586c657
|
||||
@ -72,7 +72,7 @@ lib.runTests {
|
||||
};
|
||||
|
||||
testParseBlock2 = {
|
||||
expr = __toJSON (haskellLib.parseBlock "cabal.project" (_: null) ''
|
||||
expr = __toJSON (haskellLib.parseSourceRepositoryPackageBlock "cabal.project" {} ''
|
||||
type: git
|
||||
location: https://github.com/input-output-hk/haskell.nix.git
|
||||
tag: 487eea1c249537d34c27f6143dff2b9d5586c657
|
||||
@ -87,7 +87,7 @@ lib.runTests {
|
||||
};
|
||||
|
||||
testParseBlock3 = {
|
||||
expr = __toJSON (haskellLib.parseBlock "cabal.project" (_: null) ''
|
||||
expr = __toJSON (haskellLib.parseSourceRepositoryPackageBlock "cabal.project" {} ''
|
||||
type: git
|
||||
location: https://github.com/input-output-hk/haskell.nix.git
|
||||
tag: 487eea1c249537d34c27f6143dff2b9d5586c657
|
||||
@ -102,7 +102,7 @@ lib.runTests {
|
||||
};
|
||||
|
||||
testParseBlock4 = {
|
||||
expr = __toJSON (haskellLib.parseBlock "cabal.project" (_: null) ''
|
||||
expr = __toJSON (haskellLib.parseSourceRepositoryPackageBlock "cabal.project" {} ''
|
||||
type: git
|
||||
location: https://github.com/input-output-hk/haskell.nix.git
|
||||
tag: 487eea1c249537d34c27f6143dff2b9d5586c657
|
||||
@ -117,4 +117,123 @@ lib.runTests {
|
||||
sourceRepo = testRepoData // { subdirs = ["dir1" "dir2"]; };
|
||||
};
|
||||
};
|
||||
|
||||
testParseRepositoryBlock = {
|
||||
expr = __toJSON (haskellLib.parseRepositoryBlock "cabal.project" {}
|
||||
pkgs.evalPackages.haskell-nix.cabal-install.${compiler-nix-name}
|
||||
pkgs.evalPackages.haskell-nix.nix-tools.${compiler-nix-name} ''
|
||||
ghcjs-overlay
|
||||
url: https://raw.githubusercontent.com/input-output-hk/hackage-overlay-ghcjs/bfc363b9f879c360e0a0460ec0c18ec87222ec32
|
||||
secure: True
|
||||
root-keys:
|
||||
key-threshold: 0
|
||||
--sha256: sha256-g9xGgJqYmiczjxjQ5JOiK5KUUps+9+nlNGI/0SpSOpg=
|
||||
-- end of block
|
||||
'');
|
||||
expected = __toJSON {
|
||||
name = "ghcjs-overlay";
|
||||
updatedText = ''
|
||||
repository ghcjs-overlay
|
||||
url: file:/nix/store/0lx8536b53bqssqzzbyzi22j117a7q2g-ghcjs-overlay/.cabal/packages/ghcjs-overlay
|
||||
secure: True
|
||||
root-keys:
|
||||
key-threshold: 0
|
||||
-- end of block
|
||||
'';
|
||||
home = "/nix/store/0lx8536b53bqssqzzbyzi22j117a7q2g-ghcjs-overlay";
|
||||
tarball = {
|
||||
ghcjs-overlay = "/nix/store/0lx8536b53bqssqzzbyzi22j117a7q2g-ghcjs-overlay/.cabal/packages/ghcjs-overlay/01-index.tar.gz";
|
||||
};
|
||||
hackage = {
|
||||
Cabal = {
|
||||
"3.2.1.0" = {
|
||||
revisions = {
|
||||
default = "/nix/store/3ndxx3k43gmjkfl1qn1x39g15hz5amad-Cabal-3.2.1.0-r0-2b5309e942658e3b16e6938115867538e70a647d98e3dc967f2be20d6b886e61.nix";
|
||||
r0 = "/nix/store/3ndxx3k43gmjkfl1qn1x39g15hz5amad-Cabal-3.2.1.0-r0-2b5309e942658e3b16e6938115867538e70a647d98e3dc967f2be20d6b886e61.nix";
|
||||
};
|
||||
sha256 = "826970f742b63d751f6fe3be7f862b7b1e419ddfafef3014c01de54f12874a4a";
|
||||
};
|
||||
};
|
||||
basement = {
|
||||
"0.0.12"= {
|
||||
revisions = {
|
||||
default = "/nix/store/3h1xwcij240kj243f23siw3p30hdbnrj-basement-0.0.12-r0-600669787199915545f99754496f13f955203b94dbb31de50093362c03367bb7.nix";
|
||||
r0 = "/nix/store/3h1xwcij240kj243f23siw3p30hdbnrj-basement-0.0.12-r0-600669787199915545f99754496f13f955203b94dbb31de50093362c03367bb7.nix";
|
||||
};
|
||||
sha256 = "cf8f96fd92438739a516881abb7e14747118e82a12634d44acc83173fb87f535";
|
||||
};
|
||||
};
|
||||
clock = {
|
||||
"0.8.2" = {
|
||||
revisions = {
|
||||
default = "/nix/store/mdsf1fgbpi4m1yvsg5z8z4hk5w7i63x7-clock-0.8.2-r0-2a8441d9f531bb51bb1806e56e9e9a43e5f0214faea4f31219c15120128ca43a.nix";
|
||||
r0 = "/nix/store/mdsf1fgbpi4m1yvsg5z8z4hk5w7i63x7-clock-0.8.2-r0-2a8441d9f531bb51bb1806e56e9e9a43e5f0214faea4f31219c15120128ca43a.nix";
|
||||
};
|
||||
sha256 = "57715a01df74568c638f1138b53642094de420bafd519e9f53ec7fe92876121e";
|
||||
};
|
||||
};
|
||||
cryptonite = {
|
||||
"0.29" = {
|
||||
revisions = {
|
||||
default = "/nix/store/i84rvw53j9b6p53dalg6xq85blrkrk01-cryptonite-0.29-r0-231db2acdaefc978865af9b72a6e65c4ebc70238174a7ad9076d68900f3d866d.nix";
|
||||
r0 = "/nix/store/i84rvw53j9b6p53dalg6xq85blrkrk01-cryptonite-0.29-r0-231db2acdaefc978865af9b72a6e65c4ebc70238174a7ad9076d68900f3d866d.nix";
|
||||
};
|
||||
sha256 = "f104836bdaeed5243ff7e9fc0757d7255778f0af22976eef2b7789e7e1094283";
|
||||
};
|
||||
};
|
||||
double-conversion = {
|
||||
"2.0.2.0" = {
|
||||
revisions = {
|
||||
default = "/nix/store/cb41xbmf6abcq30sj2a1b00qim8nyhqx-double-conversion-2.0.2.0-r0-698f94e66b6263a1049b56ede47aa48e224c764f345c3130265742513443595b.nix";
|
||||
r0 = "/nix/store/cb41xbmf6abcq30sj2a1b00qim8nyhqx-double-conversion-2.0.2.0-r0-698f94e66b6263a1049b56ede47aa48e224c764f345c3130265742513443595b.nix";
|
||||
};
|
||||
sha256 = "67c83bf4619624ef6b950578664cbcd3bc12eaed0d7a387997db5e0ba29fb140";
|
||||
};
|
||||
};
|
||||
foundation = {
|
||||
"0.0.26.1" = {
|
||||
revisions = {
|
||||
default = "/nix/store/5vw12rxa3as8b82kz1arddwzs45fzj6q-foundation-0.0.26.1-r0-9a2f63a33dc6b3c1425c4755522b8e619d04fdfcfef72e358155b965b28745a8.nix";
|
||||
r0 = "/nix/store/5vw12rxa3as8b82kz1arddwzs45fzj6q-foundation-0.0.26.1-r0-9a2f63a33dc6b3c1425c4755522b8e619d04fdfcfef72e358155b965b28745a8.nix";
|
||||
};
|
||||
sha256 = "3c588f6bcf875762ac18b03b17a7ee3c0c60c8e2c884c0192269b0a97e89d526";
|
||||
};
|
||||
};
|
||||
network = {
|
||||
"3.1.2.1" = {
|
||||
revisions = {
|
||||
default = "/nix/store/sfc02hqr02pa3rwhha1skvlkiwmgvsf7-network-3.1.2.1-r0-ed4b1bb733613df5a2ebecd5533d08f20bacb0dc59ed207fd4b4670fe718713f.nix";
|
||||
r0 = "/nix/store/sfc02hqr02pa3rwhha1skvlkiwmgvsf7-network-3.1.2.1-r0-ed4b1bb733613df5a2ebecd5533d08f20bacb0dc59ed207fd4b4670fe718713f.nix";
|
||||
};
|
||||
sha256 = "21869fd942cb9996ba26ba9418cdd44ac869f81caba08e5a2b2cdfe792ae4518";
|
||||
};
|
||||
"3.1.2.5" = {
|
||||
revisions = {
|
||||
default = "/nix/store/rrh5f3hb8g5bwgd6y7lwfky3nrgsg5b2-network-3.1.2.5-r0-433a5e076aaa8eb3e4158abae78fb409c6bd754e9af99bc2e87583d2bcd8404a.nix";
|
||||
r0 = "/nix/store/rrh5f3hb8g5bwgd6y7lwfky3nrgsg5b2-network-3.1.2.5-r0-433a5e076aaa8eb3e4158abae78fb409c6bd754e9af99bc2e87583d2bcd8404a.nix";
|
||||
};
|
||||
sha256 = "ee914e9b43bfb0f415777eb0473236803b14a35d48f6172079260c92c6ceb335";
|
||||
};
|
||||
};
|
||||
terminal-size = {
|
||||
"0.3.2.1" = {
|
||||
revisions = {
|
||||
default = "/nix/store/k9gk020ygp6j94sa3xv46fkgrc8jl5zn-terminal-size-0.3.2.1-r0-7b2d8e0475a46961d07ddfb91dee618de70eff55d9ba0402ebeac1f9dcf9b18b.nix";
|
||||
r0 = "/nix/store/k9gk020ygp6j94sa3xv46fkgrc8jl5zn-terminal-size-0.3.2.1-r0-7b2d8e0475a46961d07ddfb91dee618de70eff55d9ba0402ebeac1f9dcf9b18b.nix";
|
||||
};
|
||||
sha256 = "8e4fbfea182f3bf5769744196ca88bb2cb1c80caa617debe34336f90db27131e";
|
||||
};
|
||||
};
|
||||
unix-compat = {
|
||||
"0.5.3" = {
|
||||
revisions = {
|
||||
default = "/nix/store/mc1vh6wzg0vp1c1srxrqmpv9fsqay6dw-unix-compat-0.5.3-r0-9c6d68f9afb5baa6be55e8415dd401835ce0d4dfc2090f1c169fcd61c152ebac.nix";
|
||||
r0 = "/nix/store/mc1vh6wzg0vp1c1srxrqmpv9fsqay6dw-unix-compat-0.5.3-r0-9c6d68f9afb5baa6be55e8415dd401835ce0d4dfc2090f1c169fcd61c152ebac.nix";
|
||||
};
|
||||
sha256 = "2fe56781422d5caf47dcbbe82c998bd33f429f8c7093483fad36cd2d31dbdceb";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user