on master help sign in
Merge pull request #104 from liskin/directory-canonicalizePath-exception
02b2d5dMichael Snoyman
ChangeLog.md+4
@@ -1,3 +1,7 @@
1+## 0.8.21.2
2+
3+* Fix wrong file not found exception in `Data.Yaml.Include` with pre-1.2.3.0 `directory` [#104](https://github.com/snoyberg/yaml/pull/104)
4+
1## 0.8.21.1
5## 0.8.21.1
2
6
3* Add missing test files [#102](https://github.com/snoyberg/yaml/pull/102)
7* Add missing test files [#102](https://github.com/snoyberg/yaml/pull/102)
Data/Yaml/Include.hs+19−1
@@ -1,6 +1,13 @@
1+{-# LANGUAGE CPP #-}
1{-# LANGUAGE RankNTypes #-}
2{-# LANGUAGE RankNTypes #-}
2module Data.Yaml.Include (decodeFile, decodeFileEither) where
3module Data.Yaml.Include (decodeFile, decodeFileEither) where
3
4
5+#if !MIN_VERSION_directory(1, 2, 3)
6+import Control.Exception (handleJust)
7+import Control.Monad (guard)
8+import System.IO.Error (ioeGetFileName, ioeGetLocation, isDoesNotExistError)
9+#endif
10+
4import Control.Exception (throwIO)
11import Control.Exception (throwIO)
5import Control.Monad (when)
12import Control.Monad (when)
6import Control.Monad.IO.Class (liftIO)
13import Control.Monad.IO.Class (liftIO)
@@ -25,7 +32,7 @@ eventsFromFile = go []
25 where
32 where
26 go :: MonadResource m => [FilePath] -> FilePath -> Producer m Event
33 go :: MonadResource m => [FilePath] -> FilePath -> Producer m Event
27 go seen fp = do
34 go seen fp = do
28− cfp <- liftIO $ canonicalizePath fp
35+ cfp <- liftIO $ handleNotFound $ canonicalizePath fp
29 when (cfp `elem` seen) $ do
36 when (cfp `elem` seen) $ do
30 liftIO $ throwIO CyclicIncludes
37 liftIO $ throwIO CyclicIncludes
31 Y.decodeFile cfp $= do
38 Y.decodeFile cfp $= do
@@ -37,6 +44,17 @@ eventsFromFile = go []
37
44
38 irrelevantEvents = [EventStreamStart, EventDocumentStart, EventDocumentEnd, EventStreamEnd]
45 irrelevantEvents = [EventStreamStart, EventDocumentStart, EventDocumentEnd, EventStreamEnd]
39
46
47+#if !MIN_VERSION_directory(1, 2, 3)
48+ handleNotFound = handleJust
49+ (\e -> do
50+ guard (isDoesNotExistError e)
51+ guard (ioeGetLocation e == "canonicalizePath")
52+ ioeGetFileName e)
53+ (throwIO . YamlException . ("Yaml file not found: " ++))
54+#else
55+ handleNotFound = id
56+#endif
57+
40-- | Like `Data.Yaml.decodeFile` but with support for relative and absolute
58-- | Like `Data.Yaml.decodeFile` but with support for relative and absolute
41-- includes.
59-- includes.
42--
60--
test/Data/Yaml/IncludeSpec.hs+15−5
@@ -2,12 +2,12 @@
2module Data.Yaml.IncludeSpec (main, spec) where
2module Data.Yaml.IncludeSpec (main, spec) where
3
3
4import Test.Hspec
4import Test.Hspec
5−import Data.Either.Compat
5+import Data.List (isPrefixOf)
6import Data.Aeson
6import Data.Aeson
7import Data.Aeson.QQ
7import Data.Aeson.QQ
8−import Data.Yaml (ParseException)
8+import Data.Yaml (ParseException(InvalidYaml))
9−
10import Data.Yaml.Include
9import Data.Yaml.Include
10+import Text.Libyaml (YamlException(YamlException))
11
11
12main :: IO ()
12main :: IO ()
13main = hspec spec
13main = hspec spec
@@ -38,7 +38,17 @@ spec = do
38 it "aborts on cyclic includes" $ do
38 it "aborts on cyclic includes" $ do
39 (decodeFile "test/resources/loop/foo.yaml" :: IO (Maybe Value)) `shouldThrow` anyException
39 (decodeFile "test/resources/loop/foo.yaml" :: IO (Maybe Value)) `shouldThrow` anyException
40
40
41+ context "when file does not exist" $ do
42+ it "throws Left (InvalidYaml (Just (YamlException \"Yaml file not found: ...\")))" $ do
43+ (decodeFile "./does_not_exist.yaml" :: IO (Maybe Value)) `shouldThrow` isYamlFileNotFoundException
44+
41 describe "decodeFileEither" $ do
45 describe "decodeFileEither" $ do
42 context "when file does not exist" $ do
46 context "when file does not exist" $ do
43− it "returns Left" $ do
47+ it "returns Left (InvalidYaml (Just (YamlException \"Yaml file not found: ...\")))" $ do
44− (decodeFileEither "./does_not_exist.yaml" :: IO (Either ParseException Value)) >>= (`shouldSatisfy` isLeft)
48+ (decodeFileEither "./does_not_exist.yaml" :: IO (Either ParseException Value)) >>=
49+ (`shouldSatisfy` either isYamlFileNotFoundException (const False))
50+
51+isYamlFileNotFoundException :: ParseException -> Bool
52+isYamlFileNotFoundException (InvalidYaml (Just (YamlException msg)))
53+ | "Yaml file not found: " `isPrefixOf` msg = True
54+isYamlFileNotFoundException _ = False
yaml.cabal+1−1
@@ -1,5 +1,5 @@
1name: yaml
1name: yaml
2−version: 0.8.21.1
2+version: 0.8.21.2
3license: BSD3
3license: BSD3
4license-file: LICENSE
4license-file: LICENSE
5author: Michael Snoyman <michael@snoyman.com>, Anton Ageev <antage@gmail.com>,Kirill Simonov
5author: Michael Snoyman <michael@snoyman.com>, Anton Ageev <antage@gmail.com>,Kirill Simonov