From 4b7c42d644a1fb2242ad79a2193edad4ba6b2b7e Mon Sep 17 00:00:00 2001 From: Jasper Van der Jeugt Date: Fri, 24 Dec 2010 08:42:05 +0100 Subject: Add resource provider modules --- src/Hakyll/Core/ResourceProvider.hs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/Hakyll/Core/ResourceProvider.hs (limited to 'src/Hakyll/Core/ResourceProvider.hs') diff --git a/src/Hakyll/Core/ResourceProvider.hs b/src/Hakyll/Core/ResourceProvider.hs new file mode 100644 index 0000000..7b4f94a --- /dev/null +++ b/src/Hakyll/Core/ResourceProvider.hs @@ -0,0 +1,18 @@ +-- | 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. +-- +module Hakyll.Core.ResourceProvider + ( ResourceProvider (..) + ) where + +import Hakyll.Core.Identifier + +-- | A value responsible for retrieving and listing resources +-- +data ResourceProvider = ResourceProvider + { -- | A list of all resources this provider is able to provide + resourceList :: [Identifier] + , -- | Retrieve a certain resource as string + resourceString :: Identifier -> IO String + } -- cgit v1.2.3 From b30123f93cd7aa2deadd079e071899ac8f351993 Mon Sep 17 00:00:00 2001 From: Jasper Van der Jeugt Date: Sun, 26 Dec 2010 16:12:24 +0100 Subject: Add resourceLazyByteString function --- src/Hakyll/Core/ResourceProvider.hs | 8 ++++++-- src/Hakyll/Core/ResourceProvider/FileResourceProvider.hs | 7 +++++-- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'src/Hakyll/Core/ResourceProvider.hs') diff --git a/src/Hakyll/Core/ResourceProvider.hs b/src/Hakyll/Core/ResourceProvider.hs index 7b4f94a..94dda5b 100644 --- a/src/Hakyll/Core/ResourceProvider.hs +++ b/src/Hakyll/Core/ResourceProvider.hs @@ -8,11 +8,15 @@ module Hakyll.Core.ResourceProvider import Hakyll.Core.Identifier +import qualified Data.ByteString.Lazy as LB + -- | A value responsible for retrieving and listing resources -- data ResourceProvider = ResourceProvider { -- | A list of all resources this provider is able to provide - resourceList :: [Identifier] + resourceList :: [Identifier] , -- | Retrieve a certain resource as string - resourceString :: Identifier -> IO String + resourceString :: Identifier -> IO String + , -- | Retrieve a certain resource as lazy bytestring + resourceLazyByteString :: Identifier -> IO LB.ByteString } diff --git a/src/Hakyll/Core/ResourceProvider/FileResourceProvider.hs b/src/Hakyll/Core/ResourceProvider/FileResourceProvider.hs index 442ae9a..72d38be 100644 --- a/src/Hakyll/Core/ResourceProvider/FileResourceProvider.hs +++ b/src/Hakyll/Core/ResourceProvider/FileResourceProvider.hs @@ -6,6 +6,8 @@ module Hakyll.Core.ResourceProvider.FileResourceProvider import Control.Applicative ((<$>)) +import qualified Data.ByteString.Lazy as LB + import Hakyll.Core.ResourceProvider import Hakyll.Core.Identifier import Hakyll.Core.Util.File @@ -16,6 +18,7 @@ fileResourceProvider :: IO ResourceProvider fileResourceProvider = do list <- map parseIdentifier <$> getRecursiveContents "." return $ ResourceProvider - { resourceList = list - , resourceString = readFile . toFilePath + { resourceList = list + , resourceString = readFile . toFilePath + , resourceLazyByteString = LB.readFile . toFilePath } -- cgit v1.2.3 From bc92f7fea561a3f9ae69fd499e817f9244fcb206 Mon Sep 17 00:00:00 2001 From: Jasper Van der Jeugt Date: Sun, 26 Dec 2010 16:22:05 +0100 Subject: Add resourceDigest function --- src/Hakyll/Core/ResourceProvider.hs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'src/Hakyll/Core/ResourceProvider.hs') diff --git a/src/Hakyll/Core/ResourceProvider.hs b/src/Hakyll/Core/ResourceProvider.hs index 94dda5b..ba249ca 100644 --- a/src/Hakyll/Core/ResourceProvider.hs +++ b/src/Hakyll/Core/ResourceProvider.hs @@ -4,11 +4,17 @@ -- module Hakyll.Core.ResourceProvider ( ResourceProvider (..) + , resourceDigest ) where -import Hakyll.Core.Identifier +import Control.Monad ((<=<)) +import Data.Word (Word8) import qualified Data.ByteString.Lazy as LB +import OpenSSL.Digest.ByteString.Lazy (digest) +import OpenSSL.Digest (MessageDigest (MD5)) + +import Hakyll.Core.Identifier -- | A value responsible for retrieving and listing resources -- @@ -20,3 +26,8 @@ data ResourceProvider = ResourceProvider , -- | Retrieve a certain resource as lazy bytestring resourceLazyByteString :: Identifier -> IO LB.ByteString } + +-- | Retrieve a digest for a given resource +-- +resourceDigest :: ResourceProvider -> Identifier -> IO [Word8] +resourceDigest provider = digest MD5 <=< resourceLazyByteString provider -- cgit v1.2.3 From 5b67f20eab333a0a63eddae93fa114d8f5158c61 Mon Sep 17 00:00:00 2001 From: Jasper Van der Jeugt Date: Fri, 31 Dec 2010 12:38:12 +0100 Subject: Prototype of the 'cached' arrow transformer --- src/Hakyll/Core/Compiler.hs | 23 +++++++++++++++++++++++ src/Hakyll/Core/Compiler/Internal.hs | 6 +++++- src/Hakyll/Core/ResourceProvider.hs | 20 ++++++++++++++++++++ src/Hakyll/Core/Run.hs | 3 ++- src/Hakyll/Core/Store.hs | 20 -------------------- 5 files changed, 50 insertions(+), 22 deletions(-) (limited to 'src/Hakyll/Core/ResourceProvider.hs') diff --git a/src/Hakyll/Core/Compiler.hs b/src/Hakyll/Core/Compiler.hs index 5678b0a..67724bd 100644 --- a/src/Hakyll/Core/Compiler.hs +++ b/src/Hakyll/Core/Compiler.hs @@ -8,6 +8,7 @@ module Hakyll.Core.Compiler , getResourceString , require , requireAll + , cached ) where import Prelude hiding ((.), id) @@ -26,6 +27,7 @@ import Hakyll.Core.CompiledItem import Hakyll.Core.Writable import Hakyll.Core.ResourceProvider import Hakyll.Core.Compiler.Internal +import Hakyll.Core.Store -- | Get the identifier of the item that is currently being compiled -- @@ -75,3 +77,24 @@ requireAll pattern f = deps <- getDeps . compilerResourceProvider <$> ask lookup' <- compilerDependencyLookup <$> ask return $ f x $ map (unCompiledItem . lookup') deps + +cached :: (Binary a) + => String + -> Compiler () a + -> Compiler () a +cached name (Compiler d j) = Compiler d $ const $ CompilerM $ do + provider <- compilerResourceProvider <$> ask + identifier <- compilerIdentifier <$> ask + store <- compilerStore <$> ask + modified <- liftIO $ resourceModified provider identifier store + liftIO $ putStrLn $ + show identifier ++ ": " ++ if modified then "MODIFIED" else "OK" + if modified + then do v <- unCompilerM $ j () + liftIO $ storeSet store name identifier v + return v + else do v <- liftIO $ storeGet store name identifier + case v of Just v' -> return v' + Nothing -> error' + where + error' = error "Hakyll.Core.Compiler.cached: Cache corrupt!" diff --git a/src/Hakyll/Core/Compiler/Internal.hs b/src/Hakyll/Core/Compiler/Internal.hs index eee67ef..4209bdc 100644 --- a/src/Hakyll/Core/Compiler/Internal.hs +++ b/src/Hakyll/Core/Compiler/Internal.hs @@ -24,6 +24,7 @@ import Control.Arrow (Arrow, arr, first) import Hakyll.Core.Identifier import Hakyll.Core.CompiledItem import Hakyll.Core.ResourceProvider +import Hakyll.Core.Store -- | A set of dependencies -- @@ -40,6 +41,7 @@ data CompilerEnvironment = CompilerEnvironment , compilerResourceProvider :: ResourceProvider -- ^ Resource provider , compilerDependencyLookup :: DependencyLookup -- ^ Dependency lookup , compilerRoute :: Maybe FilePath -- ^ Site route + , compilerStore :: Store -- ^ Compiler store } -- | The compiler monad @@ -73,8 +75,9 @@ runCompilerJob :: Compiler () a -- ^ Compiler to run -> ResourceProvider -- ^ Resource provider -> DependencyLookup -- ^ Dependency lookup table -> Maybe FilePath -- ^ Route + -> Store -- ^ Store -> IO a -runCompilerJob compiler identifier provider lookup' route = +runCompilerJob compiler identifier provider lookup' route store = runReaderT (unCompilerM $ compilerJob compiler ()) env where env = CompilerEnvironment @@ -82,6 +85,7 @@ runCompilerJob compiler identifier provider lookup' route = , compilerResourceProvider = provider , compilerDependencyLookup = lookup' , compilerRoute = route + , compilerStore = store } runCompilerDependencies :: Compiler () a diff --git a/src/Hakyll/Core/ResourceProvider.hs b/src/Hakyll/Core/ResourceProvider.hs index ba249ca..c522ab6 100644 --- a/src/Hakyll/Core/ResourceProvider.hs +++ b/src/Hakyll/Core/ResourceProvider.hs @@ -5,6 +5,7 @@ module Hakyll.Core.ResourceProvider ( ResourceProvider (..) , resourceDigest + , resourceModified ) where import Control.Monad ((<=<)) @@ -15,6 +16,7 @@ import OpenSSL.Digest.ByteString.Lazy (digest) import OpenSSL.Digest (MessageDigest (MD5)) import Hakyll.Core.Identifier +import Hakyll.Core.Store -- | A value responsible for retrieving and listing resources -- @@ -31,3 +33,21 @@ data ResourceProvider = ResourceProvider -- resourceDigest :: ResourceProvider -> Identifier -> IO [Word8] resourceDigest provider = digest MD5 <=< resourceLazyByteString provider + +-- | Check if a resource was modified +-- +resourceModified :: ResourceProvider -> Identifier -> Store -> IO Bool +resourceModified provider identifier store = do + -- Get the latest seen digest from the store + lastDigest <- storeGet store itemName identifier + -- Calculate the digest for the resource + newDigest <- resourceDigest provider identifier + -- Check digests + if Just newDigest == lastDigest + -- All is fine, not modified + then return False + -- Resource modified; store new digest + else do storeSet store itemName identifier newDigest + return True + where + itemName = "Hakyll.Core.ResourceProvider.resourceModified" diff --git a/src/Hakyll/Core/Run.hs b/src/Hakyll/Core/Run.hs index ccb731c..636f9e4 100644 --- a/src/Hakyll/Core/Run.hs +++ b/src/Hakyll/Core/Run.hs @@ -67,7 +67,8 @@ hakyllWith rules provider store = do where addTarget route' map' (id', comp) = do let url = runRoute route' id' - compiled <- runCompilerJob comp id' provider (dependencyLookup map') url + compiled <- runCompilerJob comp id' provider (dependencyLookup map') + url store putStrLn $ "Generated target: " ++ show id' case url of diff --git a/src/Hakyll/Core/Store.hs b/src/Hakyll/Core/Store.hs index 7e57df2..02b9b4e 100644 --- a/src/Hakyll/Core/Store.hs +++ b/src/Hakyll/Core/Store.hs @@ -5,7 +5,6 @@ module Hakyll.Core.Store , makeStore , storeSet , storeGet - , wasModified ) where import Control.Applicative ((<$>)) @@ -16,7 +15,6 @@ import Data.Binary (Binary, encodeFile, decodeFile) import Hakyll.Core.Identifier import Hakyll.Core.Util.File -import Hakyll.Core.ResourceProvider -- | Data structure used for the store -- @@ -53,21 +51,3 @@ storeGet store name identifier = do else return Nothing where path = makePath store name identifier - --- | Check if a resource was modified --- -wasModified :: Store -> ResourceProvider -> Identifier -> IO Bool -wasModified store provider identifier = do - -- Get the latest seen digest from the store - lastDigest <- storeGet store itemName identifier - -- Calculate the digest for the resource - newDigest <- resourceDigest provider identifier - -- Check digests - if Just newDigest == lastDigest - -- All is fine, not modified - then return False - -- Resource modified; store new digest - else do storeSet store itemName identifier newDigest - return True - where - itemName = "Hakyll.Core.Store.wasModified" -- cgit v1.2.3 From 8bb4ea5c83fb96842f85d2d167e96c4eae09d4ea Mon Sep 17 00:00:00 2001 From: Jasper Van der Jeugt Date: Fri, 31 Dec 2010 13:28:31 +0100 Subject: Add resourceExists function --- src/Hakyll/Core/ResourceProvider.hs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/Hakyll/Core/ResourceProvider.hs') diff --git a/src/Hakyll/Core/ResourceProvider.hs b/src/Hakyll/Core/ResourceProvider.hs index c522ab6..d5f2ea3 100644 --- a/src/Hakyll/Core/ResourceProvider.hs +++ b/src/Hakyll/Core/ResourceProvider.hs @@ -4,6 +4,7 @@ -- module Hakyll.Core.ResourceProvider ( ResourceProvider (..) + , resourceExists , resourceDigest , resourceModified ) where @@ -29,6 +30,11 @@ data ResourceProvider = ResourceProvider resourceLazyByteString :: Identifier -> IO LB.ByteString } +-- | Check if a given resource exists +-- +resourceExists :: ResourceProvider -> Identifier -> Bool +resourceExists provider = flip elem $ resourceList provider + -- | Retrieve a digest for a given resource -- resourceDigest :: ResourceProvider -> Identifier -> IO [Word8] -- cgit v1.2.3 From 2b9858a8f9212219718625b7c5891bcb11cbaefb Mon Sep 17 00:00:00 2001 From: Jasper Van der Jeugt Date: Fri, 11 Feb 2011 17:52:19 +0100 Subject: Add Resource type for improved type-safety --- src/Hakyll/Core/Compiler.hs | 8 ++++---- src/Hakyll/Core/ResourceProvider.hs | 7 ++++++- src/Hakyll/Core/Rules.hs | 6 ++++-- src/Hakyll/Web.hs | 11 ++++++----- src/Hakyll/Web/Page.hs | 3 ++- src/Hakyll/Web/Template.hs | 5 +++-- 6 files changed, 25 insertions(+), 15 deletions(-) (limited to 'src/Hakyll/Core/ResourceProvider.hs') diff --git a/src/Hakyll/Core/Compiler.hs b/src/Hakyll/Core/Compiler.hs index 85b912c..bbb5737 100644 --- a/src/Hakyll/Core/Compiler.hs +++ b/src/Hakyll/Core/Compiler.hs @@ -87,7 +87,7 @@ getRouteFor = fromJob $ \identifier -> CompilerM $ do -- | Get the resource we are compiling as a string -- -getResourceString :: Compiler a String +getResourceString :: Compiler Resource String getResourceString = getIdentifier >>> getResourceString' where getResourceString' = fromJob $ \id' -> CompilerM $ do @@ -165,8 +165,8 @@ requireAllA pattern = (id &&& requireAll_ pattern >>>) cached :: (Binary a, Typeable a, Writable a) => String - -> Compiler () a - -> Compiler () a + -> Compiler Resource a + -> Compiler Resource a cached name (Compiler d j) = Compiler d $ const $ CompilerM $ do identifier <- compilerIdentifier <$> ask store <- compilerStore <$> ask @@ -174,7 +174,7 @@ cached name (Compiler d j) = Compiler d $ const $ CompilerM $ do liftIO $ putStrLn $ show identifier ++ ": " ++ if modified then "MODIFIED" else "OK" if modified - then do v <- unCompilerM $ j () + then do v <- unCompilerM $ j Resource liftIO $ storeSet store name identifier v return v else do v <- liftIO $ storeGet store name identifier diff --git a/src/Hakyll/Core/ResourceProvider.hs b/src/Hakyll/Core/ResourceProvider.hs index d5f2ea3..980f001 100644 --- a/src/Hakyll/Core/ResourceProvider.hs +++ b/src/Hakyll/Core/ResourceProvider.hs @@ -3,7 +3,8 @@ -- the concrete instance. -- module Hakyll.Core.ResourceProvider - ( ResourceProvider (..) + ( Resource (..) + , ResourceProvider (..) , resourceExists , resourceDigest , resourceModified @@ -19,6 +20,10 @@ import OpenSSL.Digest (MessageDigest (MD5)) import Hakyll.Core.Identifier import Hakyll.Core.Store +-- | A resource +-- +data Resource = Resource + -- | A value responsible for retrieving and listing resources -- data ResourceProvider = ResourceProvider diff --git a/src/Hakyll/Core/Rules.hs b/src/Hakyll/Core/Rules.hs index fbdd533..78cbac7 100644 --- a/src/Hakyll/Core/Rules.hs +++ b/src/Hakyll/Core/Rules.hs @@ -39,6 +39,7 @@ import Hakyll.Core.Routes import Hakyll.Core.CompiledItem import Hakyll.Core.Writable import Hakyll.Core.Rules.Internal +import Hakyll.Core.Util.Arrow -- | Add a route -- @@ -62,10 +63,11 @@ tellCompilers compilers = RulesM $ tell $ RuleSet mempty $ -- happen. In this case, you might want to have a look at 'create'. -- compile :: (Binary a, Typeable a, Writable a) - => Pattern -> Compiler () a -> Rules + => Pattern -> Compiler Resource a -> Rules compile pattern compiler = RulesM $ do identifiers <- matches pattern . resourceList <$> ask - unRulesM $ tellCompilers $ zip identifiers (repeat compiler) + unRulesM $ tellCompilers $ zip identifiers $ repeat $ + constA Resource >>> compiler -- | Add a compilation rule -- diff --git a/src/Hakyll/Web.hs b/src/Hakyll/Web.hs index 617e2de..ae86301 100644 --- a/src/Hakyll/Web.hs +++ b/src/Hakyll/Web.hs @@ -19,6 +19,7 @@ import Text.Hamlet (HamletSettings) import Hakyll.Core.Compiler import Hakyll.Core.Writable import Hakyll.Core.Identifier +import Hakyll.Core.ResourceProvider import Hakyll.Web.Page import Hakyll.Web.Pandoc import Hakyll.Web.Template @@ -26,7 +27,7 @@ import Hakyll.Web.RelativizeUrls import Hakyll.Web.Util.String import Hakyll.Web.CompressCss -defaultPageRead :: Compiler () (Page String) +defaultPageRead :: Compiler Resource (Page String) defaultPageRead = cached "Hakyll.Web.defaultPageRead" $ pageRead >>> addDefaultFields >>> arr applySelf >>> pageRenderPandoc @@ -36,17 +37,17 @@ defaultRelativizeUrls = getRoute &&& id >>^ uncurry relativize relativize Nothing = id relativize (Just r) = fmap (relativizeUrls $ toSiteRoot r) -defaultTemplateRead :: Compiler () Template +defaultTemplateRead :: Compiler Resource Template defaultTemplateRead = cached "Hakyll.Web.defaultTemplateRead" $ templateRead -defaultTemplateReadWith :: HamletSettings -> Compiler () Template +defaultTemplateReadWith :: HamletSettings -> Compiler Resource Template defaultTemplateReadWith settings = cached "Hakyll.Web.defaultTemplateReadWith" $ templateReadWith settings -defaultCopyFile :: Compiler () CopyFile +defaultCopyFile :: Compiler Resource CopyFile defaultCopyFile = getIdentifier >>^ CopyFile . toFilePath -defaultCompressCss :: Compiler () String +defaultCompressCss :: Compiler Resource String defaultCompressCss = getResourceString >>^ compressCss defaultApplyTemplate :: Identifier -- ^ Template diff --git a/src/Hakyll/Web/Page.hs b/src/Hakyll/Web/Page.hs index 220ee29..03995cd 100644 --- a/src/Hakyll/Web/Page.hs +++ b/src/Hakyll/Web/Page.hs @@ -68,6 +68,7 @@ import Data.Ord (comparing) import Hakyll.Core.Identifier import Hakyll.Core.Compiler +import Hakyll.Core.ResourceProvider import Hakyll.Web.Page.Internal import Hakyll.Web.Page.Read import Hakyll.Web.Page.Metadata @@ -90,7 +91,7 @@ toMap (Page m b) = M.insert "body" b m -- | Read a page (do not render it) -- -pageRead :: Compiler a (Page String) +pageRead :: Compiler Resource (Page String) pageRead = getResourceString >>^ readPage -- | Add a number of default metadata fields to a page. These fields include: diff --git a/src/Hakyll/Web/Template.hs b/src/Hakyll/Web/Template.hs index 9ea4183..6e6ad67 100644 --- a/src/Hakyll/Web/Template.hs +++ b/src/Hakyll/Web/Template.hs @@ -58,6 +58,7 @@ import Text.Hamlet (HamletSettings, defaultHamletSettings) import Hakyll.Core.Compiler import Hakyll.Core.Identifier +import Hakyll.Core.ResourceProvider import Hakyll.Web.Template.Internal import Hakyll.Web.Template.Read import Hakyll.Web.Page @@ -85,12 +86,12 @@ applySelf page = applyTemplate (readTemplate $ pageBody page) page -- @.hml@ or @.hamlet@, it will be considered as a Hamlet template, and parsed -- as such. -- -templateRead :: Compiler a Template +templateRead :: Compiler Resource Template templateRead = templateReadWith defaultHamletSettings -- | Version of 'templateRead' that enables custom settings. -- -templateReadWith :: HamletSettings -> Compiler a Template +templateReadWith :: HamletSettings -> Compiler Resource Template templateReadWith settings = getIdentifier &&& getResourceString >>^ uncurry read' where -- cgit v1.2.3 From 34257df262521e4031c5e19acad3e9ce060c488b Mon Sep 17 00:00:00 2001 From: Jasper Van der Jeugt Date: Fri, 11 Feb 2011 23:26:54 +0100 Subject: Resource = Identifier with an exists invariant --- src/Hakyll/Core/Compiler.hs | 12 ++++---- src/Hakyll/Core/ResourceProvider.hs | 35 ++++++++++++++-------- .../Core/ResourceProvider/FileResourceProvider.hs | 9 ++++-- src/Hakyll/Core/Rules.hs | 6 ++-- src/Hakyll/Core/Run.hs | 5 ++-- 5 files changed, 40 insertions(+), 27 deletions(-) (limited to 'src/Hakyll/Core/ResourceProvider.hs') diff --git a/src/Hakyll/Core/Compiler.hs b/src/Hakyll/Core/Compiler.hs index bbb5737..056ef32 100644 --- a/src/Hakyll/Core/Compiler.hs +++ b/src/Hakyll/Core/Compiler.hs @@ -88,11 +88,9 @@ getRouteFor = fromJob $ \identifier -> CompilerM $ do -- | Get the resource we are compiling as a string -- getResourceString :: Compiler Resource String -getResourceString = getIdentifier >>> getResourceString' - where - getResourceString' = fromJob $ \id' -> CompilerM $ do - provider <- compilerResourceProvider <$> ask - liftIO $ resourceString provider id' +getResourceString = fromJob $ \resource -> CompilerM $ do + provider <- compilerResourceProvider <$> ask + liftIO $ resourceString provider resource -- | Auxiliary: get a dependency -- @@ -141,7 +139,7 @@ requireAll_ :: (Binary a, Typeable a, Writable a) -> Compiler b [a] requireAll_ pattern = fromDependencies getDeps >>> fromJob requireAll_' where - getDeps = matches pattern . resourceList + getDeps = matches pattern . map unResource . resourceList requireAll_' = const $ CompilerM $ do deps <- getDeps . compilerResourceProvider <$> ask mapM (unCompilerM . getDependency) deps @@ -174,7 +172,7 @@ cached name (Compiler d j) = Compiler d $ const $ CompilerM $ do liftIO $ putStrLn $ show identifier ++ ": " ++ if modified then "MODIFIED" else "OK" if modified - then do v <- unCompilerM $ j Resource + then do v <- unCompilerM $ j $ Resource identifier liftIO $ storeSet store name identifier v return v else do v <- liftIO $ storeGet store name identifier diff --git a/src/Hakyll/Core/ResourceProvider.hs b/src/Hakyll/Core/ResourceProvider.hs index 980f001..dcd4af0 100644 --- a/src/Hakyll/Core/ResourceProvider.hs +++ b/src/Hakyll/Core/ResourceProvider.hs @@ -2,6 +2,14 @@ -- 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. +-- module Hakyll.Core.ResourceProvider ( Resource (..) , ResourceProvider (..) @@ -22,43 +30,46 @@ import Hakyll.Core.Store -- | A resource -- -data Resource = Resource +-- Invariant: the resource specified by the given identifier must exist +-- +newtype Resource = Resource {unResource :: Identifier} + deriving (Eq, Show, Ord) -- | A value responsible for retrieving and listing resources -- data ResourceProvider = ResourceProvider { -- | A list of all resources this provider is able to provide - resourceList :: [Identifier] + resourceList :: [Resource] , -- | Retrieve a certain resource as string - resourceString :: Identifier -> IO String + resourceString :: Resource -> IO String , -- | Retrieve a certain resource as lazy bytestring - resourceLazyByteString :: Identifier -> IO LB.ByteString + resourceLazyByteString :: Resource -> IO LB.ByteString } --- | Check if a given resource exists +-- | Check if a given identifier has a resource -- resourceExists :: ResourceProvider -> Identifier -> Bool -resourceExists provider = flip elem $ resourceList provider +resourceExists provider = flip elem $ map unResource $ resourceList provider -- | Retrieve a digest for a given resource -- -resourceDigest :: ResourceProvider -> Identifier -> IO [Word8] +resourceDigest :: ResourceProvider -> Resource -> IO [Word8] resourceDigest provider = digest MD5 <=< resourceLazyByteString provider -- | Check if a resource was modified -- -resourceModified :: ResourceProvider -> Identifier -> Store -> IO Bool -resourceModified provider identifier store = do +resourceModified :: ResourceProvider -> Resource -> Store -> IO Bool +resourceModified provider resource store = do -- Get the latest seen digest from the store - lastDigest <- storeGet store itemName identifier + lastDigest <- storeGet store itemName $ unResource resource -- Calculate the digest for the resource - newDigest <- resourceDigest provider identifier + newDigest <- resourceDigest provider resource -- Check digests if Just newDigest == lastDigest -- All is fine, not modified then return False -- Resource modified; store new digest - else do storeSet store itemName identifier newDigest + else do storeSet store itemName (unResource resource) newDigest return True where itemName = "Hakyll.Core.ResourceProvider.resourceModified" diff --git a/src/Hakyll/Core/ResourceProvider/FileResourceProvider.hs b/src/Hakyll/Core/ResourceProvider/FileResourceProvider.hs index 7343855..2f040b3 100644 --- a/src/Hakyll/Core/ResourceProvider/FileResourceProvider.hs +++ b/src/Hakyll/Core/ResourceProvider/FileResourceProvider.hs @@ -16,9 +16,12 @@ import Hakyll.Core.Util.File -- fileResourceProvider :: IO ResourceProvider fileResourceProvider = do + -- Retrieve a list of identifiers list <- map parseIdentifier <$> getRecursiveContents False "." + + -- Construct a resource provider return ResourceProvider - { resourceList = list - , resourceString = readFile . toFilePath - , resourceLazyByteString = LB.readFile . toFilePath + { resourceList = map Resource list + , resourceString = readFile . toFilePath . unResource + , resourceLazyByteString = LB.readFile . toFilePath . unResource } diff --git a/src/Hakyll/Core/Rules.hs b/src/Hakyll/Core/Rules.hs index 78cbac7..137dc2c 100644 --- a/src/Hakyll/Core/Rules.hs +++ b/src/Hakyll/Core/Rules.hs @@ -65,9 +65,9 @@ tellCompilers compilers = RulesM $ tell $ RuleSet mempty $ compile :: (Binary a, Typeable a, Writable a) => Pattern -> Compiler Resource a -> Rules compile pattern compiler = RulesM $ do - identifiers <- matches pattern . resourceList <$> ask - unRulesM $ tellCompilers $ zip identifiers $ repeat $ - constA Resource >>> compiler + identifiers <- matches pattern . map unResource . resourceList <$> ask + unRulesM $ tellCompilers $ flip map identifiers $ \identifier -> + (identifier, constA (Resource identifier) >>> compiler) -- | Add a compilation rule -- diff --git a/src/Hakyll/Core/Run.hs b/src/Hakyll/Core/Run.hs index 7e6851f..2b0ff5d 100644 --- a/src/Hakyll/Core/Run.hs +++ b/src/Hakyll/Core/Run.hs @@ -82,8 +82,9 @@ modified :: ResourceProvider -- ^ Resource provider -> [Identifier] -- ^ Identifiers to check -> IO (Set Identifier) -- ^ Modified resources modified provider store ids = fmap S.fromList $ flip filterM ids $ \id' -> - if resourceExists provider id' then resourceModified provider id' store - else return False + if resourceExists provider id' + then resourceModified provider (Resource id') store + else return False -- | Add a number of compilers and continue using these compilers -- -- cgit v1.2.3