@@ -124,14 +124,18 @@ cabalFromDirectory dir = do
124 _ -> liftIO $ hPutStrLn stderr "*** found zero or more than one cabal file. Exiting." >> exitFailure
124 _ -> liftIO $ hPutStrLn stderr "*** found zero or more than one cabal file. Exiting." >> exitFailure
126cabalFromFile :: Bool -> FilePath -> MaybeT IO Cabal.GenericPackageDescription
126cabalFromFile :: Bool -> FilePath -> MaybeT IO Cabal.GenericPackageDescription
127−cabalFromFile failHard file = do
127+cabalFromFile failHard file =
128− content <- MaybeT $ either (const Nothing) Just <$> Compat.tryIO (readFile file)
128+ -- readFile throws an error if it's used on binary files which contain sequences
129+ -- that do not represent valid characters. To catch that exception, we need to
130+ -- wrap the whole block in `catchIO`, because of lazy IO. The `case` will force
131+ -- the reading of the file, so we will always catch the expression here.
132+ MaybeT $ flip Compat.catchIO (const $ return Nothing) $ do
133+ content <- readFile file
129− case Cabal.parsePackageDescription content of
134+ case Cabal.parsePackageDescription content of
130− Cabal.ParseFailed e -> do
135+ Cabal.ParseFailed e | failHard -> do
133 let (line, err) = ParseUtils.locatedErrorMsg e
136 let (line, err) = ParseUtils.locatedErrorMsg e
134 msg = maybe "" ((++ ": ") . show) line ++ err
137 msg = maybe "" ((++ ": ") . show) line ++ err
135 putStrLn $ "*** error parsing cabal file: " ++ msg
138 putStrLn $ "*** error parsing cabal file: " ++ msg
136 exitFailure
139 exitFailure
140+ Cabal.ParseFailed _ -> return Nothing
137− Cabal.ParseOk _ a -> return a
141+ Cabal.ParseOk _ a -> return (Just a)