on master help sign in
Prototype of the 'cached' arrow transformer
5b67f20Jasper Van der Jeugt
src/Hakyll/Core/Compiler.hs+23
@@ -8,6 +8,7 @@ module Hakyll.Core.Compiler
8 , getResourceString
8 , getResourceString
9 , require
9 , require
10 , requireAll
10 , requireAll
11+ , cached
11 ) where
12 ) where
12
13
13import Prelude hiding ((.), id)
14import Prelude hiding ((.), id)
@@ -26,6 +27,7 @@ import Hakyll.Core.CompiledItem
26import Hakyll.Core.Writable
27import Hakyll.Core.Writable
27import Hakyll.Core.ResourceProvider
28import Hakyll.Core.ResourceProvider
28import Hakyll.Core.Compiler.Internal
29import Hakyll.Core.Compiler.Internal
30+import Hakyll.Core.Store
29
31
30-- | Get the identifier of the item that is currently being compiled
32-- | Get the identifier of the item that is currently being compiled
31--
33--
@@ -75,3 +77,24 @@ requireAll pattern f =
75 deps <- getDeps . compilerResourceProvider <$> ask
77 deps <- getDeps . compilerResourceProvider <$> ask
76 lookup' <- compilerDependencyLookup <$> ask
78 lookup' <- compilerDependencyLookup <$> ask
77 return $ f x $ map (unCompiledItem . lookup') deps
79 return $ f x $ map (unCompiledItem . lookup') deps
80+
81+cached :: (Binary a)
82+ => String
83+ -> Compiler () a
84+ -> Compiler () a
85+cached name (Compiler d j) = Compiler d $ const $ CompilerM $ do
86+ provider <- compilerResourceProvider <$> ask
87+ identifier <- compilerIdentifier <$> ask
88+ store <- compilerStore <$> ask
89+ modified <- liftIO $ resourceModified provider identifier store
90+ liftIO $ putStrLn $
91+ show identifier ++ ": " ++ if modified then "MODIFIED" else "OK"
92+ if modified
93+ then do v <- unCompilerM $ j ()
94+ liftIO $ storeSet store name identifier v
95+ return v
96+ else do v <- liftIO $ storeGet store name identifier
97+ case v of Just v' -> return v'
98+ Nothing -> error'
99+ where
100+ error' = error "Hakyll.Core.Compiler.cached: Cache corrupt!"
src/Hakyll/Core/Compiler/Internal.hs+5−1
@@ -24,6 +24,7 @@ import Control.Arrow (Arrow, arr, first)
24import Hakyll.Core.Identifier
24import Hakyll.Core.Identifier
25import Hakyll.Core.CompiledItem
25import Hakyll.Core.CompiledItem
26import Hakyll.Core.ResourceProvider
26import Hakyll.Core.ResourceProvider
27+import Hakyll.Core.Store
27
28
28-- | A set of dependencies
29-- | A set of dependencies
29--
30--
@@ -40,6 +41,7 @@ data CompilerEnvironment = CompilerEnvironment
40 , compilerResourceProvider :: ResourceProvider -- ^ Resource provider
41 , compilerResourceProvider :: ResourceProvider -- ^ Resource provider
41 , compilerDependencyLookup :: DependencyLookup -- ^ Dependency lookup
42 , compilerDependencyLookup :: DependencyLookup -- ^ Dependency lookup
42 , compilerRoute :: Maybe FilePath -- ^ Site route
43 , compilerRoute :: Maybe FilePath -- ^ Site route
44+ , compilerStore :: Store -- ^ Compiler store
43 }
45 }
44
46
45-- | The compiler monad
47-- | The compiler monad
@@ -73,8 +75,9 @@ runCompilerJob :: Compiler () a -- ^ Compiler to run
73 -> ResourceProvider -- ^ Resource provider
75 -> ResourceProvider -- ^ Resource provider
74 -> DependencyLookup -- ^ Dependency lookup table
76 -> DependencyLookup -- ^ Dependency lookup table
75 -> Maybe FilePath -- ^ Route
77 -> Maybe FilePath -- ^ Route
78+ -> Store -- ^ Store
76 -> IO a
79 -> IO a
77−runCompilerJob compiler identifier provider lookup' route =
80+runCompilerJob compiler identifier provider lookup' route store =
78 runReaderT (unCompilerM $ compilerJob compiler ()) env
81 runReaderT (unCompilerM $ compilerJob compiler ()) env
79 where
82 where
80 env = CompilerEnvironment
83 env = CompilerEnvironment
@@ -82,6 +85,7 @@ runCompilerJob compiler identifier provider lookup' route =
82 , compilerResourceProvider = provider
85 , compilerResourceProvider = provider
83 , compilerDependencyLookup = lookup'
86 , compilerDependencyLookup = lookup'
84 , compilerRoute = route
87 , compilerRoute = route
88+ , compilerStore = store
85 }
89 }
86
90
87runCompilerDependencies :: Compiler () a
91runCompilerDependencies :: Compiler () a
src/Hakyll/Core/ResourceProvider.hs+20
@@ -5,6 +5,7 @@
5module Hakyll.Core.ResourceProvider
5module Hakyll.Core.ResourceProvider
6 ( ResourceProvider (..)
6 ( ResourceProvider (..)
7 , resourceDigest
7 , resourceDigest
8+ , resourceModified
8 ) where
9 ) where
9
10
10import Control.Monad ((<=<))
11import Control.Monad ((<=<))
@@ -15,6 +16,7 @@ import OpenSSL.Digest.ByteString.Lazy (digest)
15import OpenSSL.Digest (MessageDigest (MD5))
16import OpenSSL.Digest (MessageDigest (MD5))
16
17
17import Hakyll.Core.Identifier
18import Hakyll.Core.Identifier
19+import Hakyll.Core.Store
18
20
19-- | A value responsible for retrieving and listing resources
21-- | A value responsible for retrieving and listing resources
20--
22--
@@ -31,3 +33,21 @@ data ResourceProvider = ResourceProvider
31--
33--
32resourceDigest :: ResourceProvider -> Identifier -> IO [Word8]
34resourceDigest :: ResourceProvider -> Identifier -> IO [Word8]
33resourceDigest provider = digest MD5 <=< resourceLazyByteString provider
35resourceDigest provider = digest MD5 <=< resourceLazyByteString provider
36+
37+-- | Check if a resource was modified
38+--
39+resourceModified :: ResourceProvider -> Identifier -> Store -> IO Bool
40+resourceModified provider identifier store = do
41+ -- Get the latest seen digest from the store
42+ lastDigest <- storeGet store itemName identifier
43+ -- Calculate the digest for the resource
44+ newDigest <- resourceDigest provider identifier
45+ -- Check digests
46+ if Just newDigest == lastDigest
47+ -- All is fine, not modified
48+ then return False
49+ -- Resource modified; store new digest
50+ else do storeSet store itemName identifier newDigest
51+ return True
52+ where
53+ itemName = "Hakyll.Core.ResourceProvider.resourceModified"
src/Hakyll/Core/Run.hs+2−1
@@ -67,7 +67,8 @@ hakyllWith rules provider store = do
67 where
67 where
68 addTarget route' map' (id', comp) = do
68 addTarget route' map' (id', comp) = do
69 let url = runRoute route' id'
69 let url = runRoute route' id'
70− compiled <- runCompilerJob comp id' provider (dependencyLookup map') url
70+ compiled <- runCompilerJob comp id' provider (dependencyLookup map')
71+ url store
71 putStrLn $ "Generated target: " ++ show id'
72 putStrLn $ "Generated target: " ++ show id'
72
73
73 case url of
74 case url of
src/Hakyll/Core/Store.hs−20
@@ -5,7 +5,6 @@ module Hakyll.Core.Store
5 , makeStore
5 , makeStore
6 , storeSet
6 , storeSet
7 , storeGet
7 , storeGet
8− , wasModified
9 ) where
8 ) where
10
9
11import Control.Applicative ((<$>))
10import Control.Applicative ((<$>))
@@ -16,7 +15,6 @@ import Data.Binary (Binary, encodeFile, decodeFile)
16
15
17import Hakyll.Core.Identifier
16import Hakyll.Core.Identifier
18import Hakyll.Core.Util.File
17import Hakyll.Core.Util.File
19−import Hakyll.Core.ResourceProvider
20
18
21-- | Data structure used for the store
19-- | Data structure used for the store
22--
20--
@@ -53,21 +51,3 @@ storeGet store name identifier = do
53 else return Nothing
51 else return Nothing
54 where
52 where
55 path = makePath store name identifier
53 path = makePath store name identifier
56−
57−-- | Check if a resource was modified
58−--
59−wasModified :: Store -> ResourceProvider -> Identifier -> IO Bool
60−wasModified store provider identifier = do
61− -- Get the latest seen digest from the store
62− lastDigest <- storeGet store itemName identifier
63− -- Calculate the digest for the resource
64− newDigest <- resourceDigest provider identifier
65− -- Check digests
66− if Just newDigest == lastDigest
67− -- All is fine, not modified
68− then return False
69− -- Resource modified; store new digest
70− else do storeSet store itemName identifier newDigest
71− return True
72− where
73− itemName = "Hakyll.Core.Store.wasModified"