    {-# LANGUAGE TupleSections #-}

    -- | 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

    -- | 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 x = withTempFile $ \file -> do
        exit <- withFile file WriteMode $ \h -> do
            (_, _, _, pid) <- createProcess (shell x){std_out=UseHandle h, std_err=UseHandle h}
            waitForProcess pid
        fmap (exit,) $ readFile' file

    -- | A version of 'system' that throws an error if the 'ExitCode' is not 'ExitSuccess'.
    system_ :: String -> IO ()
    system_ x = do
        res <- system 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_ :: String -> IO String
    systemOutput_ x = do
        (res,out) <- systemOutput x
        when (res /= ExitSuccess) $
            error $ "Failed when running system command: " ++ x
        return out