packages feed

dhrun-1.0.1: src/Dhrun/Types/Cfg.hs

{-# language MultiParamTypeClasses #-}
{-# language FlexibleInstances #-}
{-# language DeriveGeneric #-}

{-|
Module      : Dhrun.Internal
Description : types
Copyright   : (c) Valentin Reis, 2018
License     : MIT
Maintainer  : fre@freux.fr
-}

module Dhrun.Types.Cfg
  ( Cfg(..)
  , Verbosity(..)
  , Cmd(..)
  , EnvVar(..)
  , VarName(..)
  , VarValue(..)
  , WorkDir(..)
  , WorkDirBehavior(..)
  , Check(..)
  , FileCheck(..)
  , FileName(..)
  , CommandName(..)
  , Arg(..)
  , Pattern(..)
  , inputCfg
  , decodeCfgFile
  , decodeCfg
  , encodeCfg
  , encodeCmd
  )
where

import           Dhall
import qualified Dhrun.Types.Dhall             as DT
import qualified Dhrun.Types.Yaml              as DAT
import           Data.Yaml.Internal
import           Protolude
import qualified Prelude                        ( String )

newtype Arg = Arg Text deriving (Eq, Show, Generic)
instance StringConv Arg Text where
  strConv _ (Arg x) = toS x
instance StringConv Arg Prelude.String where
  strConv _ (Arg x) = toS x

newtype CommandName = CommandName Text deriving (Eq, Show, Generic)
instance StringConv CommandName Text where
  strConv _ (CommandName x) = toS x
instance StringConv CommandName FilePath where
  strConv _ (CommandName x) = toS x

newtype Pattern = Pattern Text deriving (Eq, Show, Generic)
instance StringConv Pattern ByteString where
  strConv _ (Pattern x) = toS x
instance StringConv Pattern Text where
  strConv _ (Pattern x) = toS x

newtype FileName = FileName Text deriving (Eq, Show, Generic)
instance StringConv FileName Text where
  strConv _ (FileName x) = toS x
instance StringConv FileName FilePath where
  strConv _ (FileName x) = toS x

newtype VarName = VarName Text deriving (Eq, Show, Generic)
instance StringConv VarName Text where
  strConv _ (VarName x) = toS x

newtype VarValue = VarValue Text deriving (Eq, Show, Generic)
instance StringConv VarValue Text where
  strConv _ (VarValue x) = toS x

newtype Pre = Pre Text deriving (Eq, Show, Generic)
instance StringConv Pre Text where
  strConv _ (Pre x) = toS x

newtype Post = Post Text deriving (Eq, Show, Generic)
instance StringConv Post Text where
  strConv _ (Post x) = toS x

newtype WorkDir = WorkDir Text deriving (Eq, Show, Generic)
instance StringConv WorkDir Text where
  strConv _ (WorkDir x) = toS x
instance StringConv WorkDir FilePath where
  strConv _ (WorkDir x) = toS x

data WorkDirBehavior = Keep | Remove
  deriving (Read, Show, Eq)

data Verbosity = Normal | Verbose
  deriving (Read, Show, Eq)

data EnvVar = EnvVar {
    varname :: VarName
  , value   :: VarValue
  } deriving (Eq, Show, Generic)


data Check = Check {
    avoids :: [Pattern]
  , wants  :: [Pattern]
  } deriving (Eq, Show, Generic)

data FileCheck a = FileCheck {
    filename  :: FileName
  , filecheck :: a
  } deriving (Eq, Show, Generic)

data Cmd = Cmd {
    name        :: CommandName
  , exitcode    :: Maybe ExitCode
  , args        :: [Arg]
  , vars        :: [EnvVar]
  , passvars    :: [VarName]
  , out         :: FileCheck Check
  , err         :: FileCheck Check
  , postchecks  :: [FileCheck Check]
  , timeout     :: Maybe Int
  , otherwd     :: Maybe WorkDir
  } deriving (Eq, Show, Generic)

data Cfg = Cfg
  { cmds      :: [Cmd],
    workdir   :: WorkDir,
    cleaning  :: WorkDirBehavior,
    verbosity :: Verbosity,
    pre       :: [Pre],
    post      :: [Post]
  } deriving (Show, Eq)

toInternal :: DT.Cfg -> Cfg
toInternal DT.Cfg {..} = Cfg
  { cmds      = toInternalCmd <$> cmds
  , workdir   = WorkDir workdir
  , cleaning  = if cleaning then Remove else Keep
  , pre       = Pre <$> pre
  , post      = Post <$> post
  , verbosity = if verbose then Verbose else Normal
  }

fromInternal :: Cfg -> DT.Cfg
fromInternal Cfg {..} = DT.Cfg
  { cmds     = fromInternalCmd <$> cmds
  , workdir  = toS workdir
  , cleaning = cleaning == Remove
  , pre      = toS <$> pre
  , post     = toS <$> post
  , verbose  = verbosity == Verbose
  }

toInternalCmd :: DT.Cmd -> Cmd
toInternalCmd DT.Cmd {..} = Cmd
  { name       = CommandName name
  , exitcode   = case exitcode of
                   Just 0 -> Just ExitSuccess
                   Just x -> Just $ ExitFailure (fromInteger x)
                   Nothing -> Nothing
  , args       = Arg <$> args
  , vars       = vars <&> \DT.EnvVar {..} ->
    EnvVar {varname = VarName varname, value = VarValue value}
  , passvars   = VarName <$> passvars
  , out        = toInternalFileCheck out
  , err        = toInternalFileCheck err
  , postchecks = toInternalFileCheck <$> postchecks
  , timeout    = fromInteger . toInteger <$> timeout
  , otherwd      = WorkDir <$> otherwd
  }

toInternalFileCheck :: DT.FileCheck DT.Check -> FileCheck Check
toInternalFileCheck DT.FileCheck {..} = FileCheck
  { filename  = FileName filename
  , filecheck = toInternalCheck filecheck
  }

toInternalCheck :: DT.Check -> Check
toInternalCheck DT.Check {..} =
  Check {avoids = Pattern <$> avoids, wants = Pattern <$> wants}

fromInternalCmd :: Cmd -> DT.Cmd
fromInternalCmd Cmd {..} = DT.Cmd
  { out        = fromInternalFileCheck out
  , err        = fromInternalFileCheck err
  , postchecks = fromInternalFileCheck <$> postchecks
  , timeout    = fromInteger . toInteger <$> timeout
  , name       = toS name
  , exitcode   = case exitcode of
                   Just ExitSuccess -> Just 1
                   Just (ExitFailure n) -> Just $ toInteger n
                   Nothing -> Nothing
  , args       = toS <$> args
  , vars       = vars <&> \case
    EnvVar {..} -> DT.EnvVar {varname = toS varname, value = toS value}
  , passvars   = toS <$> passvars
  , otherwd      = toS <$> otherwd
  }

fromInternalFileCheck :: FileCheck Check -> DT.FileCheck DT.Check
fromInternalFileCheck FileCheck {..} = DT.FileCheck
  { filename  = toS filename
  , filecheck = fromInternalCheck filecheck
  }

fromInternalCheck :: Check -> DT.Check
fromInternalCheck Check {..} =
  DT.Check {avoids = toS <$> avoids, wants = toS <$> wants}

decodeCfgFile :: (MonadIO m) => Text -> m Cfg
decodeCfgFile fn = toInternal <$> DAT.decodeCfgFile fn

decodeCfg :: ByteString -> Either Data.Yaml.Internal.ParseException Cfg
decodeCfg t = toInternal <$> DAT.decodeCfg t

encodeCfg :: Cfg -> ByteString
encodeCfg = DAT.encodeCfg . fromInternal

encodeCmd :: Cmd -> ByteString
encodeCmd = DAT.encodeCmd . fromInternalCmd

inputCfg :: (MonadIO m) => Text -> m Cfg
inputCfg fn = toInternal <$> DT.inputCfg fn