packages feed

feedback-0.0.0.0: src/Feedback/Common/Process.hs

{-# LANGUAGE RecordWildCards #-}
{-# OPTIONS_GHC -fno-warn-unused-pattern-binds #-}

module Feedback.Common.Process where

import Data.Map as M
import qualified Data.Text as T
import qualified Data.Text.Encoding as TE
import Feedback.Common.OptParse
import Path
import Path.IO
import System.Environment as System (getEnvironment)
import System.Exit
import System.Process.Typed as Typed
import UnliftIO.IO.File

data ProcessHandle = ProcessHandle
  { processHandleProcess :: !P
  }

type P = Process () () ()

startProcessAndWait :: RunSettings -> IO ExitCode
startProcessAndWait runSettings = do
  processConfig <- makeProcessConfigFor runSettings
  startProcess processConfig >>= waitExitCode

startProcessHandle :: RunSettings -> IO ProcessHandle
startProcessHandle runSettings = do
  processConfig <- makeProcessConfigFor runSettings
  processHandleProcess <- startProcess processConfig
  pure ProcessHandle {..}

waitProcessHandle :: ProcessHandle -> IO ExitCode
waitProcessHandle ProcessHandle {..} = waitExitCode processHandleProcess

makeProcessConfigFor :: RunSettings -> IO (ProcessConfig () () ())
makeProcessConfigFor RunSettings {..} = do
  let RunSettings _ _ _ = undefined
  -- Set up the environment
  env <- System.getEnvironment
  let envForProcess = M.toList $ M.union runSettingExtraEnv (M.fromList env)
  -- Set up the command
  commandString <- case runSettingCommand of
    CommandArgs c -> pure c
    CommandScript s -> do
      -- Write the script to a file
      systemTempDir <- getTempDir
      scriptFile <- resolveFile systemTempDir "feedback-script.sh"
      writeBinaryFileDurableAtomic (fromAbsFile scriptFile) (TE.encodeUtf8 (T.pack s))
      -- Make the script executable
      oldPermissions <- getPermissions scriptFile
      let newPermissions = setOwnerExecutable True oldPermissions
      setPermissions scriptFile newPermissions

      pure $ fromAbsFile scriptFile

  pure $
    setStdout inherit
      . setStderr inherit
      . setStdin closed -- TODO make this configurable?
      . setEnv envForProcess
      . maybe id (setWorkingDir . fromAbsDir) runSettingWorkingDir
      $ shell commandString

stopProcessHandle :: ProcessHandle -> IO ()
stopProcessHandle ProcessHandle {..} = do
  stopProcess processHandleProcess
  -- No need to cancel the waiter thread.
  pure ()