on 877cb21 help sign in
83 lines 3.3 kB history raw
1--------------------------------------------------------------------------------
2module Hakyll.Core.Provider.Modified
3 ( resourceModified
4 , resourceModificationTime
5 ) where
8--------------------------------------------------------------------------------
9import Control.Applicative ((<$>), (<*>))
10import Control.Monad (when)
11import qualified Crypto.Hash.MD5 as MD5
12import qualified Data.ByteString as B
13import qualified Data.ByteString.Lazy as BL
14import Data.IORef
15import qualified Data.Map as M
16import Data.Time (UTCTime)
17import System.Directory (getModificationTime)
20--------------------------------------------------------------------------------
21import Hakyll.Core.Identifier
22import Hakyll.Core.Provider.Internal
23import Hakyll.Core.Provider.MetadataCache
24import Hakyll.Core.Store (Store)
25import qualified Hakyll.Core.Store as Store
28--------------------------------------------------------------------------------
29-- | A resource is modified if it or its metadata has changed
30resourceModified :: Provider -> Identifier -> IO Bool
31resourceModified rp r
32 | not exists = return False
33 | otherwise = do
34 cache <- readIORef cacheRef
35 case M.lookup normalized cache of
36 Just m -> return m
37 Nothing -> do
38 -- Check if the actual file was modified, and do a recursive
39 -- call to check if the metadata file was modified
40 m <- (||)
41 <$> fileDigestModified store (toFilePath r)
42 <*> resourceModified rp (resourceMetadataResource r)
43 modifyIORef cacheRef (M.insert normalized m)
45 -- Important! (But ugly)
46 when m $ resourceInvalidateMetadataCache rp r
48 return m
49 where
50 normalized = setVersion Nothing r
51 exists = resourceExists rp r
52 store = providerStore rp
53 cacheRef = providerModifiedCache rp
56--------------------------------------------------------------------------------
57-- | Utility: Check if a the digest of a file was modified
58fileDigestModified :: Store -> FilePath -> IO Bool
59fileDigestModified store fp = do
60 -- Get the latest seen digest from the store, and calculate the current
61 -- digest for the
62 lastDigest <- Store.get store key
63 newDigest <- fileDigest fp
64 if Store.Found newDigest == lastDigest
65 -- All is fine, not modified
66 then return False
67 -- Resource modified; store new digest
68 else do
69 Store.set store key newDigest
70 return True
71 where
72 key = ["Hakyll.Core.Resource.Provider.fileModified", fp]
75--------------------------------------------------------------------------------
76-- | Utility: Retrieve a digest for a given file
77fileDigest :: FilePath -> IO B.ByteString
78fileDigest = fmap MD5.hashlazy . BL.readFile
81--------------------------------------------------------------------------------
82resourceModificationTime :: Identifier -> IO UTCTime
83resourceModificationTime = getModificationTime . toFilePath