on master help sign in
Track metadata dependencies
712ffa3Alexey Kreshchuk
hakyll.cabal+1
@@ -133,6 +133,7 @@ Library
133 Hakyll.Core.Provider.Metadata
133 Hakyll.Core.Provider.Metadata
134 Hakyll.Core.Provider.MetadataCache
134 Hakyll.Core.Provider.MetadataCache
135 Hakyll.Core.Rules.Internal
135 Hakyll.Core.Rules.Internal
136+ Hakyll.Core.Rules.Default
136 Hakyll.Core.Runtime
137 Hakyll.Core.Runtime
137 Hakyll.Core.Store
138 Hakyll.Core.Store
138 Hakyll.Core.Util.File
139 Hakyll.Core.Util.File
src/Hakyll/Core/Metadata.hs+10
@@ -5,6 +5,7 @@ module Hakyll.Core.Metadata
5 , getMetadataField
5 , getMetadataField
6 , getMetadataField'
6 , getMetadataField'
7 , makePatternDependency
7 , makePatternDependency
8+ , metadataFiles
8 ) where
9 ) where
9
10
10
11
@@ -12,6 +13,7 @@ module Hakyll.Core.Metadata
12import Control.Monad (forM)
13import Control.Monad (forM)
13import Data.Map (Map)
14import Data.Map (Map)
14import qualified Data.Map as M
15import qualified Data.Map as M
16+import System.FilePath.Posix ((</>), takeDirectory)
15
17
16
18
17--------------------------------------------------------------------------------
19--------------------------------------------------------------------------------
@@ -61,3 +63,11 @@ makePatternDependency :: MonadMetadata m => Pattern -> m Dependency
61makePatternDependency pattern = do
63makePatternDependency pattern = do
62 matches' <- getMatches pattern
64 matches' <- getMatches pattern
63 return $ PatternDependency pattern matches'
65 return $ PatternDependency pattern matches'
66+
67+--------------------------------------------------------------------------------
68+-- | Returns a list of all directory-wise metadata files, subdir first, global last
69+metadataFiles :: Identifier -> [Identifier]
70+metadataFiles = go . takeDirectory . toFilePath where
71+ go "." = [fromFilePath "metadata"]
72+ go dir = fromFilePath (dir </> "metadata") : go (takeDirectory dir)
73+
src/Hakyll/Core/Provider/Metadata.hs+8−12
@@ -44,7 +44,7 @@ loadMetadata p identifier = do
44 Nothing -> return M.empty
44 Nothing -> return M.empty
45 Just mi' -> loadMetadataFile $ resourceFilePath p mi'
45 Just mi' -> loadMetadataFile $ resourceFilePath p mi'
46
46
47− gmd <- loadGlobalMetadata p $ toFilePath identifier
47+ gmd <- loadGlobalMetadata p identifier
48
48
49 return (M.unions [md, emd, gmd], body)
49 return (M.unions [md, emd, gmd], body)
50 where
50 where
@@ -141,21 +141,17 @@ page = do
141
141
142--------------------------------------------------------------------------------
142--------------------------------------------------------------------------------
143-- | Load directory-wise metadata
143-- | Load directory-wise metadata
144−loadGlobalMetadata :: Provider -> FilePath -> IO (M.Map String String)
144+loadGlobalMetadata :: Provider -> Identifier -> IO Metadata
145−loadGlobalMetadata p fp = liftM M.fromList $ loadgm $ takeDirectory fp where
145+loadGlobalMetadata p fp = liftM M.fromList $ loadgm fp where
146− loadgm :: FilePath -> IO [(String, String)]
146+ loadgm :: Identifier -> IO [(String, String)]
147− loadgm dir | dir == "." = return []
147+ loadgm = liftM concat . mapM loadOne . reverse . filter (resourceExists p) . metadataFiles
148− | otherwise = do
149− let mfp = fromFilePath $ combine dir "metadata"
150− md <- if resourceExists p mfp then loadOne mfp dir else return []
151− others <- loadgm (takeDirectory dir)
152− return $ others ++ md
153− loadOne mfp dir =
148+ loadOne mfp =
154 let path = resourceFilePath p mfp
149 let path = resourceFilePath p mfp
150+ dir = takeDirectory $ toFilePath mfp
155 -- TODO: It might be better to print warning and continue
151 -- TODO: It might be better to print warning and continue
156 in either (error.show) (findMetadata dir) . P.parse namedMetadata path <$> readFile path
152 in either (error.show) (findMetadata dir) . P.parse namedMetadata path <$> readFile path
157 findMetadata dir =
153 findMetadata dir =
158− concatMap snd . filter (flip matches (fromFilePath fp) . fromGlob . combine dir . fst)
154+ concatMap snd . filter (flip matches fp . fromGlob . combine dir . fst)
159
155
160namedMetadata :: Parser [(String, [(String, String)])]
156namedMetadata :: Parser [(String, [(String, String)])]
161namedMetadata = P.many namedMetadataBlock
157namedMetadata = P.many namedMetadataBlock
src/Hakyll/Core/Rules/Default.hsnew file+23
@@ -0,0 +1,23 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+module Hakyll.Core.Rules.Default
3+ ( internalRules
4+ , addMetadataDependencies
5+ )
6+where
7+import Hakyll.Core.Rules
8+import Hakyll.Core.Compiler
9+import Hakyll.Core.Compiler.Internal (compilerTellDependencies)
10+import Hakyll.Core.Metadata (getMatches, metadataFiles)
11+import Hakyll.Core.Identifier.Pattern(fromList)
12+
13+internalRules :: Rules ()
14+internalRules = do
15+ match "metadata" $ compile $ makeItem ()
16+ match "**/metadata" $ compile $ makeItem ()
17+
18+--------------------------------------------------------------------------------
19+addMetadataDependencies :: Compiler ()
20+addMetadataDependencies =
21+ compilerTellDependencies . map IdentifierDependency =<< getMatches . fromList =<< fmap metadataFiles getUnderlying
22+
23+
src/Hakyll/Core/Runtime.hs+3−2
@@ -35,6 +35,7 @@ import qualified Hakyll.Core.Logger as Logger
35import Hakyll.Core.Provider
35import Hakyll.Core.Provider
36import Hakyll.Core.Routes
36import Hakyll.Core.Routes
37import Hakyll.Core.Rules.Internal
37import Hakyll.Core.Rules.Internal
38+import Hakyll.Core.Rules.Default
38import Hakyll.Core.Store (Store)
39import Hakyll.Core.Store (Store)
39import qualified Hakyll.Core.Store as Store
40import qualified Hakyll.Core.Store as Store
40import Hakyll.Core.Util.File
41import Hakyll.Core.Util.File
@@ -53,7 +54,7 @@ run config verbosity rules = do
53 provider <- newProvider store (shouldIgnoreFile config) $
54 provider <- newProvider store (shouldIgnoreFile config) $
54 providerDirectory config
55 providerDirectory config
55 Logger.message logger "Running rules..."
56 Logger.message logger "Running rules..."
56− ruleSet <- runRules rules provider
57+ ruleSet <- runRules (internalRules >> rules) provider
57
58
58 -- Get old facts
59 -- Get old facts
59 mOldFacts <- Store.get store factsKey
60 mOldFacts <- Store.get store factsKey
@@ -186,7 +187,7 @@ chase trail id'
186 config <- runtimeConfiguration <$> ask
187 config <- runtimeConfiguration <$> ask
187 Logger.debug logger $ "Processing " ++ show id'
188 Logger.debug logger $ "Processing " ++ show id'
188
189
189− let compiler = todo M.! id'
190+ let compiler = addMetadataDependencies >> todo M.! id'
190 read' = CompilerRead
191 read' = CompilerRead
191 { compilerConfig = config
192 { compilerConfig = config
192 , compilerUnderlying = id'
193 , compilerUnderlying = id'