-- | -- Module: SHC.Stack -- Copyright: (c) 2014-2015 Guillaume Nargeot, (c) 2015-2016 Felipe Lessa -- License: BSD3 -- Maintainer: Michele Lacchia -- Stability: experimental -- -- Utility functions related to Stack. module SHC.Stack where import Data.Version import Control.Monad (forM, guard) import System.Directory (makeRelativeToCurrentDirectory) import System.FilePath ((), equalFilePath, splitPath) import qualified Data.ByteString.Char8 as BS8 import qualified Data.Yaml as Y import SHC.Types import SHC.Utils stack :: [String] -> IO String stack = readP "stack" -- | Verify that the required Stack is present. checkStackVersion :: IO Bool checkStackVersion = do let lowerBound = Version [0,1,7,0] [] stackVersion <- stack ["--numeric-version"] return $ verifyVersion stackVersion lowerBound -- | Return the HPC data directory, given the package name. getHpcDir :: String -> IO FilePath getHpcDir package = ( package) <$> stack ["path", "--local-hpc-root"] -- | Return the HPC mix directory, where module data is stored. This -- path needs to be prefixed with the project's path -- (cf. 'stackProjectPath'). getBaseMixDir :: IO FilePath getBaseMixDir = ( "hpc") <$> stack ["path", "--dist-dir"] -- | Get relevant information from @stack query@. Used to find -- package filepaths. getStackQuery :: IO StackQuery getStackQuery = either err return . Y.decodeEither' . BS8.pack =<< stack ["query"] where err = fail . (++) "getStackQuery: Couldn't decode the result of 'stack query' as YAML: " . show -- | Get the key that GHC uses for the given package. getProjectKey :: String -> IO String getProjectKey pkgName = stack ["exec", "--", "ghc-pkg", "field", pkgName, "key", "--simple-output"] -- | Get the Stack info needed to find project files. getStackProjects :: IO [StackProject] getStackProjects = do sq <- getStackQuery baseMixDir <- getBaseMixDir forM (stackQueryLocals sq) $ \(pkgName, filepath) -> do relfp <- makeRelativeToCurrentDirectory filepath let mpath = guard (not $ relfp `equalFilePath` ".") >> Just relfp key <- if ".stack-work/" `elem` splitPath relfp then return pkgName else getProjectKey pkgName return StackProject { stackProjectName = pkgName , stackProjectPath = mpath , stackProjectKey = key , stackProjectMixDir = maybe id () mpath baseMixDir }