module Sos
( Sos
, runSos
, sosEnqueueJobs
, module Sos.Exception
, module Sos.FileEvent
, module Sos.Job
, module Sos.JobQueue
, module Sos.Rule
, module Sos.Template
) where
import Sos.Exception
import Sos.FileEvent
import Sos.Job
import Sos.JobQueue
import Sos.Rule
import Sos.Template
import Control.Applicative
import Control.Monad.Except
import Control.Monad.Trans.Resource
import Data.List.NonEmpty (NonEmpty(..))
import Streaming
import System.Exit
import Text.Regex.TDFA (match)
import qualified Streaming.Prelude as S
type Sos a = ResourceT (ExceptT SosException IO) a
runSos :: Sos a -> IO a
runSos act =
runExceptT (runResourceT act) >>= \case
Left err -> do
print err
exitFailure
Right x -> return x
sosEnqueueJobs
:: (Applicative m, MonadError SosException m, MonadResource m)
=> [Rule]
-> Stream (Of FileEvent) m a
-> JobQueue
-> m a
sosEnqueueJobs rules events queue =
S.mapM_
(\(event, cmds) -> liftIO (enqueueJob event cmds queue))
(jobStream rules events)
jobStream
:: forall m a.
(Applicative m, MonadError SosException m)
=> [Rule]
-> Stream (Of FileEvent) m a
-> Stream (Of (FileEvent, NonEmpty ShellCommand)) m a
jobStream rules events =
S.for events
(\event ->
lift (commands event) >>= \case
[] -> pure ()
(c:cs) -> S.yield (event, c :| cs))
where
commands :: FileEvent -> m [ShellCommand]
commands event = concat <$> mapM go rules
where
go :: Rule -> m [ShellCommand]
go rule =
case match (ruleRegex rule) (fileEventPath event) of
[] -> pure []
(xs:_) -> mapM (instantiateTemplate xs) (ruleTemplates rule)