dojang-0.2.0: src/Dojang/Types/Registry.hs
{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE OverloadedStrings #-}
-- | This module provides the registry type and functions for reading and
-- writing the registry file. The registry file stores the path to the
-- repository so that commands like @dojang edit@ can be run from any
-- directory.
module Dojang.Types.Registry
( Registry (..)
, readRegistry
, registryFilename
, writeRegistry
) where
import Control.DeepSeq (force)
import Control.Monad.IO.Class (MonadIO)
import Data.Text (Text, pack, unpack)
import Data.Text.Encoding (decodeUtf8Lenient, encodeUtf8)
import System.IO.Unsafe (unsafePerformIO)
import System.OsPath (OsPath, decodeFS, encodeFS)
import TextShow (FromStringShow (FromStringShow), showt)
import Toml (decode, encode)
import Toml.FromValue
( FromValue (fromValue)
, Result (Failure, Success)
, parseTableFromValue
, reqKey
)
import Toml.ToValue
( ToTable (toTable)
, ToValue (toValue)
, defaultTableToValue
, table
, (.=)
)
import Dojang.MonadFileSystem (MonadFileSystem (..))
-- | The registry stores the path to the repository.
data Registry = Registry
{ repositoryPath :: OsPath
-- ^ The path to the repository.
}
deriving (Eq, Show)
-- | The filename for the registry file.
registryFilename :: OsPath
registryFilename = unsafePerformIO $ encodeFS ".dojang"
{-# NOINLINE registryFilename #-}
instance FromValue Registry where
fromValue =
parseTableFromValue $
Registry
<$> (textToOsPath <$> reqKey "repository")
where
textToOsPath :: Text -> OsPath
textToOsPath t = unsafePerformIO $ encodeFS $ unpack t
instance ToValue Registry where
toValue = defaultTableToValue
instance ToTable Registry where
toTable reg =
table
[ "repository" .= osPathToText reg.repositoryPath
]
where
osPathToText :: OsPath -> Text
osPathToText p = pack $ unsafePerformIO $ decodeFS p
-- | Read the registry from a file.
readRegistry
:: (MonadFileSystem m, MonadIO m)
=> OsPath
-- ^ The path to the registry file.
-> m (Maybe Registry)
readRegistry path = do
fileExists <- exists path
if not fileExists
then return Nothing
else do
contents <- Dojang.MonadFileSystem.readFile path
let textContents = decodeUtf8Lenient contents
case decode $ unpack $ force textContents of
Success _ reg -> return $ Just reg
Failure _ -> return Nothing
-- | Write the registry to a file.
writeRegistry
:: (MonadFileSystem m)
=> OsPath
-- ^ The path to the registry file.
-> Registry
-- ^ The registry to write.
-> m ()
writeRegistry path registry = do
let contents = showt $ FromStringShow $ encode registry
Dojang.MonadFileSystem.writeFile path (encodeUtf8 contents)