    {-# LANGUAGE TupleSections, ConstraintKinds #-}

    -- | Extra functions for creating processes. Specifically variants that automatically check
    --   the 'ExitCode' and capture the 'stdout' \/ 'stderr' handles.
    module System.Process.Extra(
        module System.Process,
        system_, systemOutput, systemOutput_
        ) where

    import Control.Monad
    import System.IO.Extra
    import System.Process
    import System.Exit
    import Data.Functor
    import Partial
    import Prelude

    -- | A version of 'system' that also captures the output, both 'stdout' and 'stderr'.
    --   Returns a pair of the 'ExitCode' and the output.
    systemOutput :: String -> IO (ExitCode, String)
    systemOutput :: String -> IO (ExitCode, String)
    systemOutput String
    x = (String -> IO (ExitCode, String)) -> IO (ExitCode, String)
    forall a. (String -> IO a) -> IO a
    withTempFile ((String -> IO (ExitCode, String)) -> IO (ExitCode, String))
    -> (String -> IO (ExitCode, String)) -> IO (ExitCode, String)
    forall a b. (a -> b) -> a -> b
    $ \String
    file -> do
        exit <- String -> IOMode -> (Handle -> IO ExitCode) -> IO ExitCode
    forall r. String -> IOMode -> (Handle -> IO r) -> IO r
    withFile String
    file IOMode
    WriteMode ((Handle -> IO ExitCode) -> IO ExitCode)
    -> (Handle -> IO ExitCode) -> IO ExitCode
    forall a b. (a -> b) -> a -> b
    $ \Handle
    h -> do
            (_, _, _, pid) <- CreateProcess
    -> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
    createProcess (String -> CreateProcess
    shell String
    x){std_out=UseHandle h, std_err=UseHandle h}
            waitForProcess pid
        (exit,) <$> readFile' file

    -- | A version of 'system' that throws an error if the 'ExitCode' is not 'ExitSuccess'.
    system_ :: Partial => String -> IO ()
    system_ :: Partial => String -> IO ()
    system_ String
    x = do
        res <- String -> IO ExitCode
    system String
    x
        when (res /= ExitSuccess) $
            error $ "Failed when running system command: " ++ x

    -- | A version of 'system' that captures the output (both 'stdout' and 'stderr')
    --   and throws an error if the 'ExitCode' is not 'ExitSuccess'.
    systemOutput_ :: Partial => String -> IO String
    systemOutput_ :: Partial => String -> IO String
    systemOutput_ String
    x = do
        (res,out) <- String -> IO (ExitCode, String)
    systemOutput String
    x
        when (res /= ExitSuccess) $
            error $ "Failed when running system command: " ++ x
        pure out