module Config.Dyre
(
wrapMain
, Params(..)
, newParams
, defaultParams
) where
import System.IO ( hPutStrLn, stderr )
import System.Directory ( doesFileExist, canonicalizePath )
import System.Environment (getArgs)
import GHC.Environment (getFullArgs)
import Control.Exception (assert)
import Control.Monad ( when )
import Config.Dyre.Params ( Params(..), RTSOptionHandling(..) )
import Config.Dyre.Compile ( customCompile, getErrorString )
import Config.Dyre.Compat ( customExec )
import Config.Dyre.Options ( getForceReconf, getDenyReconf
, withDyreOptions )
import Config.Dyre.Paths
( getPathsConfig, customExecutable, runningExecutable, configFile
, checkFilesModified
)
defaultParams :: Params cfgType a
defaultParams :: Params cfgType a
defaultParams = Params :: forall cfgType a.
String
-> Bool
-> Maybe (IO String)
-> Maybe (IO String)
-> (cfgType -> IO a)
-> (cfgType -> String -> cfgType)
-> [String]
-> [String]
-> [String]
-> Bool
-> (String -> IO ())
-> RTSOptionHandling
-> Bool
-> Params cfgType a
Params
{ projectName :: String
projectName = String
forall a. HasCallStack => a
undefined
, configCheck :: Bool
configCheck = Bool
True
, configDir :: Maybe (IO String)
configDir = Maybe (IO String)
forall a. Maybe a
Nothing
, cacheDir :: Maybe (IO String)
cacheDir = Maybe (IO String)
forall a. Maybe a
Nothing
, realMain :: cfgType -> IO a
realMain = cfgType -> IO a
forall a. HasCallStack => a
undefined
, showError :: cfgType -> String -> cfgType
showError = cfgType -> String -> cfgType
forall a. HasCallStack => a
undefined
, includeDirs :: [String]
includeDirs = []
, hidePackages :: [String]
hidePackages = []
, ghcOpts :: [String]
ghcOpts = []
, forceRecomp :: Bool
forceRecomp = Bool
True
, statusOut :: String -> IO ()
statusOut = Handle -> String -> IO ()
hPutStrLn Handle
stderr
, rtsOptsHandling :: RTSOptionHandling
rtsOptsHandling = [String] -> RTSOptionHandling
RTSAppend []
, includeCurrentDirectory :: Bool
includeCurrentDirectory = Bool
True
}
{-# DEPRECATED defaultParams "Use 'newParams' instead" #-}
newParams
:: String
-> (cfg -> IO a)
-> (cfg -> String -> cfg)
-> Params cfg a
newParams :: String -> (cfg -> IO a) -> (cfg -> String -> cfg) -> Params cfg a
newParams String
name cfg -> IO a
main cfg -> String -> cfg
err =
Params Any Any
forall cfgType a. Params cfgType a
defaultParams { projectName :: String
projectName = String
name, realMain :: cfg -> IO a
realMain = cfg -> IO a
main, showError :: cfg -> String -> cfg
showError = cfg -> String -> cfg
err }
wrapMain :: Params cfgType a -> cfgType -> IO a
wrapMain :: Params cfgType a -> cfgType -> IO a
wrapMain Params cfgType a
params cfgType
cfg = Params cfgType a -> IO a -> IO a
forall c r a. Params c r -> IO a -> IO a
withDyreOptions Params cfgType a
params (IO a -> IO a) -> IO a -> IO a
forall a b. (a -> b) -> a -> b
$
if Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Params cfgType a -> Bool
forall cfgType a. Params cfgType a -> Bool
configCheck Params cfgType a
params
then Params cfgType a -> cfgType -> IO a
forall cfgType a. Params cfgType a -> cfgType -> IO a
realMain Params cfgType a
params cfgType
cfg
else do
PathsConfig
paths <- Params cfgType a -> IO PathsConfig
forall cfg a. Params cfg a -> IO PathsConfig
getPathsConfig Params cfgType a
params
let tempBinary :: String
tempBinary = PathsConfig -> String
customExecutable PathsConfig
paths
thisBinary :: String
thisBinary = PathsConfig -> String
runningExecutable PathsConfig
paths
Bool
confExists <- String -> IO Bool
doesFileExist (PathsConfig -> String
configFile PathsConfig
paths)
Bool
denyReconf <- IO Bool
getDenyReconf
Bool
forceReconf <- IO Bool
getForceReconf
Bool
doReconf <- case (Bool
confExists, Bool
denyReconf, Bool
forceReconf) of
(Bool
False, Bool
_, Bool
_) -> Bool -> IO Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False
(Bool
_, Bool
True, Bool
_) -> Bool -> IO Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False
(Bool
_, Bool
_, Bool
True) -> Bool -> IO Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True
(Bool
_, Bool
_, Bool
False) -> PathsConfig -> IO Bool
checkFilesModified PathsConfig
paths
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
doReconf (Params cfgType a -> IO ()
forall cfgType a. Params cfgType a -> IO ()
customCompile Params cfgType a
params)
Maybe String
errorData <- Params cfgType a -> IO (Maybe String)
forall cfgType a. Params cfgType a -> IO (Maybe String)
getErrorString Params cfgType a
params
Bool
customExists <- String -> IO Bool
doesFileExist String
tempBinary
case (Bool
confExists, Bool
customExists) of
(Bool
False, Bool
_) ->
Maybe String -> IO a
enterMain Maybe String
forall a. Maybe a
Nothing
(Bool
True, Bool
True) -> do
String
thisBinary' <- String -> IO String
canonicalizePath String
thisBinary
String
tempBinary' <- String -> IO String
canonicalizePath String
tempBinary
if String
thisBinary' String -> String -> Bool
forall a. Eq a => a -> a -> Bool
/= String
tempBinary'
then Maybe String -> String -> IO a
forall a b. Maybe a -> String -> IO b
launchSub Maybe String
errorData String
tempBinary
else Maybe String -> IO a
enterMain Maybe String
errorData
(Bool
True, Bool
False) ->
Maybe String -> IO a
enterMain Maybe String
errorData
where launchSub :: Maybe a -> String -> IO b
launchSub Maybe a
errorData String
tempBinary = do
Params cfgType a -> String -> IO ()
forall cfgType a. Params cfgType a -> String -> IO ()
statusOut Params cfgType a
params (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ String
"Launching custom binary " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
tempBinary String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\n"
[String]
givenArgs <- RTSOptionHandling -> IO [String]
handleRTSOptions (RTSOptionHandling -> IO [String])
-> RTSOptionHandling -> IO [String]
forall a b. (a -> b) -> a -> b
$ Params cfgType a -> RTSOptionHandling
forall cfgType a. Params cfgType a -> RTSOptionHandling
rtsOptsHandling Params cfgType a
params
let arguments :: [String]
arguments = case Maybe a
errorData of
Maybe a
Nothing -> [String]
givenArgs
Just _ -> String
"--deny-reconf"String -> [String] -> [String]
forall a. a -> [a] -> [a]
:[String]
givenArgs
String -> Maybe [String] -> IO b
forall a. String -> Maybe [String] -> IO a
customExec String
tempBinary (Maybe [String] -> IO b) -> Maybe [String] -> IO b
forall a b. (a -> b) -> a -> b
$ [String] -> Maybe [String]
forall a. a -> Maybe a
Just [String]
arguments
enterMain :: Maybe String -> IO a
enterMain Maybe String
errorData = do
let mainConfig :: cfgType
mainConfig = case Maybe String
errorData of
Maybe String
Nothing -> cfgType
cfg
Just ed -> Params cfgType a -> cfgType -> String -> cfgType
forall cfgType a. Params cfgType a -> cfgType -> String -> cfgType
showError Params cfgType a
params cfgType
cfg String
ed
Params cfgType a -> cfgType -> IO a
forall cfgType a. Params cfgType a -> cfgType -> IO a
realMain Params cfgType a
params cfgType
mainConfig
assertM :: Applicative f => Bool -> f ()
assertM :: Bool -> f ()
assertM Bool
b = Bool -> f () -> f ()
forall a. HasCallStack => Bool -> a -> a
assert Bool
b (() -> f ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ())
filterRTSArgs :: [String] -> [String]
filterRTSArgs :: [String] -> [String]
filterRTSArgs = Bool -> [String] -> [String]
filt Bool
False
where
filt :: Bool -> [String] -> [String]
filt Bool
_ [] = []
filt Bool
_ (String
"--RTS":[String]
_) = []
filt Bool
False (String
"+RTS" :[String]
rest) = Bool -> [String] -> [String]
filt Bool
True [String]
rest
filt Bool
True (String
"-RTS" :[String]
rest) = Bool -> [String] -> [String]
filt Bool
False [String]
rest
filt Bool
False (String
_ :[String]
rest) = Bool -> [String] -> [String]
filt Bool
False [String]
rest
filt Bool
True (String
arg :[String]
rest) = String
argString -> [String] -> [String]
forall a. a -> [a] -> [a]
:Bool -> [String] -> [String]
filt Bool
True [String]
rest
editRTSOptions :: [String] -> RTSOptionHandling -> [String]
editRTSOptions :: [String] -> RTSOptionHandling -> [String]
editRTSOptions [String]
_ (RTSReplace [String]
ls) = [String]
ls
editRTSOptions [String]
opts (RTSAppend [String]
ls) = [String]
opts [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String]
ls
handleRTSOptions :: RTSOptionHandling -> IO [String]
handleRTSOptions :: RTSOptionHandling -> IO [String]
handleRTSOptions RTSOptionHandling
h = do [String]
fargs <- IO [String]
getFullArgs
[String]
args <- IO [String]
getArgs
let rtsArgs :: [String]
rtsArgs = [String] -> RTSOptionHandling -> [String]
editRTSOptions ([String] -> [String]
filterRTSArgs [String]
fargs) RTSOptionHandling
h
Bool -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f ()
assertM (Bool -> IO ()) -> Bool -> IO ()
forall a b. (a -> b) -> a -> b
$ String
"--RTS" String -> [String] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [String]
rtsArgs
[String] -> IO [String]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([String] -> IO [String]) -> [String] -> IO [String]
forall a b. (a -> b) -> a -> b
$ case [String]
rtsArgs of
[] | String
"+RTS" String -> [String] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [String]
args -> String
"--RTS"String -> [String] -> [String]
forall a. a -> [a] -> [a]
:[String]
args
| Bool
otherwise -> [String]
args
[String]
_ -> String
"+RTS" String -> [String] -> [String]
forall a. a -> [a] -> [a]
: [String]
rtsArgs [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ String
"--RTS" String -> [String] -> [String]
forall a. a -> [a] -> [a]
: [String]
args