Skip to content

Commit f038fbe

Browse files
committed
Introduce CommandIOException
This introduces a structured exception for the result of running an external process. By using a structured type, the build system can catch these exceptions and control how they are displayed to the user rather than relying on the default shake formatting.
1 parent 84beb23 commit f038fbe

File tree

2 files changed

+28
-11
lines changed

2 files changed

+28
-11
lines changed

src/Development/Shake.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ module Development.Shake(
5555
Rules, action, withoutActions, alternatives, priority, versioned,
5656
Action, traced,
5757
liftIO, actionOnException, actionFinally, actionBracket, actionCatch, actionRetry, runAfter,
58-
ShakeException(..),
58+
ShakeException(..), CommandIOException(..),
5959
-- * Configuration
6060
ShakeOptions(..), Rebuild(..), Lint(..), Change(..),
6161
getShakeOptions, getShakeOptionsRules, getHashedShakeVersion,

src/Development/Shake/Command.hs

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ module Development.Shake.Command(
1717
command, command_, cmd, cmd_, unit, CmdArgument(..), CmdArguments(..), IsCmdArgument(..), (:->),
1818
Stdout(..), StdoutTrim(..), Stderr(..), Stdouterr(..), Exit(..), Process(..), CmdTime(..), CmdLine(..), FSATrace(..),
1919
CmdResult, CmdString, CmdOption(..),
20-
addPath, addEnv,
20+
addPath, addEnv, CommandIOException(..)
2121
) where
2222

2323
import Data.Tuple.Extra
@@ -417,15 +417,32 @@ commandExplicitIO params = removeOptionShell params $ \params -> removeOptionFSA
417417
Just v -> do
418418
v <- canonicalizePath v `catchIO` const (pure v)
419419
pure $ "Current directory: " ++ v ++ "\n"
420-
liftIO $ errorIO $
421-
"Development.Shake." ++ funcName ++ ", system command failed\n" ++
422-
"Command line: " ++ optRealCommand ++ "\n" ++
423-
(if optRealCommand /= optUserCommand then "Original command line: " ++ optUserCommand ++ "\n" else "") ++
424-
cwd ++
425-
"Exit code: " ++ show (case exit of ExitFailure i -> i; _ -> 0) ++ "\n" ++
426-
if null captured then "Stderr not captured because WithStderr False was used\n"
427-
else if null exceptionBuffer then intercalate " and " captured ++ " " ++ (if length captured == 1 then "was" else "were") ++ " empty"
428-
else intercalate " and " captured ++ ":\n" ++ unlines (dropWhile null $ lines $ concat exceptionBuffer)
420+
liftIO $ throwIO $ CommandIOException funcName optRealCommand optUserCommand
421+
cwd exit captured exceptionBuffer
422+
423+
-- | An IO exception which arose from running a command.
424+
data CommandIOException =
425+
CommandIOException { commandIO_funcName :: String -- ^ The name of the command
426+
, commandIO_realCommand :: String -- ^ The command line which was run
427+
, commandIO_userCommand :: String -- ^ The user given name to the command (by using 'UserCommand')
428+
, commandIO_cwd :: FilePath -- ^ Directory the command was run in
429+
, commandIO_exit :: ExitCode -- ^ The exit code of the command
430+
, commandIO_captured :: [String] -- ^ The handles which were captured (ie "Stderr", "Stdout", modified with 'WithStdout' and 'WithStderr')
431+
, commandIO_exceptionBuffer :: [String] -- ^ The captured output
432+
}
433+
434+
instance Exception CommandIOException
435+
436+
instance Show CommandIOException where
437+
show CommandIOException{..} =
438+
"Development.Shake." ++ commandIO_funcName ++ ", system command failed\n" ++
439+
"Command line: " ++ commandIO_realCommand ++ "\n" ++
440+
(if commandIO_realCommand /= commandIO_userCommand then "Original command line: " ++ commandIO_userCommand ++ "\n" else "") ++
441+
commandIO_cwd ++
442+
"Exit code: " ++ show (case commandIO_exit of ExitFailure i -> i; _ -> 0) ++ "\n" ++
443+
if null commandIO_captured then "Stderr not captured because WithStderr False was used\n"
444+
else if null commandIO_exceptionBuffer then intercalate " and " commandIO_captured ++ " " ++ (if length commandIO_captured == 1 then "was" else "were") ++ " empty"
445+
else intercalate " and " commandIO_captured ++ ":\n" ++ unlines (dropWhile null $ lines $ concat commandIO_exceptionBuffer)
429446

430447

431448
mergeCwd :: [FilePath] -> Maybe FilePath

0 commit comments

Comments
 (0)