content-store-0.2.0: Data/ContentStore/Config.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
-- | Module: Data.ContentStore.Config
-- Copyright: (c) 2017 Red Hat, Inc.
-- License: LGPL
--
-- Maintainer: https://github.com/weldr
-- Stability: alpha
-- Portability: portable
--
-- Manage the content store's internal config file.
module Data.ContentStore.Config(Config(..),
defaultConfig,
readConfig,
writeConfig)
where
-- Objects in the store are given file names that are their hash.
-- Lots of hash algorithms are available, which means we need to
-- know which one was used in a given store if we ever want to be
-- able to pull objects back out of it. Thus, a config file.
--
-- Right now the only thing it's storing is the name of the hash
-- algorithm. This may make using aeson seem like overkill, but
-- most of the config file parsing modules are unpleasant to use
-- and if this config file ever becomes too much more complicated,
-- we'll end up using aeson anyway. Might as well start with it.
import Data.Aeson
import Data.Aeson.Types(Result(..), parseJSON)
import qualified Data.Text as T
import qualified Data.Text.IO as TIO
import Text.Toml(parseTomlDoc)
-- | Configuration information needed by the content store.
data Config = Config {
-- | Is the data in the content store compressed? If this option is missing
-- in a config file, we assume that the data is not compressed. This is to
-- keep backwards compatibility with previous versions of the content store
-- that did not support compression. New content stores are created supporting
-- compressed contents by default.
confCompressed :: Bool,
-- | What 'DigestAlgorithm' is in use by this content store? While we do support
-- several different algorithms, only one can ever be in use by a single content
-- store. Note that the 'ContentStore' record also stores this piece of
-- information. The difference is that here, we are only storing the text
-- representation as given in a config file.
confHash :: T.Text
}
instance FromJSON Config where
parseJSON = withObject "Config" $ \v ->
Config <$> v .:? "compressed" .!= False
<*> v .:? "hash" .!= "BLAKE2b256"
instance ToJSON Config where
toJSON Config{..} = object [ "hash" .= toJSON confHash ]
-- | Construct a default 'Config' record useful for when creating a new 'ContentStore',
-- as with 'mkContentStore'. Among other things, this is where the default hash
-- algorithm is defined.
defaultConfig :: Config
defaultConfig =
Config { confCompressed = True,
confHash = "BLAKE2b256" }
-- | Read a config file on disk, returning the 'Config' record on success and an error
-- message on error. This function is typically not useful outside of content store
-- internals.
readConfig :: FilePath -> IO (Either T.Text Config)
readConfig path = do
contents <- TIO.readFile path
case parseTomlDoc "" contents of
Left err -> return $ Left $ T.pack $ show err
Right tbl -> do let j = toJSON tbl
case (fromJSON j :: Result Config) of
Error err -> return $ Left $ T.pack $ show err
Success c -> return $ Right c
-- | Write a 'Config' object to disk. This function is typically not useful outside
-- of content store internals.
writeConfig :: FilePath -> Config -> IO ()
writeConfig path Config{..} = TIO.writeFile path configText
where
configText = T.concat ["compressed = ", if confCompressed then "true" else "false", "\n",
"hash = \"", confHash, "\"\n"]