packages feed

hs-0.1.0.0: src/HS/Managers/Stack.hs

{-# LANGUAGE LambdaCase                 #-}
{-# LANGUAGE MultiWayIf                 #-}
{-# LANGUAGE OverloadedStrings          #-}
{-# LANGUAGE RecordWildCards            #-}
{-# LANGUAGE ScopedTypeVariables        #-}
{-# LANGUAGE TupleSections              #-}

module HS.Managers.Stack
  ( installStack
  , stackDiscover
  ) where

import           Control.Exception
import           Data.Map(Map)
import qualified Data.Map               as Map
import           Data.Maybe
import qualified Data.Text              as T
import           Fmt
import           HS.Cfg.Types
import           HS.Managers.Types
import           HS.Types.CompilerTool
import           System.Directory
import           System.Info(os,arch)
import           System.Process.Typed
import           Text.Enum.Text


-- | use @stack@ to install a toolchain
installStack :: Cfg -> CompilerVersion -> IO Installation
installStack cfg cv = do
    runProcess_ $ proc "stack" ["setup","ghc-"+|cv|+""]
    dir <- stackInstallationDir cfg cv
    return
      Installation
        { _iln_compiler   = cv
        , _iln_manager    = stack
        , _iln_dir        = dir
        }

-- | locate all of the toolchains being managed by the local stack installation
stackDiscover :: Cfg -> IO (Map Compiler Installation)
stackDiscover cfg = handle hdl $ mk =<< listDirectory =<< stackStashDir cfg
  where
    mk :: [FilePath] -> IO (Map Compiler Installation)
    mk fps = mk' fps <$> stackStashDir cfg

    mk' :: [FilePath] -> FilePath -> Map Compiler Installation
    mk' fps sr = Map.fromList $ catMaybes $ map (chk sr) fps

    chk :: FilePath -> FilePath -> Maybe (Compiler,Installation)
    chk sr fp = do
        cp  <- either (const Nothing) Just $ parseText $ T.pack fp
        cv  <- compilerVersion cp
        return $ (,) cp
          Installation
            { _iln_compiler   = cv
            , _iln_manager    = stack
            , _iln_dir        = stackInstallationDir' cfg cv sr
            }

    hdl :: SomeException -> IO (Map Compiler Installation)
    hdl _ = return mempty

stackInstallationDir :: Cfg -> CompilerVersion -> IO FilePath
stackInstallationDir cfg cv = stackInstallationDir' cfg cv <$> stackStashDir cfg

stackInstallationDir' :: Cfg -> CompilerVersion -> FilePath -> FilePath
stackInstallationDir' _ cv sr = ""+|sr|+"/ghc-"+|cv|+""

stackStashDir :: Cfg -> IO FilePath
stackStashDir _ = mk <$> getHomeDirectory
  where
    mk :: FilePath -> FilePath
    mk hme = ""+|hme|+"/.stack/programs/"+|arch|+"-"+|os'|+""

    os' :: String
    os' =
      if | os=="darwin" -> "osx"
         | otherwise    -> os