module Runner ( run ) where import Control.Lens import Data.Foldable as F import Data.Functor import Distribution.Nixpkgs.Haskell.FromStack import Distribution.Nixpkgs.Haskell.FromStack.Package import Distribution.Nixpkgs.Haskell.Stack import Distribution.Nixpkgs.Haskell.Stack.PrettyPrinting as PP import Distribution.Version (Version) import Distribution.Compiler (AbiTag(..), unknownCompilerInfo) import Distribution.Package (mkPackageName, pkgName) import Distribution.Text as Text (display) import Language.Nix as Nix import Options.Applicative import Paths_stackage2nix ( version ) import Runner.Cli import Stack.Config import Stack.Types import Stackage.Types import System.IO (withFile, IOMode(..), hPutStrLn, hPrint) import Text.PrettyPrint.HughesPJClass (render) import qualified Data.Set as Set import qualified Data.Map as Map import qualified LtsHaskell as LH run :: IO () run = do opts <- execParser pinfo stackYaml <- envStackYaml >>= \case Just p -> putStrLn "Getting project config file from STACK_YAML environment" $> p Nothing -> pure $ opts ^. optStackYaml stackConf <- either fail pure =<< readStackConfig stackYaml let buildPlanFile = LH.buildPlanFilePath (opts ^. optLtsHaskellRepo) (stackConf ^. scResolver) buildPlan <- LH.loadBuildPlan buildPlanFile packageSetConfig <- LH.buildPackageSetConfig (opts ^. optAllCabalHashesRepo) (opts ^. optNixpkgsRepository) buildPlan -- generate haskell packages override let overrideConfig = mkOverrideConfig opts (siGhcVersion $ bpSystemInfo buildPlan) stackPackagesConfig = mkStackPackagesConfig opts packages <- traverse (packageDerivation stackPackagesConfig (opts ^. optHackageDb)) $ stackConf ^. scPackages let out = PP.overrideHaskellPackages overrideConfig packages withFile (opts ^. optOutDerivation) WriteMode $ \h -> do hPutStrLn h ("# Generated by stackage2nix " ++ Text.display version ++ " from " ++ stackYaml ^. syFilePath) hPrint h out let reachable = Set.map mkPackageName $ F.foldr1 Set.union $ nodeDepends . mkNode <$> packages s2nLoader mHash pkgId = if pkgName pkgId `Set.member` reachable then packageLoader packageSetConfig Nothing pkgId else packageLoader packageSetConfig mHash pkgId s2nPackageSetConfig = packageSetConfig { packageLoader = s2nLoader } s2nPackageConfig = PackageConfig { enableCheck = opts ^. optDoCheckStackage , enableHaddock = opts ^. optDoHaddockStackage } allNodes <- traverse (uncurry (buildNodeM s2nPackageSetConfig s2nPackageConfig)) $ Map.toList (bpPackages buildPlan) -- Find all reachable dependencies in stackage set to stick into -- stackage packages file. This is performed on the full stackage -- set rather than pruning stackage packages beforehand because -- stackage does not concern itself with build tools while cabal2nix -- does: pruning only after generating full set of packages allows -- us to make sure all those extra dependencies are explicitly -- listed as well. let nodes = case opts ^. optOutPackagesClosure of True -> flip reachableDependencies allNodes -- Originally reachable nodes are root nodes $ filter (\n -> mkPackageName (nodeName n) `Set.member` reachable) allNodes False -> allNodes withFile (opts ^. optOutStackagePackages) WriteMode $ \h -> do hPutStrLn h ("# Generated by stackage2nix " ++ Text.display version ++ " from " ++ buildPlanFile) hPutStrLn h $ render $ pPrintOutPackages (view nodeDerivation <$> nodes) withFile (opts ^. optOutStackageConfig) WriteMode $ \h -> do hPutStrLn h ("# Generated by stackage2nix " ++ Text.display version ++ " from " ++ buildPlanFile) hPutStrLn h $ render $ pPrintOutConfig (bpSystemInfo buildPlan) nodes mkOverrideConfig :: Options -> Version -> OverrideConfig mkOverrideConfig opts ghcVersion = OverrideConfig { _ocGhc = ghcVersion , _ocStackagePackages = opts ^. optOutStackagePackages , _ocStackageConfig = opts ^. optOutStackageConfig , _ocNixpkgs = opts ^. optNixpkgsRepository } mkStackPackagesConfig :: Options -> StackPackagesConfig mkStackPackagesConfig opts = StackPackagesConfig { _spcHaskellResolver = const True , _spcNixpkgsResolver = \i -> Just (Nix.binding # (i, Nix.path # [i])) , _spcTargetPlatform = opts ^. optPlatform , _spcTargetCompiler = unknownCompilerInfo (opts ^. optCompilerId) NoAbiTag , _spcFlagAssignment = [] , _spcDoCheckPackages = opts ^. optDoCheckPackages , _spcDoHaddockPackages = opts ^. optDoHaddockPackages , _spcDoCheckStackage = opts ^. optDoCheckStackage , _spcDoHaddockStackage = opts ^. optDoHaddockStackage }