{-# LANGUAGE TemplateHaskell , OverloadedStrings , RecordWildCards , PatternGuards #-} module System.Posix.ARX.TMPXTools where import Data.ByteString (ByteString) import qualified Data.ByteString.Char8 as Bytes import Data.Char import Data.List import Data.Maybe import Data.Monoid import Numeric import qualified Blaze.ByteString.Builder as Blaze import Data.FileEmbed import Data.Hashable data Template = Template { rm0 :: Bool, {-^ Remove tmp on run success? -} rm1 :: Bool, {-^ Remove tmp on run error? -} shared :: Bool, {-^ Share directory across runs? -} tmpdir :: ByteString, {-^ Temp file location. -} env :: Blaze.Builder, {-^ Stream for env text. -} run :: Blaze.Builder, {-^ Stream for run text. -} dat :: Blaze.Builder {-^ Data text. -} } instance Show Template where show Template{..} = "Template { tmpdir=" ++ Bytes.unpack tmpdir ++ " rm0=" ++ tf rm0 ++ " rm1=" ++ tf rm1 ++ " shared=" ++ tf shared ++ " ... }" where tf True = "true" tf False = "false" render :: Template -> Blaze.Builder render Template{..} = mconcat [ blaze a, flags, blaze b, env, blaze c, run, blaze d, dat, blaze e ] where flags = mconcat [ "rm0=", tf rm0, " ; ", "rm1=", tf rm1, " ; ", "shared=", tf shared, " ; ", "hash=", (hexStr . hash) dat, " ; ", "tmpdir=", blaze tmpdir, "\n" ] hash = abs . Data.Hashable.hash . Blaze.toByteString hexStr = blaze . Bytes.pack . hex hex i = Numeric.showIntAtBase 16 Data.Char.intToDigit i "" blaze = Blaze.fromByteString tf True = "true" tf False = "false" a : b : c : d : e : f : [] = findChunks $(embedFile "./model-scripts/tmpx.sh") findChunks :: ByteString -> [ByteString] findChunks = coalesce . markHoles coalesce :: [Maybe ByteString] -> [ByteString] coalesce = reverse . catMaybes . foldl' f [] where f [ ] item = [item] f (Just a : t) (Just b) = Just (Bytes.append a b) : t f (Nothing : t) (Just b) = Just b : Nothing : t f (Just a : t) (Nothing) = Nothing : Just a : t f (Nothing : t) (Nothing) = Nothing : t markHoles :: ByteString -> [Maybe ByteString] markHoles = map f . Bytes.lines where f l | isHole l = Nothing | otherwise = Just (l `Bytes.snoc` '\n') isHole :: ByteString -> Bool isHole line = "# To be set by tool." `Bytes.isSuffixOf` line