From 4a280ee4fc6954950db587352b49bbab6cd36828 Mon Sep 17 00:00:00 2001 From: Charlie Durham Date: Sun, 9 May 2021 22:40:33 -0400 Subject: [PATCH 1/3] added 'embedFileIfExists' --- Data/FileEmbed.hs | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/Data/FileEmbed.hs b/Data/FileEmbed.hs index ca796c0..a9edb92 100644 --- a/Data/FileEmbed.hs +++ b/Data/FileEmbed.hs @@ -19,6 +19,7 @@ module Data.FileEmbed ( -- * Embed at compile time embedFile + , embedFileIfExists , embedOneFileOf , embedDir , embedDirListing @@ -60,13 +61,14 @@ import qualified Data.ByteString.Internal as B #endif import System.Directory (doesDirectoryExist, doesFileExist, getDirectoryContents, canonicalizePath) -import Control.Exception (throw, ErrorCall(..)) -import Control.Monad (filterM) +import Control.Exception (throw, tryJust, ErrorCall(..)) +import Control.Monad (filterM, guard) import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as B8 import Control.Arrow ((&&&), second) import Control.Applicative ((<$>)) import Data.ByteString.Unsafe (unsafePackAddressLen) +import System.IO.Error (isDoesNotExistError) import System.IO.Unsafe (unsafePerformIO) import System.FilePath ((), takeDirectory, takeExtension) import Data.String (fromString) @@ -87,6 +89,26 @@ embedFile fp = #endif (runIO $ B.readFile fp) >>= bsToExp +-- | Maybe embed a single file in your source code depending on whether or not file exists. +-- +-- Warning: Does not use `qAddDependentFile` to force a recompile depending on changes to or appearance of the file. +-- +-- > import qualified Data.ByteString +-- > +-- > maybeMyFile :: Maybe Data.ByteString.ByteString +-- > maybeMyFile = $(embedFileIfExists "dirName/fileName") +embedFileIfExists :: FilePath -> Q Exp +embedFileIfExists fp = runIO maybeFile >>= maybeBsToExp + where + maybeFile :: IO (Maybe B.ByteString) + maybeFile = + either (const Nothing) Just <$> + tryJust (guard . isDoesNotExistError) (B.readFile fp) + + maybeBsToExp :: Maybe B.ByteString -> Q Exp + maybeBsToExp Nothing = [| Nothing |] + maybeBsToExp (Just bs) = [| Just $(bsToExp bs) |] + -- | Embed a single existing file in your source code -- out of list a list of paths supplied. -- From 752a2b80a670ded37027e97c0a1070c2ffa089ee Mon Sep 17 00:00:00 2001 From: Charles Durham Date: Mon, 10 May 2021 10:06:01 -0400 Subject: [PATCH 2/3] added 'qAddDependentFile' to 'embedFileIfExists' and some tests --- Data/FileEmbed.hs | 17 +++++++++++------ file-embed.cabal | 1 + test/main.hs | 7 +++++++ 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/Data/FileEmbed.hs b/Data/FileEmbed.hs index a9edb92..5846e70 100644 --- a/Data/FileEmbed.hs +++ b/Data/FileEmbed.hs @@ -91,24 +91,29 @@ embedFile fp = -- | Maybe embed a single file in your source code depending on whether or not file exists. -- --- Warning: Does not use `qAddDependentFile` to force a recompile depending on changes to or appearance of the file. +-- Warning: When a build is compiled with the file missing, a recompile when the file exists might not trigger an embed of the file. +-- You might try to fix this by doing a clean build. -- -- > import qualified Data.ByteString -- > -- > maybeMyFile :: Maybe Data.ByteString.ByteString -- > maybeMyFile = $(embedFileIfExists "dirName/fileName") embedFileIfExists :: FilePath -> Q Exp -embedFileIfExists fp = runIO maybeFile >>= maybeBsToExp +embedFileIfExists fp = do + mbs <- runIO maybeFile + case mbs of + Nothing -> [| Nothing |] + Just bs -> do +#if MIN_VERSION_template_haskell(2,7,0) + qAddDependentFile fp +#endif + [| Just $(bsToExp bs) |] where maybeFile :: IO (Maybe B.ByteString) maybeFile = either (const Nothing) Just <$> tryJust (guard . isDoesNotExistError) (B.readFile fp) - maybeBsToExp :: Maybe B.ByteString -> Q Exp - maybeBsToExp Nothing = [| Nothing |] - maybeBsToExp (Just bs) = [| Just $(bsToExp bs) |] - -- | Embed a single existing file in your source code -- out of list a list of paths supplied. -- diff --git a/file-embed.cabal b/file-embed.cabal index 5ba1889..894a586 100644 --- a/file-embed.cabal +++ b/file-embed.cabal @@ -33,6 +33,7 @@ test-suite test main-is: main.hs hs-source-dirs: test build-depends: base + , bytestring , file-embed , filepath diff --git a/test/main.hs b/test/main.hs index 31c4067..4b665c8 100644 --- a/test/main.hs +++ b/test/main.hs @@ -2,6 +2,7 @@ {-# LANGUAGE OverloadedStrings #-} import Control.Monad (unless) +import qualified Data.ByteString as B (ByteString) import Data.FileEmbed import System.FilePath (()) @@ -19,3 +20,9 @@ main = do ] let str = $(embedStringFile "test/sample/foo") :: String filter (/= '\r') str @?= "foo\n" + + let mbs = $(embedFileIfExists "test/sample/foo") + mbs @?= Just "foo\r\n" + + let mbs2 = $(embedFileIfExists "test/sample/foo2") :: Maybe B.ByteString + mbs2 @?= Nothing From 65cc8e5e90d49b67682c6e829aa933fdc97be555 Mon Sep 17 00:00:00 2001 From: Charles Durham Date: Mon, 10 May 2021 10:33:59 -0400 Subject: [PATCH 3/3] updated for '\r' --- test/main.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/main.hs b/test/main.hs index 4b665c8..351eead 100644 --- a/test/main.hs +++ b/test/main.hs @@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings #-} import Control.Monad (unless) -import qualified Data.ByteString as B (ByteString) +import qualified Data.ByteString as B (ByteString, filter) import Data.FileEmbed import System.FilePath (()) @@ -22,7 +22,7 @@ main = do filter (/= '\r') str @?= "foo\n" let mbs = $(embedFileIfExists "test/sample/foo") - mbs @?= Just "foo\r\n" + fmap (B.filter (/= fromIntegral (fromEnum '\r'))) mbs @?= Just "foo\n" let mbs2 = $(embedFileIfExists "test/sample/foo2") :: Maybe B.ByteString mbs2 @?= Nothing