diff options
Diffstat (limited to 'src/Hakyll/Core/Resource/Provider.hs')
| -rw-r--r-- | src/Hakyll/Core/Resource/Provider.hs | 138 |
1 files changed, 29 insertions, 109 deletions
diff --git a/src/Hakyll/Core/Resource/Provider.hs b/src/Hakyll/Core/Resource/Provider.hs index 2ed7797..8f4c83f 100644 --- a/src/Hakyll/Core/Resource/Provider.hs +++ b/src/Hakyll/Core/Resource/Provider.hs @@ -1,125 +1,45 @@ -------------------------------------------------------------------------------- --- | This module provides an API for resource providers. Resource providers --- allow Hakyll to get content from resources; the type of resource depends on --- the concrete instance. --- --- A resource is represented by the 'Resource' type. This is basically just a --- newtype wrapper around 'Identifier' -- but it has an important effect: it --- guarantees that a resource with this identifier can be provided by one or --- more resource providers. --- --- Therefore, it is not recommended to read files directly -- you should use the --- provided 'Resource' methods. --- +-- | This module provides an wrapper API around the file system which does some +-- caching. module Hakyll.Core.Resource.Provider - ( ResourceProvider (..) + ( -- * Constructing resource providers + ResourceProvider + , newResourceProvider + + -- * Querying resource properties , resourceList - , makeResourceProvider , resourceExists - , resourceDigest , resourceModified - ) where - - --------------------------------------------------------------------------------- -import Control.Applicative ((<$>)) -import Control.Concurrent (MVar, readMVar, modifyMVar_, newMVar) -import Data.Map (Map) -import qualified Data.Map as M -import qualified Data.Set as S - - --------------------------------------------------------------------------------- -import Data.Time (UTCTime) -import qualified Crypto.Hash.MD5 as MD5 -import qualified Data.ByteString as B -import qualified Data.ByteString.Lazy as LB - - --------------------------------------------------------------------------------- -import Hakyll.Core.Store (Store) -import Hakyll.Core.Resource -import qualified Hakyll.Core.Store as Store + , resourceModificationTime + -- * Access to raw resource content + , resourceString + , resourceLBS --------------------------------------------------------------------------------- --- | A value responsible for retrieving and listing resources -data ResourceProvider = ResourceProvider - { -- | A set of all resources this provider is able to provide - resourceSet :: S.Set Resource - , -- | Retrieve a certain resource as string - resourceString :: Resource -> IO String - , -- | Retrieve a certain resource as lazy bytestring - resourceLBS :: Resource -> IO LB.ByteString - , -- | Check when a resource was last modified - resourceModificationTime :: Resource -> IO UTCTime - , -- | Cache keeping track of modified items - resourceModifiedCache :: MVar (Map Resource Bool) - } - - --------------------------------------------------------------------------------- --- | Create a resource provider -makeResourceProvider :: [Resource] -- ^ Resource list - -> (Resource -> IO String) -- ^ String reader - -> (Resource -> IO LB.ByteString) -- ^ ByteString reader - -> (Resource -> IO UTCTime) -- ^ Time checker - -> IO ResourceProvider -- ^ Resulting provider -makeResourceProvider l s b t = - ResourceProvider (S.fromList l) s b t <$> newMVar M.empty - - --------------------------------------------------------------------------------- --- | Get the list of all resources -resourceList :: ResourceProvider -> [Resource] -resourceList = S.toList . resourceSet - - --------------------------------------------------------------------------------- --- | Check if a given identifier has a resource -resourceExists :: ResourceProvider -> Resource -> Bool -resourceExists provider = flip S.member $ resourceSet provider + -- * Access to metadata and body content + , resourceMetadata + , resourceBody + ) where -------------------------------------------------------------------------------- --- | Retrieve a digest for a given resource -resourceDigest :: ResourceProvider -> Resource -> IO B.ByteString -resourceDigest provider = fmap MD5.hashlazy . resourceLBS provider +import Hakyll.Core.Resource +import qualified Hakyll.Core.Resource.MetadataCache as Internal +import Hakyll.Core.Resource.Modified +import Hakyll.Core.Resource.Provider.Internal -------------------------------------------------------------------------------- --- | Check if a resource was modified -resourceModified :: ResourceProvider -> Store -> Resource -> IO Bool -resourceModified provider store r = do - cache <- readMVar mvar - case M.lookup r cache of - -- Already in the cache - Just m -> return m - -- Not yet in the cache, check digests (if it exists) - Nothing -> do - m <- if resourceExists provider r - then digestModified provider store r - else return False - modifyMVar_ mvar (return . M.insert r m) - return m - where - mvar = resourceModifiedCache provider +-- | Wrapper to ensure metadata cache is invalidated if necessary +resourceMetadata :: ResourceProvider -> Resource -> IO Metadata +resourceMetadata rp r = do + _ <- resourceModified rp r + Internal.resourceMetadata rp r -------------------------------------------------------------------------------- --- | Check if a resource digest was modified -digestModified :: ResourceProvider -> Store -> Resource -> IO Bool -digestModified provider store r = do - -- Get the latest seen digest from the store - lastDigest <- Store.get store key - -- Calculate the digest for the resource - newDigest <- resourceDigest provider r - -- Check digests - if Store.Found newDigest == lastDigest - -- All is fine, not modified - then return False - -- Resource modified; store new digest - else do Store.set store key newDigest - return True - where - key = ["Hakyll.Core.ResourceProvider.digestModified", unResource r] +-- | Wrapper to ensure metadata cache is invalidated if necessary +resourceBody :: ResourceProvider -> Resource -> IO String +resourceBody rp r = do + _ <- resourceModified rp r + Internal.resourceBody rp r |
