module Darcs.Util.Exception
( firstJustIO
, catchall
, catchNonExistence
, clarifyErrors
, prettyException
, prettyError
, die
, handleOnly
, handleOnlyIOError
, ifIOError
, ifDoesNotExistError
) where
import Darcs.Prelude
import Control.Exception
( Exception(fromException)
, SomeException
, catch
, handle
, throwIO
)
import Data.Maybe ( isJust )
import System.Exit ( exitFailure )
import System.IO ( stderr, hPutStrLn )
import System.IO.Error
( ioeGetErrorString
, ioeGetFileName
, isDoesNotExistError
, isUserError
)
import Darcs.Util.SignalHandler ( catchNonSignal )
catchall :: IO a
-> IO a
-> IO a
IO a
a catchall :: forall a. IO a -> IO a -> IO a
`catchall` IO a
b = IO a
a forall a. IO a -> (SomeException -> IO a) -> IO a
`catchNonSignal` (\SomeException
_ -> IO a
b)
catchNonExistence :: IO a -> a -> IO a
catchNonExistence :: forall a. IO a -> a -> IO a
catchNonExistence IO a
job a
nonexistval =
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
catch IO a
job forall a b. (a -> b) -> a -> b
$
\IOError
e -> if IOError -> Bool
isDoesNotExistError IOError
e then forall (m :: * -> *) a. Monad m => a -> m a
return a
nonexistval
else forall a. IOError -> IO a
ioError IOError
e
firstJustM :: Monad m
=> [m (Maybe a)]
-> m (Maybe a)
firstJustM :: forall (m :: * -> *) a. Monad m => [m (Maybe a)] -> m (Maybe a)
firstJustM [] = forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing
firstJustM (m (Maybe a)
e:[m (Maybe a)]
es) = m (Maybe a)
e forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (\Maybe a
v -> if forall a. Maybe a -> Bool
isJust Maybe a
v then forall (m :: * -> *) a. Monad m => a -> m a
return Maybe a
v else forall (m :: * -> *) a. Monad m => [m (Maybe a)] -> m (Maybe a)
firstJustM [m (Maybe a)]
es)
firstJustIO :: [IO (Maybe a)]
-> IO (Maybe a)
firstJustIO :: forall a. [IO (Maybe a)] -> IO (Maybe a)
firstJustIO = forall (m :: * -> *) a. Monad m => [m (Maybe a)] -> m (Maybe a)
firstJustM forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map (forall a. IO a -> IO a -> IO a
`catchall` forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing)
clarifyErrors :: IO a
-> String
-> IO a
clarifyErrors :: forall a. IO a -> String -> IO a
clarifyErrors IO a
a String
e = IO a
a forall e a. Exception e => IO a -> (e -> IO a) -> IO a
`catch` (\SomeException
x -> forall a. String -> IO a
die forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines [SomeException -> String
prettyException SomeException
x,String
e])
prettyException :: SomeException
-> String
prettyException :: SomeException -> String
prettyException SomeException
e | Just IOError
ioe <- forall e. Exception e => SomeException -> Maybe e
fromException SomeException
e, IOError -> Bool
isUserError IOError
ioe = IOError -> String
ioeGetErrorString IOError
ioe
prettyException SomeException
e | Just IOError
ioe <- forall e. Exception e => SomeException -> Maybe e
fromException SomeException
e, IOError -> Bool
isDoesNotExistError IOError
ioe =
case IOError -> Maybe String
ioeGetFileName IOError
ioe of
Just String
f -> String
f forall a. [a] -> [a] -> [a]
++ String
" does not exist"
Maybe String
Nothing -> forall a. Show a => a -> String
show SomeException
e
prettyException SomeException
e = forall a. Show a => a -> String
show SomeException
e
prettyError :: IOError -> String
prettyError :: IOError -> String
prettyError IOError
e | IOError -> Bool
isUserError IOError
e = IOError -> String
ioeGetErrorString IOError
e
| Bool
otherwise = forall a. Show a => a -> String
show IOError
e
die :: String -> IO a
die :: forall a. String -> IO a
die String
msg = Handle -> String -> IO ()
hPutStrLn Handle
stderr String
msg forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall a. IO a
exitFailure
handleOnlyIOError :: IO a -> IO a -> IO a
handleOnlyIOError :: forall a. IO a -> IO a -> IO a
handleOnlyIOError = forall e a. Exception e => (e -> Bool) -> IO a -> IO a -> IO a
handleOnly (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. IOError -> Bool
isUserError)
ifIOError :: a -> IO a -> IO a
ifIOError :: forall a. a -> IO a -> IO a
ifIOError a
use_instead = forall a. IO a -> IO a -> IO a
handleOnlyIOError (forall (m :: * -> *) a. Monad m => a -> m a
return a
use_instead)
ifDoesNotExistError :: a -> IO a -> IO a
ifDoesNotExistError :: forall a. a -> IO a -> IO a
ifDoesNotExistError a
use_instead = forall e a. Exception e => (e -> Bool) -> IO a -> IO a -> IO a
handleOnly IOError -> Bool
isDoesNotExistError (forall (m :: * -> *) a. Monad m => a -> m a
return a
use_instead)
handleOnly :: Exception e => (e -> Bool) -> IO a -> IO a -> IO a
handleOnly :: forall e a. Exception e => (e -> Bool) -> IO a -> IO a -> IO a
handleOnly e -> Bool
pred IO a
handler = forall e a. Exception e => (e -> IO a) -> IO a -> IO a
handle (\e
e -> if e -> Bool
pred e
e then IO a
handler else forall e a. Exception e => e -> IO a
throwIO e
e)