-- | Template haskell expression to embed executables.
module Hydra.Node.EmbedTH where

import Hydra.Prelude

import Data.FileEmbed (embedFile)
import Language.Haskell.TH (Exp, Q, runIO)
import System.Directory (findExecutable)

-- | Template haskell expression to find and embed an executable with given name.
embedExecutable :: String -> Q Exp
embedExecutable :: String -> Q Exp
embedExecutable String
exe = do
  String
fp <- IO String -> Q String
forall a. IO a -> Q a
runIO (IO String -> Q String) -> IO String -> Q String
forall a b. (a -> b) -> a -> b
$ do
    String -> IO (Maybe String)
findExecutable String
exe IO (Maybe String) -> (Maybe String -> IO String) -> IO String
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
      Maybe String
Nothing -> String -> IO String
forall a. String -> IO a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> IO String) -> String -> IO String
forall a b. (a -> b) -> a -> b
$ String
exe String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" not found, ensure it is in PATH when compiling (and do a cabal clean)"
      Just String
fp -> do
        String -> IO ()
forall (m :: * -> *). MonadIO m => String -> m ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ String
"Embedding " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
exe String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" from: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
fp
        String -> IO String
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
fp
  String -> Q Exp
embedFile String
fp