forked from commercialhaskell/stack
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRun.hs
More file actions
93 lines (87 loc) · 3.36 KB
/
Run.hs
File metadata and controls
93 lines (87 loc) · 3.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE FlexibleContexts #-}
-- | Reading from external processes.
module System.Process.Run
(runIn
,callProcess
,callProcess'
,ProcessExitedUnsuccessfully)
where
import Control.Exception.Lifted
import Control.Monad.Trans.Control (MonadBaseControl)
import Control.Monad.IO.Class (MonadIO, liftIO)
import Control.Monad.Logger (MonadLogger, logError)
import Data.Conduit.Process hiding (callProcess)
import Data.Foldable (forM_)
import Data.Text (Text)
import qualified Data.Text as T
import Path (Path, Abs, Dir, toFilePath)
import Prelude -- Fix AMP warning
import System.Exit (exitWith, ExitCode (..))
import qualified System.Process
import System.Process.Read
-- | Run the given command in the given directory, inheriting stdout
-- and stderr. If it exits with anything but success, prints an error
-- and then calls 'exitWith' to exit the program.
runIn :: forall (m :: * -> *).
(MonadLogger m,MonadIO m,MonadBaseControl IO m)
=> Path Abs Dir -- ^ directory to run in
-> FilePath -- ^ command to run
-> EnvOverride
-> [String] -- ^ command line arguments
-> Maybe Text
-> m ()
runIn wd cmd menv args errMsg = do
result <- try (callProcess (Just wd) menv cmd args)
case result of
Left (ProcessExitedUnsuccessfully _ ec) -> do
$logError $
T.pack $
concat
[ "Exit code "
, show ec
, " while running "
, show (cmd : args)
, " in "
, toFilePath wd]
forM_ errMsg $logError
liftIO (exitWith ec)
Right () -> return ()
-- | Like as @System.Process.callProcess@, but takes an optional working directory and
-- environment override, and throws ProcessExitedUnsuccessfully if the
-- process exits unsuccessfully. Inherits stdout and stderr.
callProcess :: (MonadIO m, MonadLogger m)
=> Maybe (Path Abs Dir)
-> EnvOverride
-> String
-> [String]
-> m ()
callProcess =
callProcess' id
-- | Like as @System.Process.callProcess@, but takes an optional working directory and
-- environment override, and throws ProcessExitedUnsuccessfully if the
-- process exits unsuccessfully. Inherits stdout and stderr.
callProcess' :: (MonadIO m, MonadLogger m)
=> (CreateProcess -> CreateProcess)
-> Maybe (Path Abs Dir)
-> EnvOverride
-> String
-> [String]
-> m ()
callProcess' modCP wd menv cmd0 args = do
cmd <- preProcess wd menv cmd0
let c = modCP $ (proc cmd args) { delegate_ctlc = True
, cwd = fmap toFilePath wd
, env = envHelper menv }
action (_, _, _, p) = do
exit_code <- waitForProcess p
case exit_code of
ExitSuccess -> return ()
ExitFailure _ -> throwIO (ProcessExitedUnsuccessfully c exit_code)
$logProcessRun cmd args
liftIO (System.Process.createProcess c >>= action)