From 73cc078174a567a059916632c07ae64692e37d5f Mon Sep 17 00:00:00 2001 From: Bergi Date: Sat, 17 Mar 2018 16:26:22 +0100 Subject: [PATCH] Do not consider .metadata files to be separate resources but allow resources without a "body", consisting only of their metadata file (Even if that sounds a bit crazy) --- lib/Hakyll/Core/Provider/Internal.hs | 30 +++++++++++------------ lib/Hakyll/Core/Provider/Metadata.hs | 3 ++- lib/Hakyll/Core/Provider/MetadataCache.hs | 4 ++- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/lib/Hakyll/Core/Provider/Internal.hs b/lib/Hakyll/Core/Provider/Internal.hs index c298653af..a3f78fa7e 100644 --- a/lib/Hakyll/Core/Provider/Internal.hs +++ b/lib/Hakyll/Core/Provider/Internal.hs @@ -22,6 +22,7 @@ module Hakyll.Core.Provider.Internal -------------------------------------------------------------------------------- import Control.DeepSeq (NFData (..), deepseq) import Control.Monad (forM) +import Control.Applicative ((<|>)) import Data.Binary (Binary (..)) import qualified Data.ByteString.Lazy as BL import Data.Map (Map) @@ -32,7 +33,7 @@ import qualified Data.Set as S import Data.Time (Day (..), UTCTime (..)) import Data.Typeable (Typeable) import System.Directory (getModificationTime) -import System.FilePath (addExtension, ()) +import System.FilePath (stripExtension, ()) -------------------------------------------------------------------------------- @@ -106,10 +107,7 @@ newProvider :: Store -- ^ Store to use -> IO Provider -- ^ Resulting provider newProvider store ignore directory = do list <- map fromFilePath <$> getRecursiveContents ignore directory - let universe = S.fromList list - files <- fmap (maxmtime . M.fromList) $ forM list $ \identifier -> do - rInfo <- getResourceInfo directory universe identifier - return (identifier, rInfo) + files <- M.fromListWith combine <$> mapM (getResourceInfo directory) list -- Get the old files from the store, and then immediately replace them by -- the new files. @@ -120,20 +118,20 @@ newProvider store ignore directory = do where oldKey = ["Hakyll.Core.Provider.Internal.newProvider", "oldFiles"] - -- Update modified if metadata is modified - maxmtime files = flip M.map files $ \rInfo@(ResourceInfo mtime meta) -> - let metaMod = fmap resourceInfoModified $ meta >>= flip M.lookup files - in rInfo {resourceInfoModified = maybe mtime (max mtime) metaMod} + -- Combine a resource with its metadata file + combine (ResourceInfo xTime xMeta) (ResourceInfo yTime yMeta) = + ResourceInfo (xTime `max` yTime) (xMeta <|> yMeta) -------------------------------------------------------------------------------- -getResourceInfo :: FilePath -> Set Identifier -> Identifier -> IO ResourceInfo -getResourceInfo directory universe identifier = do - mtime <- fileModificationTime $ directory toFilePath identifier - return $ ResourceInfo (BinaryTime mtime) $ - if mdRsc `S.member` universe then Just mdRsc else Nothing - where - mdRsc = fromFilePath $ flip addExtension "metadata" $ toFilePath identifier +getResourceInfo :: FilePath -> Identifier -> IO (Identifier, ResourceInfo) +getResourceInfo directory identifier = do + let file = toFilePath identifier + mtime <- fileModificationTime $ directory file + let makeInfo m = ResourceInfo (BinaryTime mtime) m + return $ case stripExtension "metadata" file of + Nothing -> (identifier, makeInfo Nothing) + Just r -> (fromFilePath r, makeInfo (Just identifier)) -------------------------------------------------------------------------------- diff --git a/lib/Hakyll/Core/Provider/Metadata.hs b/lib/Hakyll/Core/Provider/Metadata.hs index 6285ce17b..c7da31828 100644 --- a/lib/Hakyll/Core/Provider/Metadata.hs +++ b/lib/Hakyll/Core/Provider/Metadata.hs @@ -27,12 +27,13 @@ import Hakyll.Core.Identifier import Hakyll.Core.Metadata import Hakyll.Core.Provider.Internal import System.IO as IO +import System.IO.Error (catchIOError) -------------------------------------------------------------------------------- loadMetadata :: Provider -> Identifier -> IO (Metadata, Maybe String) loadMetadata p identifier = do - hasHeader <- probablyHasMetadataHeader fp + hasHeader <- probablyHasMetadataHeader fp `catchIOError` \_ -> return False (md, body) <- if hasHeader then second Just <$> loadMetadataHeader fp else return (mempty, Nothing) diff --git a/lib/Hakyll/Core/Provider/MetadataCache.hs b/lib/Hakyll/Core/Provider/MetadataCache.hs index 46dbf3ed1..02f7cac35 100644 --- a/lib/Hakyll/Core/Provider/MetadataCache.hs +++ b/lib/Hakyll/Core/Provider/MetadataCache.hs @@ -18,7 +18,9 @@ import qualified Hakyll.Core.Store as Store -------------------------------------------------------------------------------- resourceMetadata :: Provider -> Identifier -> IO Metadata resourceMetadata p r - | not (resourceExists p r) = return mempty + | not (resourceExists p r) = fail $ unwords [ + "Hakyll.Core.Provider.MetadataCache.resourceMetadata:", + "cannot read metadata,", show r, "does not exist"] | otherwise = do -- TODO keep time in md cache load p r