2012-11-08 11:45:26 +00:00
|
|
|
--------------------------------------------------------------------------------
|
2012-11-19 14:52:51 +00:00
|
|
|
{-# LANGUAGE CPP #-}
|
2012-11-18 20:56:52 +00:00
|
|
|
module Hakyll.Core.Provider.Modified
|
2012-11-08 11:45:26 +00:00
|
|
|
( resourceModified
|
|
|
|
, resourceModificationTime
|
|
|
|
) where
|
|
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
2012-11-18 20:56:52 +00:00
|
|
|
import Control.Applicative ((<$>), (<*>))
|
|
|
|
import Control.Monad (when)
|
|
|
|
import qualified Crypto.Hash.MD5 as MD5
|
|
|
|
import qualified Data.ByteString as B
|
|
|
|
import qualified Data.ByteString.Lazy as BL
|
2012-11-08 11:45:26 +00:00
|
|
|
import Data.IORef
|
2012-11-18 20:56:52 +00:00
|
|
|
import qualified Data.Map as M
|
|
|
|
import Data.Time (UTCTime)
|
|
|
|
import System.Directory (getModificationTime)
|
2012-11-19 14:52:51 +00:00
|
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
#if !MIN_VERSION_directory(1,2,0)
|
|
|
|
import Data.Time (readTime)
|
|
|
|
import System.Locale (defaultTimeLocale)
|
|
|
|
import System.Time (formatCalendarTime,
|
|
|
|
toCalendarTime)
|
|
|
|
#endif
|
2012-11-08 11:45:26 +00:00
|
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
2012-11-09 15:34:45 +00:00
|
|
|
import Hakyll.Core.Identifier
|
2012-11-18 20:56:52 +00:00
|
|
|
import Hakyll.Core.Provider.Internal
|
|
|
|
import Hakyll.Core.Provider.MetadataCache
|
|
|
|
import Hakyll.Core.Store (Store)
|
|
|
|
import qualified Hakyll.Core.Store as Store
|
2012-11-08 11:45:26 +00:00
|
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
-- | A resource is modified if it or its metadata has changed
|
2012-11-18 20:56:52 +00:00
|
|
|
resourceModified :: Provider -> Identifier -> IO Bool
|
2012-11-19 13:59:55 +00:00
|
|
|
resourceModified p r
|
2012-11-08 11:45:26 +00:00
|
|
|
| not exists = return False
|
|
|
|
| otherwise = do
|
|
|
|
cache <- readIORef cacheRef
|
2012-11-09 15:34:45 +00:00
|
|
|
case M.lookup normalized cache of
|
2012-11-08 11:45:26 +00:00
|
|
|
Just m -> return m
|
|
|
|
Nothing -> do
|
|
|
|
-- Check if the actual file was modified, and do a recursive
|
|
|
|
-- call to check if the metadata file was modified
|
|
|
|
m <- (||)
|
2012-11-19 13:59:55 +00:00
|
|
|
<$> fileDigestModified store filePath
|
|
|
|
<*> resourceModified p (resourceMetadataResource r)
|
2012-11-09 15:34:45 +00:00
|
|
|
modifyIORef cacheRef (M.insert normalized m)
|
2012-11-08 11:45:26 +00:00
|
|
|
|
2012-11-08 12:50:08 +00:00
|
|
|
-- Important! (But ugly)
|
2012-11-19 13:59:55 +00:00
|
|
|
when m $ resourceInvalidateMetadataCache p r
|
2012-11-08 11:45:26 +00:00
|
|
|
|
|
|
|
return m
|
|
|
|
where
|
2012-11-13 12:13:17 +00:00
|
|
|
normalized = setVersion Nothing r
|
2012-11-19 13:59:55 +00:00
|
|
|
exists = resourceExists p r
|
|
|
|
store = providerStore p
|
|
|
|
cacheRef = providerModifiedCache p
|
|
|
|
filePath = resourceFilePath p r
|
2012-11-08 11:45:26 +00:00
|
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
-- | Utility: Check if a the digest of a file was modified
|
|
|
|
fileDigestModified :: Store -> FilePath -> IO Bool
|
|
|
|
fileDigestModified store fp = do
|
|
|
|
-- Get the latest seen digest from the store, and calculate the current
|
|
|
|
-- digest for the
|
|
|
|
lastDigest <- Store.get store key
|
|
|
|
newDigest <- fileDigest fp
|
|
|
|
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.Resource.Provider.fileModified", fp]
|
|
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
-- | Utility: Retrieve a digest for a given file
|
|
|
|
fileDigest :: FilePath -> IO B.ByteString
|
|
|
|
fileDigest = fmap MD5.hashlazy . BL.readFile
|
|
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
2012-11-19 13:59:55 +00:00
|
|
|
resourceModificationTime :: Provider -> Identifier -> IO UTCTime
|
2012-11-19 14:52:51 +00:00
|
|
|
resourceModificationTime p i = do
|
|
|
|
#if MIN_VERSION_directory(1,2,0)
|
|
|
|
getModificationTime $ resourceFilePath p i
|
|
|
|
#else
|
|
|
|
ct <- toCalendarTime =<< getModificationTime (resourceFilePath p i)
|
|
|
|
let str = formatCalendarTime defaultTimeLocale "%s" ct
|
|
|
|
return $ readTime defaultTimeLocale "%s" str
|
|
|
|
#endif
|