module System.JBI.Commands
( WrappedTool (..)
, Valid
, toolName
, toolInformation
, checkValidity
, alreadyUsed
, infoProjectDir
, prepare
, targets
, build
, repl
, clean
, test
, bench
, exec
, run
, update
) where
import System.JBI.Commands.BuildTool
import System.JBI.Commands.Tool
import System.JBI.Environment
import System.JBI.Tagged
import Control.Monad (forM)
import Data.Aeson (ToJSON(toJSON))
import Data.Function (on)
import Data.Proxy (Proxy(..))
import System.Directory (withCurrentDirectory)
import System.Exit (ExitCode(ExitSuccess), die)
data WrappedTool proxy where
Wrapped :: (NamedTool bt) => proxy bt -> WrappedTool proxy
instance Eq (WrappedTool Proxy) where
(==) = (==) `on` toolName
instance Show (WrappedTool Proxy) where
show = toolName
deriving instance Show (WrappedTool ToolInformation)
deriving instance Show (WrappedTool Valid)
instance ToJSON (WrappedTool ToolInformation) where
toJSON = withWrapped toJSON
withWrapped :: (forall bt. (NamedTool bt) => proxy bt -> res)
-> WrappedTool proxy -> res
withWrapped f (Wrapped bt) = f bt
toolName :: WrappedTool proxy -> String
toolName = withWrapped prettyName
toolInformation :: GlobalEnv -> WrappedTool proxy -> IO (WrappedTool ToolInformation)
toolInformation env (Wrapped pr) = Wrapped <$> commandToolInformation env pr
data Valid bt = Valid
{ command :: !(Installed bt)
, projectDir :: !(Tagged bt ProjectRoot)
, hasArtifacts :: !Bool
} deriving (Eq, Ord, Show, Read)
alreadyUsed :: WrappedTool Valid -> Bool
alreadyUsed = withWrapped hasArtifacts
infoProjectDir :: WrappedTool Valid -> ProjectRoot
infoProjectDir = withWrapped (stripTag . projectDir)
checkValidity :: GlobalEnv -> WrappedTool proxy -> IO (Maybe (WrappedTool Valid))
checkValidity env (Wrapped p) = fmap Wrapped <$> check p
where
check :: (BuildTool bt) => proxy' bt -> IO (Maybe (Valid bt))
check _ = do
mInst <- commandInformation
case mInst of
Nothing -> return Nothing
Just inst -> do
usbl <- canUseCommand env inst
if not usbl
then return Nothing
else do mroot <- commandProjectRoot (path inst)
forM mroot $ \root ->
Valid inst root <$> hasBuildArtifacts root
runInProject :: (forall bt. (BuildTool bt) => Tagged bt CommandPath -> IO res)
-> WrappedTool Valid -> IO res
runInProject f (Wrapped val) = withCurrentDirectory (stripTag (projectDir val))
(f (path (command val)))
prepareWrapped :: GlobalEnv -> WrappedTool Valid -> IO (WrappedTool Valid)
prepareWrapped env wt@(Wrapped val) = do
ec <- runInProject (commandPrepare env) wt
case ec of
ExitSuccess -> do
hasArt <- canUseCommand env (command val)
if hasArt
then return (Wrapped (val { hasArtifacts = True }))
else die "Preparation failed"
_ -> die "Could not prepare"
runPrepared :: (forall bt. (BuildTool bt) => GlobalEnv -> Tagged bt CommandPath -> IO res)
-> GlobalEnv -> WrappedTool Valid -> IO res
runPrepared f env wv = do
wv' <- if not (alreadyUsed wv)
then prepareWrapped env wv
else return wv
runInProject (f env) wv'
prepare :: GlobalEnv -> WrappedTool Valid -> IO ExitCode
prepare env wv = prepareWrapped env wv >> return ExitSuccess
targets :: GlobalEnv -> WrappedTool Valid -> IO [ProjectTarget]
targets = runPrepared (const (fmap stripTags . commandTargets))
build :: Maybe ProjectTarget -> GlobalEnv -> WrappedTool Valid -> IO ExitCode
build targ = runPrepared (\env cp -> commandBuild env cp (tagInner (tag targ)))
repl :: Maybe ProjectTarget -> GlobalEnv -> WrappedTool Valid -> IO ExitCode
repl targ = runPrepared (\env cp -> commandRepl env cp (tagInner (tag targ)))
clean :: GlobalEnv -> WrappedTool Valid -> IO ExitCode
clean = runPrepared commandClean
test :: GlobalEnv -> WrappedTool Valid -> IO ExitCode
test = runPrepared commandTest
bench :: GlobalEnv -> WrappedTool Valid -> IO ExitCode
bench = runPrepared commandBench
exec :: String -> Args -> GlobalEnv -> WrappedTool Valid -> IO ExitCode
exec cmd args = runPrepared (\env cp -> commandExec env cp cmd args)
run :: ProjectTarget -> Args -> GlobalEnv -> WrappedTool Valid -> IO ExitCode
run targ args = runPrepared (\env cp -> commandRun env cp (tag targ) args)
update :: GlobalEnv -> WrappedTool Valid -> IO ExitCode
update = runPrepared commandUpdate