From 712ffa39b5857fdc5cdae1db38a177267a430b11 Mon Sep 17 00:00:00 2001 From: Alexey Kreshchuk Date: Wed, 16 Oct 2013 01:39:04 +0400 Subject: Track metadata dependencies I had to prepend some Rules to global Rules set. This might be possible to replaced by a correct Store.set call. I also had to prepend some Compile rules. --- src/Hakyll/Core/Metadata.hs | 10 ++++++++++ src/Hakyll/Core/Provider/Metadata.hs | 20 ++++++++------------ src/Hakyll/Core/Rules/Default.hs | 23 +++++++++++++++++++++++ src/Hakyll/Core/Runtime.hs | 5 +++-- 4 files changed, 44 insertions(+), 14 deletions(-) create mode 100644 src/Hakyll/Core/Rules/Default.hs (limited to 'src/Hakyll') diff --git a/src/Hakyll/Core/Metadata.hs b/src/Hakyll/Core/Metadata.hs index 7902b94..a330636 100644 --- a/src/Hakyll/Core/Metadata.hs +++ b/src/Hakyll/Core/Metadata.hs @@ -5,6 +5,7 @@ module Hakyll.Core.Metadata , getMetadataField , getMetadataField' , makePatternDependency + , metadataFiles ) where @@ -12,6 +13,7 @@ module Hakyll.Core.Metadata import Control.Monad (forM) import Data.Map (Map) import qualified Data.Map as M +import System.FilePath.Posix ((), takeDirectory) -------------------------------------------------------------------------------- @@ -61,3 +63,11 @@ makePatternDependency :: MonadMetadata m => Pattern -> m Dependency makePatternDependency pattern = do matches' <- getMatches pattern return $ PatternDependency pattern matches' + +-------------------------------------------------------------------------------- +-- | Returns a list of all directory-wise metadata files, subdir first, global last +metadataFiles :: Identifier -> [Identifier] +metadataFiles = go . takeDirectory . toFilePath where + go "." = [fromFilePath "metadata"] + go dir = fromFilePath (dir "metadata") : go (takeDirectory dir) + diff --git a/src/Hakyll/Core/Provider/Metadata.hs b/src/Hakyll/Core/Provider/Metadata.hs index 8f39f22..4331861 100644 --- a/src/Hakyll/Core/Provider/Metadata.hs +++ b/src/Hakyll/Core/Provider/Metadata.hs @@ -44,7 +44,7 @@ loadMetadata p identifier = do Nothing -> return M.empty Just mi' -> loadMetadataFile $ resourceFilePath p mi' - gmd <- loadGlobalMetadata p $ toFilePath identifier + gmd <- loadGlobalMetadata p identifier return (M.unions [md, emd, gmd], body) where @@ -141,21 +141,17 @@ page = do -------------------------------------------------------------------------------- -- | Load directory-wise metadata -loadGlobalMetadata :: Provider -> FilePath -> IO (M.Map String String) -loadGlobalMetadata p fp = liftM M.fromList $ loadgm $ takeDirectory fp where - loadgm :: FilePath -> IO [(String, String)] - loadgm dir | dir == "." = return [] - | otherwise = do - let mfp = fromFilePath $ combine dir "metadata" - md <- if resourceExists p mfp then loadOne mfp dir else return [] - others <- loadgm (takeDirectory dir) - return $ others ++ md - loadOne mfp dir = +loadGlobalMetadata :: Provider -> Identifier -> IO Metadata +loadGlobalMetadata p fp = liftM M.fromList $ loadgm fp where + loadgm :: Identifier -> IO [(String, String)] + loadgm = liftM concat . mapM loadOne . reverse . filter (resourceExists p) . metadataFiles + loadOne mfp = let path = resourceFilePath p mfp + dir = takeDirectory $ toFilePath mfp -- TODO: It might be better to print warning and continue in either (error.show) (findMetadata dir) . P.parse namedMetadata path <$> readFile path findMetadata dir = - concatMap snd . filter (flip matches (fromFilePath fp) . fromGlob . combine dir . fst) + concatMap snd . filter (flip matches fp . fromGlob . combine dir . fst) namedMetadata :: Parser [(String, [(String, String)])] namedMetadata = P.many namedMetadataBlock diff --git a/src/Hakyll/Core/Rules/Default.hs b/src/Hakyll/Core/Rules/Default.hs new file mode 100644 index 0000000..ccca1bd --- /dev/null +++ b/src/Hakyll/Core/Rules/Default.hs @@ -0,0 +1,23 @@ +{-# LANGUAGE OverloadedStrings #-} +module Hakyll.Core.Rules.Default + ( internalRules + , addMetadataDependencies + ) +where +import Hakyll.Core.Rules +import Hakyll.Core.Compiler +import Hakyll.Core.Compiler.Internal (compilerTellDependencies) +import Hakyll.Core.Metadata (getMatches, metadataFiles) +import Hakyll.Core.Identifier.Pattern(fromList) + +internalRules :: Rules () +internalRules = do + match "metadata" $ compile $ makeItem () + match "**/metadata" $ compile $ makeItem () + +-------------------------------------------------------------------------------- +addMetadataDependencies :: Compiler () +addMetadataDependencies = + compilerTellDependencies . map IdentifierDependency =<< getMatches . fromList =<< fmap metadataFiles getUnderlying + + diff --git a/src/Hakyll/Core/Runtime.hs b/src/Hakyll/Core/Runtime.hs index 824d11b..4ef30df 100644 --- a/src/Hakyll/Core/Runtime.hs +++ b/src/Hakyll/Core/Runtime.hs @@ -35,6 +35,7 @@ import qualified Hakyll.Core.Logger as Logger import Hakyll.Core.Provider import Hakyll.Core.Routes import Hakyll.Core.Rules.Internal +import Hakyll.Core.Rules.Default import Hakyll.Core.Store (Store) import qualified Hakyll.Core.Store as Store import Hakyll.Core.Util.File @@ -53,7 +54,7 @@ run config verbosity rules = do provider <- newProvider store (shouldIgnoreFile config) $ providerDirectory config Logger.message logger "Running rules..." - ruleSet <- runRules rules provider + ruleSet <- runRules (internalRules >> rules) provider -- Get old facts mOldFacts <- Store.get store factsKey @@ -186,7 +187,7 @@ chase trail id' config <- runtimeConfiguration <$> ask Logger.debug logger $ "Processing " ++ show id' - let compiler = todo M.! id' + let compiler = addMetadataDependencies >> todo M.! id' read' = CompilerRead { compilerConfig = config , compilerUnderlying = id' -- cgit v1.2.3