Config.hs 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. {-# LANGUAGE OverloadedStrings #-}
  2. {-# LANGUAGE RecordWildCards #-}
  3. module Config
  4. ( ConfigFile
  5. , fetchConfig
  6. , Ini.iniValueL
  7. ) where
  8. import Control.Monad (forM)
  9. import Data.Ini.Config.Bidir ((.=), (.=?), (&))
  10. import qualified Data.Ini.Config.Bidir as Ini
  11. import qualified Data.Text as T
  12. import qualified Data.Text.IO as T
  13. import Data.Monoid ((<>))
  14. import qualified System.Directory as Sys
  15. import System.FilePath ((</>))
  16. import qualified System.Exit as Sys
  17. import qualified System.Environment.XDG.BaseDir as Sys
  18. import Text.Read (readMaybe)
  19. import Types
  20. type ConfigFile = Ini.Ini Config
  21. defaultConfig :: IO Config
  22. defaultConfig = do
  23. _configInstallPath <- Sys.getUserDataDir ("hatch" </> "install")
  24. let _configCurrentCompiler = Nothing
  25. return Config { .. }
  26. configSpec :: Ini.IniSpec Config ()
  27. configSpec = do
  28. Ini.section "hatch" $ do
  29. configInstallPath .= Ini.field "path" Ini.string
  30. & Ini.optional
  31. configCurrentCompiler .=? Ini.field "current" versionField
  32. versionField :: Ini.FieldValue Compiler
  33. versionField = Ini.FieldValue { .. }
  34. where
  35. fvParse t
  36. | Just ver <- T.stripPrefix "ghc-" t
  37. , [x,y,z] <- T.splitOn "." ver
  38. , Just x' <- readMaybe (T.unpack x)
  39. , Just y' <- readMaybe (T.unpack y)
  40. , Just z' <- readMaybe (T.unpack z)
  41. = Right (Compiler (x', y', z'))
  42. | otherwise = Left ("Bad GHC version: " ++ show t)
  43. fvEmit = T.pack . compilerString
  44. locateConfig :: FilePath -> IO (Maybe FilePath)
  45. locateConfig filename = do
  46. xdgLocs <- Sys.getAllConfigFiles "hatch" filename
  47. let confLocations = ["./" <> filename] ++
  48. xdgLocs ++
  49. ["/etc/hatch/" <> filename]
  50. results <- forM confLocations (\fp -> (,) fp <$> Sys.doesFileExist fp)
  51. case filter snd results of
  52. [] -> return Nothing
  53. ((fp, _):_) -> return (Just fp)
  54. fetchConfig :: IO (Ini.Ini Config)
  55. fetchConfig = do
  56. def <- defaultConfig
  57. let ini = Ini.ini def configSpec
  58. confLocation <- locateConfig "config.ini"
  59. print confLocation
  60. case confLocation of
  61. Nothing -> return ini
  62. Just fp -> do
  63. content <- T.readFile fp
  64. case Ini.parseIni content ini of
  65. Left err -> do
  66. Sys.die err
  67. Right x -> return x