{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} module Config ( ConfigFile , fetchConfig , Ini.iniValueL ) where import Control.Monad (forM) import Data.Ini.Config.Bidir ((.=), (.=?), (&)) import qualified Data.Ini.Config.Bidir as Ini import qualified Data.Text as T import qualified Data.Text.IO as T import Data.Monoid ((<>)) import qualified System.Directory as Sys import System.FilePath (()) import qualified System.Exit as Sys import qualified System.Environment.XDG.BaseDir as Sys import Text.Read (readMaybe) import Types type ConfigFile = Ini.Ini Config defaultConfig :: IO Config defaultConfig = do _configInstallPath <- Sys.getUserDataDir ("hatch" "install") let _configCurrentCompiler = Nothing return Config { .. } configSpec :: Ini.IniSpec Config () configSpec = do Ini.section "hatch" $ do configInstallPath .= Ini.field "path" Ini.string & Ini.optional configCurrentCompiler .=? Ini.field "current" versionField versionField :: Ini.FieldValue Compiler versionField = Ini.FieldValue { .. } where fvParse t | Just ver <- T.stripPrefix "ghc-" t , [x,y,z] <- T.splitOn "." ver , Just x' <- readMaybe (T.unpack x) , Just y' <- readMaybe (T.unpack y) , Just z' <- readMaybe (T.unpack z) = Right (Compiler (x', y', z')) | otherwise = Left ("Bad GHC version: " ++ show t) fvEmit = T.pack . compilerString locateConfig :: FilePath -> IO (Maybe FilePath) locateConfig filename = do xdgLocs <- Sys.getAllConfigFiles "hatch" filename let confLocations = ["./" <> filename] ++ xdgLocs ++ ["/etc/hatch/" <> filename] results <- forM confLocations (\fp -> (,) fp <$> Sys.doesFileExist fp) case filter snd results of [] -> return Nothing ((fp, _):_) -> return (Just fp) fetchConfig :: IO (Ini.Ini Config) fetchConfig = do def <- defaultConfig let ini = Ini.ini def configSpec confLocation <- locateConfig "config.ini" print confLocation case confLocation of Nothing -> return ini Just fp -> do content <- T.readFile fp case Ini.parseIni content ini of Left err -> do Sys.die err Right x -> return x