module Hakyll.Core.Resource.Provider
( ResourceProvider (..)
, resourceExists
, resourceDigest
, resourceModified
) where
import Control.Concurrent (MVar, readMVar, modifyMVar_)
import Control.Monad ((<=<))
import Data.Word (Word8)
import Data.Map (Map)
import qualified Data.Map as M
import qualified Data.ByteString.Lazy as LB
import OpenSSL.Digest.ByteString.Lazy (digest)
import OpenSSL.Digest (MessageDigest (MD5))
import Hakyll.Core.Identifier
import Hakyll.Core.Store
import Hakyll.Core.Resource
data ResourceProvider = ResourceProvider
{
resourceList :: [Resource]
,
resourceString :: Resource -> IO String
,
resourceLazyByteString :: Resource -> IO LB.ByteString
,
resourceModifiedCache :: MVar (Map Resource Bool)
}
resourceExists :: ResourceProvider -> Identifier -> Bool
resourceExists provider = flip elem $ map unResource $ resourceList provider
resourceDigest :: ResourceProvider -> Resource -> IO [Word8]
resourceDigest provider = digest MD5 <=< resourceLazyByteString provider
resourceModified :: ResourceProvider -> Resource -> Store -> IO Bool
resourceModified provider resource store = do
cache <- readMVar mvar
case M.lookup resource cache of
Just m -> return m
Nothing -> do
m <- if resourceExists provider (unResource resource)
then digestModified provider resource store
else return False
modifyMVar_ mvar (return . M.insert resource m)
return m
where
mvar = resourceModifiedCache provider
digestModified :: ResourceProvider -> Resource -> Store -> IO Bool
digestModified provider resource store = do
lastDigest <- storeGet store itemName $ unResource resource
newDigest <- resourceDigest provider resource
if Just newDigest == lastDigest
then return False
else do storeSet store itemName (unResource resource) newDigest
return True
where
itemName = "Hakyll.Core.ResourceProvider.digestModified"