module B9.B9Monad
  ( runB9,
    runB9Interactive,
    B9,
    B9Eff,
    IsB9,
  )
where

import B9.B9Config
import B9.B9Error
import B9.B9Logging
import B9.BuildInfo
import B9.Environment
import B9.Repository
import B9.RepositoryIO
import Control.Eff
import Data.Functor ()
import GHC.Stack

-- | Definition of the B9 monad. See 'B9Eff'.
--
-- This module is used by the _effectful_ functions in this library.
--
-- @since 0.5.65
type B9 a = Eff B9Eff a

-- | Definition of the B9 effect list. It encapsulates logging,
-- a reader for the "B9.B9Config" and access to the
-- current build id, the current build directory and the artifact to build.
--
-- This monad is used by the _effectful_ functions in this library.
--
-- @since 0.5.65
type B9Eff =
  '[ SelectedRemoteRepoReader,
     RepoCacheReader,
     BuildInfoReader,
     LoggerReader,
     B9ConfigReader,
     EnvironmentReader,
     ExcB9,
     Lift
       IO
   ]

-- | A constraint that contains all effects of 'B9Eff'
--
-- @since 0.5.65
type IsB9 e = (HasCallStack, Lifted IO e, CommandIO e, B9Eff <:: e)

-- | Execute a 'B9' effect and return an action that needs
-- the 'B9Config'.
--
-- @since 0.5.65
runB9 :: HasCallStack => B9 a -> B9ConfigAction a
runB9 :: B9 a -> B9ConfigAction a
runB9 = Bool -> B9 a -> B9ConfigAction a
forall a. HasCallStack => Bool -> B9 a -> B9ConfigAction a
runB9Full Bool
False

-- | Execute a 'B9' effect like 'runB9' but run 
-- external commands, such as `systemd-nspawn`, 
-- /interactively/.
--
-- When run /interactively/, the stdin/stdout of 
-- certain commands is inherited from the main process.
--
-- @since 2.0.0
runB9Interactive :: HasCallStack => B9 a -> B9ConfigAction a
runB9Interactive :: B9 a -> B9ConfigAction a
runB9Interactive = Bool -> B9 a -> B9ConfigAction a
forall a. HasCallStack => Bool -> B9 a -> B9ConfigAction a
runB9Full Bool
True

runB9Full :: HasCallStack => Bool -> B9 a -> B9ConfigAction a
runB9Full :: Bool -> B9 a -> B9ConfigAction a
runB9Full Bool
interactive B9 a
action = do
  B9Config
cfg <- Eff
  '[B9ConfigWriter, B9ConfigReader, EnvironmentReader, Lift IO]
  B9Config
forall (e :: [* -> *]). Member B9ConfigReader e => Eff e B9Config
getB9Config
  Environment
env <- Eff
  '[B9ConfigWriter, B9ConfigReader, EnvironmentReader, Lift IO]
  Environment
forall (e :: [* -> *]).
Member EnvironmentReader e =>
Eff e Environment
askEnvironment
  IO a -> B9ConfigAction a
forall (m :: * -> *) (r :: [* -> *]) a.
Lifted m r =>
m a -> Eff r a
lift
    ( Eff '[Lift IO] a -> IO a
forall (m :: * -> *) w. Monad m => Eff '[Lift m] w -> m w
runLift
        (Eff '[Lift IO] a -> IO a)
-> (B9 a -> Eff '[Lift IO] a) -> B9 a -> IO a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Eff '[ExcB9, Lift IO] a -> Eff '[Lift IO] a
forall (e :: [* -> *]) a.
Lifted IO e =>
Eff (ExcB9 : e) a -> Eff e a
errorOnException
        (Eff '[ExcB9, Lift IO] a -> Eff '[Lift IO] a)
-> (B9 a -> Eff '[ExcB9, Lift IO] a) -> B9 a -> Eff '[Lift IO] a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Environment
-> Eff '[EnvironmentReader, ExcB9, Lift IO] a
-> Eff '[ExcB9, Lift IO] a
forall (e :: [* -> *]) a.
Environment -> Eff (EnvironmentReader : e) a -> Eff e a
runEnvironmentReader Environment
env
        (Eff '[EnvironmentReader, ExcB9, Lift IO] a
 -> Eff '[ExcB9, Lift IO] a)
-> (B9 a -> Eff '[EnvironmentReader, ExcB9, Lift IO] a)
-> B9 a
-> Eff '[ExcB9, Lift IO] a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. B9Config
-> Eff '[B9ConfigReader, EnvironmentReader, ExcB9, Lift IO] a
-> Eff '[EnvironmentReader, ExcB9, Lift IO] a
forall (e :: [* -> *]) a.
HasCallStack =>
B9Config -> Eff (B9ConfigReader : e) a -> Eff e a
runB9ConfigReader B9Config
cfg
        (Eff '[B9ConfigReader, EnvironmentReader, ExcB9, Lift IO] a
 -> Eff '[EnvironmentReader, ExcB9, Lift IO] a)
-> (B9 a
    -> Eff '[B9ConfigReader, EnvironmentReader, ExcB9, Lift IO] a)
-> B9 a
-> Eff '[EnvironmentReader, ExcB9, Lift IO] a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Eff
  '[LoggerReader, B9ConfigReader, EnvironmentReader, ExcB9, Lift IO]
  a
-> Eff '[B9ConfigReader, EnvironmentReader, ExcB9, Lift IO] a
forall (e :: [* -> *]) a.
(MonadBaseControl IO (Eff e), MonadIO (Eff e),
 Member B9ConfigReader e) =>
Eff (LoggerReader : e) a -> Eff e a
withLogger
        (Eff
   '[LoggerReader, B9ConfigReader, EnvironmentReader, ExcB9, Lift IO]
   a
 -> Eff '[B9ConfigReader, EnvironmentReader, ExcB9, Lift IO] a)
-> (B9 a
    -> Eff
         '[LoggerReader, B9ConfigReader, EnvironmentReader, ExcB9, Lift IO]
         a)
-> B9 a
-> Eff '[B9ConfigReader, EnvironmentReader, ExcB9, Lift IO] a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool
-> Eff
     '[BuildInfoReader, LoggerReader, B9ConfigReader, EnvironmentReader,
       ExcB9, Lift IO]
     a
-> Eff
     '[LoggerReader, B9ConfigReader, EnvironmentReader, ExcB9, Lift IO]
     a
forall (e :: [* -> *]) a.
(Lifted IO e, MonadBaseControl IO (Eff e), Member B9ConfigReader e,
 Member ExcB9 e, Member EnvironmentReader e, Member LoggerReader e,
 HasCallStack) =>
Bool -> Eff (BuildInfoReader : e) a -> Eff e a
withBuildInfo Bool
interactive
        (Eff
   '[BuildInfoReader, LoggerReader, B9ConfigReader, EnvironmentReader,
     ExcB9, Lift IO]
   a
 -> Eff
      '[LoggerReader, B9ConfigReader, EnvironmentReader, ExcB9, Lift IO]
      a)
-> (B9 a
    -> Eff
         '[BuildInfoReader, LoggerReader, B9ConfigReader, EnvironmentReader,
           ExcB9, Lift IO]
         a)
-> B9 a
-> Eff
     '[LoggerReader, B9ConfigReader, EnvironmentReader, ExcB9, Lift IO]
     a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Eff
  '[RepoCacheReader, BuildInfoReader, LoggerReader, B9ConfigReader,
    EnvironmentReader, ExcB9, Lift IO]
  a
-> Eff
     '[BuildInfoReader, LoggerReader, B9ConfigReader, EnvironmentReader,
       ExcB9, Lift IO]
     a
forall (e :: [* -> *]) a.
(Member B9ConfigReader e, Lifted IO e) =>
Eff (RepoCacheReader : e) a -> Eff e a
withRemoteRepos
        (Eff
   '[RepoCacheReader, BuildInfoReader, LoggerReader, B9ConfigReader,
     EnvironmentReader, ExcB9, Lift IO]
   a
 -> Eff
      '[BuildInfoReader, LoggerReader, B9ConfigReader, EnvironmentReader,
        ExcB9, Lift IO]
      a)
-> (B9 a
    -> Eff
         '[RepoCacheReader, BuildInfoReader, LoggerReader, B9ConfigReader,
           EnvironmentReader, ExcB9, Lift IO]
         a)
-> B9 a
-> Eff
     '[BuildInfoReader, LoggerReader, B9ConfigReader, EnvironmentReader,
       ExcB9, Lift IO]
     a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. B9 a
-> Eff
     '[RepoCacheReader, BuildInfoReader, LoggerReader, B9ConfigReader,
       EnvironmentReader, ExcB9, Lift IO]
     a
forall (e :: [* -> *]) a.
(Member B9ConfigReader e, Member ExcB9 e) =>
Eff (SelectedRemoteRepoReader : e) a -> Eff e a
withSelectedRemoteRepo
        (B9 a -> IO a) -> B9 a -> IO a
forall a b. (a -> b) -> a -> b
$ B9 a
action
    )