diff --git a/changelog.md b/changelog.md index 5e8fcaf9..5f6dbe98 100644 --- a/changelog.md +++ b/changelog.md @@ -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`). diff --git a/lib/cabal-project-parser.nix b/lib/cabal-project-parser.nix index e54119bb..8735602b 100644 --- a/lib/cabal-project-parser.nix +++ b/lib/cabal-project-parser.nix @@ -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 < $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; } diff --git a/lib/call-cabal-project-to-nix.nix b/lib/call-cabal-project-to-nix.nix index cb42f737..75aa4b70 100644 --- a/lib/call-cabal-project-to-nix.nix +++ b/lib/call-cabal-project-to-nix.nix @@ -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; } diff --git a/lib/default.nix b/lib/default.nix index 2bb6a675..42073595 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -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; diff --git a/lib/stack-cache-generator.nix b/lib/stack-cache-generator.nix index 8756913a..847e7da0 100644 --- a/lib/stack-cache-generator.nix +++ b/lib/stack-cache-generator.nix @@ -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; diff --git a/mk-local-hackage-repo/default.nix b/mk-local-hackage-repo/default.nix index fdef900a..4ebed246 100644 --- a/mk-local-hackage-repo/default.nix +++ b/mk-local-hackage-repo/default.nix @@ -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 diff --git a/modules/cabal-project.nix b/modules/cabal-project.nix index 54afab78..ddb9d578 100644 --- a/modules/cabal-project.nix +++ b/modules/cabal-project.nix @@ -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); diff --git a/modules/stack-project.nix b/modules/stack-project.nix index c87601c8..a207d301 100644 --- a/modules/stack-project.nix +++ b/modules/stack-project.nix @@ -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; diff --git a/overlays/hackage-quirks.nix b/overlays/hackage-quirks.nix index c71edd9a..7010950c 100644 --- a/overlays/hackage-quirks.nix +++ b/overlays/hackage-quirks.nix @@ -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 diff --git a/overlays/haskell.nix b/overlays/haskell.nix index fdbfd24d..dd2c5270 100644 --- a/overlays/haskell.nix +++ b/overlays/haskell.nix @@ -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 < $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 { diff --git a/test/default.nix b/test/default.nix index fcb13ad5..31e77b8d 100644 --- a/test/default.nix +++ b/test/default.nix @@ -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; }; diff --git a/test/extra-hackage/default.nix b/test/extra-hackage/default.nix index 40d8c407..c9e42a4e 100644 --- a/test/extra-hackage/default.nix +++ b/test/extra-hackage/default.nix @@ -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 diff --git a/test/extra-hackage/external-package-user/cabal.project b/test/extra-hackage/external-package-user/cabal.project index 013aeca6..5563086a 100644 --- a/test/extra-hackage/external-package-user/cabal.project +++ b/test/extra-hackage/external-package-user/cabal.project @@ -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 diff --git a/test/ghcjs-overlay/CHANGELOG.md b/test/ghcjs-overlay/CHANGELOG.md new file mode 100644 index 00000000..1b3a4d2f --- /dev/null +++ b/test/ghcjs-overlay/CHANGELOG.md @@ -0,0 +1,5 @@ +# Revision history for external-package-user + +## 0.1.0.0 -- YYYY-mm-dd + +* First version. Released on an unsuspecting world. diff --git a/test/ghcjs-overlay/Main.hs b/test/ghcjs-overlay/Main.hs new file mode 100644 index 00000000..60d904e8 --- /dev/null +++ b/test/ghcjs-overlay/Main.hs @@ -0,0 +1,8 @@ +module Main where + +import qualified MyLib (someFunc) + +main :: IO () +main = do + putStrLn "Hello, Haskell!" + MyLib.someFunc diff --git a/test/ghcjs-overlay/MyLib.hs b/test/ghcjs-overlay/MyLib.hs new file mode 100644 index 00000000..e657c440 --- /dev/null +++ b/test/ghcjs-overlay/MyLib.hs @@ -0,0 +1,4 @@ +module MyLib (someFunc) where + +someFunc :: IO () +someFunc = putStrLn "someFunc" diff --git a/test/ghcjs-overlay/Setup.hs b/test/ghcjs-overlay/Setup.hs new file mode 100644 index 00000000..9a994af6 --- /dev/null +++ b/test/ghcjs-overlay/Setup.hs @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain diff --git a/test/ghcjs-overlay/cabal.project b/test/ghcjs-overlay/cabal.project new file mode 100644 index 00000000..d9c071dd --- /dev/null +++ b/test/ghcjs-overlay/cabal.project @@ -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= + diff --git a/test/ghcjs-overlay/default.nix b/test/ghcjs-overlay/default.nix new file mode 100644 index 00000000..88e23600 --- /dev/null +++ b/test/ghcjs-overlay/default.nix @@ -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; + }; + }; +} diff --git a/test/ghcjs-overlay/ghcjs-overlay-test.cabal b/test/ghcjs-overlay/ghcjs-overlay-test.cabal new file mode 100644 index 00000000..a4e6ffa6 --- /dev/null +++ b/test/ghcjs-overlay/ghcjs-overlay-test.cabal @@ -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 diff --git a/test/lookup-sha256/default.nix b/test/sha256map/default.nix similarity index 91% rename from test/lookup-sha256/default.nix rename to test/sha256map/default.nix index 4333149c..ee35c1b8 100644 --- a/test/lookup-sha256/default.nix +++ b/test/sha256map/default.nix @@ -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 ''; diff --git a/test/unit.nix b/test/unit.nix index 366d81a9..3fca4b98 100644 --- a/test/unit.nix +++ b/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"; + }; + }; + }; + }; + }; }