|
| 1 | +{ mkHackageIndex, pkgs, runCommand, nix-tools, cabal-install, ghc, hpack, symlinkJoin }: |
| 2 | +let defaultGhc = ghc; |
| 3 | + defaultCabalInstall = cabal-install; |
| 4 | +in { hackageIndexState, src, ghc ? defaultGhc, cabal-install ? defaultCabalInstall }: |
| 5 | +let |
| 6 | + cabalFiles = |
| 7 | + pkgs.lib.cleanSourceWith { |
| 8 | + inherit src; |
| 9 | + filter = path: type: |
| 10 | + type == "directory" || |
| 11 | + pkgs.lib.any (i: (pkgs.lib.hasSuffix i path)) [ ".project" ".cabal" "package.yaml" ]; |
| 12 | + }; |
| 13 | + plan = if (builtins.compareVersions cabal-install.version "2.4.0.0") < 0 |
| 14 | + # cabal-install versions before 2.4 will generate insufficient plan information. |
| 15 | + then throw "cabal-install (current version: ${cabal-install.version}) needs to be at least 2.4 for plan-to-nix to work without cabal-to-nix" |
| 16 | + else runCommand "plan" { |
| 17 | + nativeBuildInputs = [ nix-tools ghc hpack cabal-install pkgs.rsync ]; |
| 18 | + } '' |
| 19 | + tmp=$(mktemp -d) |
| 20 | + cd $tmp |
| 21 | + cp -r ${cabalFiles}/* . |
| 22 | + chmod +w -R . |
| 23 | + # warning: this may not generate the proper cabal file. |
| 24 | + # hpack allows globbing, and turns that into module lists |
| 25 | + # without the source available (we cleaneSourceWith'd it), |
| 26 | + # this may not produce the right result. |
| 27 | + find . -name package.yaml -exec hpack "{}" \; |
| 28 | + HOME=${mkHackageIndex hackageIndexState} cabal new-configure |
| 29 | +
|
| 30 | + export LANG=C.utf8 # Needed or stack-to-nix will die on unicode inputs |
| 31 | + mkdir -p $out |
| 32 | +
|
| 33 | + # ensure we have all our .cabal files (also those generated from package.yaml) files. |
| 34 | + # otherwise we'd need to be careful about putting the `cabal-generator = hpack` into |
| 35 | + # the nix expression. As we already called `hpack` on all `package.yaml` files we can |
| 36 | + # skip that step and just package the .cabal files up as well. |
| 37 | + # |
| 38 | + # This is also important as `plan-to-nix` will look for the .cabal files when generating |
| 39 | + # the relevant `pkgs.nix` file with the local .cabal expressions. |
| 40 | + rsync -a --prune-empty-dirs \ |
| 41 | + --include '*/' --include '*.cabal' --include 'package.yaml' \ |
| 42 | + --exclude '*' \ |
| 43 | + $tmp/ $out/ |
| 44 | +
|
| 45 | + # make sure the path's in the plan.json are relative to $out instead of $tmp |
| 46 | + # this is necessary so that plan-to-nix relative path logic can work. |
| 47 | + substituteInPlace $tmp/dist-newstyle/cache/plan.json --replace "$tmp" "$out" |
| 48 | +
|
| 49 | + # run `plan-to-nix` in $out. This should produce files right there with the |
| 50 | + # proper relative paths. |
| 51 | + (cd $out && plan-to-nix --plan-json $tmp/dist-newstyle/cache/plan.json -o .) |
| 52 | +
|
| 53 | + # move pkgs.nix to default.nix ensure we can just nix `import` the result. |
| 54 | + mv $out/pkgs.nix $out/default.nix |
| 55 | + ''; |
| 56 | +in |
| 57 | + runCommand "plan-and-src" { nativeBuildInputs = [ pkgs.xorg.lndir pkgs.rsync ]; } '' |
| 58 | + mkdir $out |
| 59 | + # todo: should we clean `src` to drop any .git, .nix, ... other irelevant files? |
| 60 | + lndir -silent "${src}" "$out" |
| 61 | + rsync -a ${plan}/ $out/ |
| 62 | + '' |
0 commit comments