haskell-te: f5d9b0b4404b6f45ddb4c063be4ce0cc5b488b7e

     1: { bash, checkStderr, fail, haskellPackages, haskellPkgNameVersion,
     2:   haveVar, hsNameVersion, jq, lib, mkBin, python, runCommand, withDeps,
     3:   writeScript }:
     4: with builtins;
     5: with lib;
     6: 
     7: with rec {
     8:   inherit (haskellPackages) cabal-install;
     9: 
    10:   # Runs AstPlugin. Requires GHC_PKG to point at a pkg-db containing all of
    11:   # the required dependencies, plus AstPlugin
    12:   runAstPluginRaw = mkBin {
    13:     name   = "runAstPluginRaw";
    14:     paths  = [ bash ];
    15:     script = ''
    16:       #!${bash}/bin/bash
    17:       set -e
    18: 
    19:       OPTS="-package-db=$GHC_PKG -package AstPlugin -fplugin=AstPlugin.Plugin"
    20: 
    21:       # NOTE: GHC plugin writes JSON to stderr
    22:       cabal --ghc-options="$OPTS" build
    23:     '';
    24:   };
    25: 
    26:   # Extract the JSON from runAstPlugin's stderr
    27:   getJson = mkBin {
    28:     name   = "getJson";
    29:     paths  = [ python ];
    30:     script = ''
    31:       #!/usr/bin/env python
    32:       from os         import getenv
    33:       from subprocess import PIPE, Popen
    34:       from sys        import stdout, stderr
    35: 
    36:       # Run the given command, capturing stdout and stderr
    37:       p = Popen([getenv('CMD')], stdout=PIPE, stderr=PIPE)
    38:       sout, serr = p.communicate()
    39: 
    40:       # We want any lines beginning with '{' to go to stdout, all else to stderr
    41:       isJson  = lambda l: l.startswith('{')
    42:       notJson = lambda l: not isJson(l)
    43: 
    44:       stderr.write(sout + '\n')
    45:       stderr.write('\n'.join(filter(notJson, serr.split('\n'))))
    46:       stdout.write('\n'.join(filter(isJson,  serr.split('\n'))))
    47:     '';
    48:   };
    49: 
    50:   testGetJson = runCommand "testGetJson"
    51:     {
    52:       __noChroot  = true;
    53:       buildInputs = [ fail getJson ];
    54:       script1     = writeScript "script1" ''
    55:         #!${bash}/bin/bash
    56:         set -e
    57:         echo   stdout1
    58:         echo   stderr1   1>&2
    59:         echo '{stdout2}'
    60:         echo '{stderr2}' 1>&2
    61:         echo   stdout3
    62:         echo   stderr3   1>&2
    63:       '';
    64:     }
    65:     ''
    66:       set -e
    67:       set -o pipefail
    68: 
    69:       X=$(CMD="$script1" getJson) || fail "Couldn't run getJson"
    70:       [[ "x$X" = 'x{stderr2}' ]]  || fail "Got unexpected output '$X'"
    71: 
    72:       echo pass > "$out"
    73:     '';
    74: 
    75:   runAstPlugin = withDeps [ testGetJson ] (mkBin {
    76:     name   = "runAstPlugin";
    77:     paths  = [ getJson haveVar jq runAstPluginRaw ];
    78:     vars   = { CMD = "runAstPluginRaw"; };
    79:     script = ''
    80:       #!${bash}/bin/bash
    81:       set -e
    82:       set -o pipefail
    83: 
    84:       haveVar nameVersion
    85: 
    86:       getJson | jq -c --argjson nv "$nameVersion" '. + $nv' | jq -s '.'
    87:     '';
    88:   });
    89: 
    90:   main = mkBin {
    91:     name   = "dumpToNix";
    92:     paths  = [ bash cabal-install checkStderr fail haskellPkgNameVersion
    93:                runAstPlugin ];
    94:     script = ''
    95:       #!${bash}/bin/bash
    96:       set -e
    97:       set -o pipefail
    98: 
    99:       nameVersion=$(haskellPkgNameVersion "$1")
   100:       export nameVersion
   101: 
   102:       [[ -n "$pName" ]] || pName=$(echo "$nameVersion" | jq -r '.package')
   103:       export pName
   104: 
   105:       cp -r "$1" ./pkgDir
   106:       chmod +w -R ./pkgDir
   107: 
   108:       export HOME="$PWD"
   109:       cd ./pkgDir
   110: 
   111:       function packageMissing {
   112:         for P in "$pName" AstPlugin
   113:         do
   114:           "$1" list "$P" | grep '(no packages)' > /dev/null && return 0
   115:         done
   116:         return 1
   117:       }
   118: 
   119:       GHC_PKG=""
   120:       if packageMissing "ghc-pkg"
   121:       then
   122:         echo "Didn't find '$pName' in ghc-pkg DB, trying others" 1>&2
   123: 
   124:         # Not found in DB. Maybe broken nix-shell nesting, try elsewhere in PATH.
   125:         while read -r DIR
   126:         do
   127:           # Ignore entries which don't contain ghc-pkg
   128:           [[ -e "$DIR/ghc-pkg" ]] || continue
   129: 
   130:           # Ignore ghc-pkg entries which don't contain AstPlugin or $pName
   131:           packageMissing "$DIR/ghc-pkg" && continue
   132: 
   133:           # If we're here, we've found a ghc-pkg with AstPlugin and $pName
   134:           GHC_PKG=$("$DIR/ghc-pkg" list | head -n 1 | tr -d ':')
   135: 
   136:           echo "Found ghc-pkg DB at '$GHC_PKG'" 1>&2
   137:           break
   138:         done < <(echo "$PATH" | tr ':' '\n' | grep ghc)
   139: 
   140:         if [[ -z "$GHC_PKG" ]]
   141:         then
   142:           echo "Couldn't find ghc-pkg for AstPlugin & '$pName'" 1>&2
   143:           exit 1
   144:         fi
   145:       else
   146:         GHC_PKG=$(ghc-pkg list | head -n 1 | tr -d ':')
   147:       fi
   148: 
   149:       export GHC_PKG
   150: 
   151:       cabal configure --package-db="$GHC_PKG" 1>&2
   152:       runAstPlugin 2> >(checkStderr)
   153:     '';
   154:   };
   155: };
   156: 
   157: {
   158:   inherit main;
   159: 
   160:   dumpToNix = { pkgDir }:
   161:     with rec {
   162:       mkDeps = hsPkgs:
   163:         with {
   164:           pkgDeps = if hsPkgs ? "${pName}"
   165:                        then [ hsPkgs."${pName}" ]
   166:                        else [ (hsPkgs.callPackage pkgDir {}) ];
   167:         };
   168:         [ hsPkgs.AstPlugin hsPkgs.mlspec hsPkgs.mlspec-helper hsPkgs.QuickCheck
   169:           hsPkgs.quickspec ] ++ pkgDeps;
   170: 
   171:       nameVersion = runCommand "hs-name-version.json"
   172:         {
   173:           inherit pName;
   174:           buildInputs = [ hsNameVersion ];
   175:         }
   176:         ''
   177:           hsNameVersion "$pName" > "$out"
   178:         '';
   179: 
   180:       # Look for a .cabal file and extract the "name:" field
   181:       pName = (haskellPackages.callPackage pkgDir {}).name;
   182: 
   183:       hPkgs = (haskellPackages.ghcWithPackages mkDeps).override {
   184:         ignoreCollisions = true;
   185:       };
   186:     };
   187:     runCommand "dumpToNix"
   188:       {
   189:         inherit nameVersion pkgDir pName;
   190:         buildInputs = [ main hPkgs ];
   191:       }
   192:       ''
   193:         dumpToNix "$pkgDir" > "$out"
   194:       '';
   195: }

Generated by git2html.