{-# LANGUAGE RecordWildCards, DeriveDataTypeable #-} module Development.Bake.Core.Run( runInit, runUpdate, runTest, runExtra ) where import Development.Bake.Core.Type hiding (Client) import Development.Bake.Core.Message import Development.Shake.Command import Control.Exception.Extra import General.BigString import General.Extra import System.Time.Extra import Control.DeepSeq import Control.Concurrent.Extra import System.IO.Unsafe import Data.Tuple.Extra import System.IO.Extra import System.Environment.Extra import System.FilePath import Data.Maybe import System.Exit import Safe import qualified Data.Text as T import qualified Data.Text.Lazy as TL {-# NOINLINE running #-} running :: Var Int running = unsafePerformIO $ newVar 0 state x = "--state=" ++ fromState x patch x = "--patch=" ++ fromPatch x test x = "--test=" ++ fromTest x runInit :: IO (Maybe State, Answer) runInit = runAll "init" [] [] toState runUpdate :: State -> [Patch] -> IO (Maybe State, Answer) runUpdate s ps = runAll "update" (state s : map patch ps) [] toState runTest :: State -> [Patch] -> Maybe Test -> IO Answer runTest s ps t = do (ex, ans) <- runAll "test" (state s : map patch ps) (map test $ maybeToList t) (map toTest . readNote "runTest") return $ maybe ans (\ex -> ans{aTests=ex}) (if t == Nothing then ex else Nothing) runExtra :: State -> Maybe Patch -> IO (Maybe (T.Text, TL.Text), Answer) runExtra s ps = runAll "extra" (state s : map patch (maybeToList ps)) [] ((T.pack *** TL.pack) . readNote "runExtra") runAll :: NFData a => String -> [String] -> [String] -> (String -> a) -> IO (Maybe a, Answer) runAll name args1 args2 parse = do exe <- getExecutablePath dir <- createDir ("bake-" ++ name) args1 (time, res) <- duration $ try_ $ do exe <- getExecutablePath (out, exit) <- bigStringFromFile $ \file -> do res <- bracket_ (modifyVar_ running $ return . succ) (modifyVar_ running $ return . pred) $ do v <- readVar running print $ "RUNNING = " ++ show v cmd [Cwd dir, FileStdout file, FileStderr file] exe ("run" ++ name) args1 args2 v <- readVar running print $ "RUNNING = " ++ show v return res ex <- if exit /= ExitSuccess then return Nothing else do ans <- fmap parse $ readFile' $ dir ".bake.result" evaluate $ rnf ans return $ Just ans return (ex, Answer out (Just 0) [] (exit == ExitSuccess)) case res of Left e -> do e <- showException e return (Nothing, Answer (bigStringFromString e) (Just time) [] False) Right (ex,ans) -> return (ex, ans{aDuration=Just time})