@@ -3,13 +3,16 @@
33module Hakyll.Core.Run where
44
55import Control.Arrow ((&&&))
6−import Control.Monad (foldM, forM_, forM)
6+import Control.Monad (foldM, forM_, forM, filterM)
7+import Data.Map (Map)
78import qualified Data.Map as M
89import Data.Monoid (mempty)
910import Data.Typeable (Typeable)
1011import Data.Binary (Binary)
1112import System.FilePath ((</>))
1213import Control.Applicative ((<$>))
14+import Data.Set (Set)
15+import qualified Data.Set as S
1316
1417import Hakyll.Core.Route
1518import Hakyll.Core.Identifier
@@ -22,6 +25,7 @@ import Hakyll.Core.Rules
2225import Hakyll.Core.DirectedGraph
2326import Hakyll.Core.DirectedGraph.Dot
2427import Hakyll.Core.DirectedGraph.DependencySolver
28+import Hakyll.Core.DirectedGraph.ObsoleteFilter
2529import Hakyll.Core.Writable
2630import Hakyll.Core.Store
2731import Hakyll.Core.CompiledItem
@@ -48,9 +52,23 @@ hakyllWith rules provider store = do
4852 -- Create a compiler map
4953 compilerMap = M.fromList compilers
5054
51− -- Create and solve the graph, creating a compiler order
55+ -- Create the graph
5256 graph = fromList dependencies
53− ordered = solveDependencies graph
57+
58+ putStrLn "Writing dependency graph to dependencies.dot..."
59+ writeDot "dependencies.dot" show graph
60+
61+ -- Check which items are up-to-date
62+ modified' <- modified provider store $ map fst compilers
63+
64+ let -- Try to reduce the graph
65+ reducedGraph = filterObsolete modified' graph
66+
67+ putStrLn "Writing reduced graph to reduced.dot..."
68+ writeDot "reduced.dot" show reducedGraph
69+
70+ let -- Solve the graph
71+ ordered = solveDependencies reducedGraph
5472
5573 -- Join the order with the compilers again
5674 orderedCompilers = map (id &&& (compilerMap M.!)) ordered
@@ -58,30 +76,23 @@ hakyllWith rules provider store = do
5876 -- Fetch the routes
5977 route' = rulesRoute ruleSet
6078
61− putStrLn "Writing dependency graph to dependencies.dot..."
62− writeDot "dependencies.dot" show graph
63−
64− -- Check which items are up-to-date: modified will be a Map Identifier Bool
65− modifiedMap <- fmap M.fromList $ forM orderedCompilers $ \(id', _) -> do
66− modified <- if resourceExists provider id'
67− then resourceModified provider id' store
68− else return False
69− return (id', modified)
79+ putStrLn $ show reducedGraph
80+ putStrLn $ show ordered
7081
7182 -- Generate all the targets in order
72− _ <- foldM (addTarget route' modifiedMap) M.empty orderedCompilers
83+ _ <- foldM (addTarget route' modified') M.empty orderedCompilers
7384
7485 putStrLn "DONE."
7586 where
76− addTarget route' modifiedMap map' (id', comp) = do
87+ addTarget route' modified' map' (id', comp) = do
7788 let url = runRoute route' id'
7889
7990 -- Check if the resource was modified
80− let modified = modifiedMap M.! id'
91+ let isModified = id' `S.member` modified'
8192
8293 -- Run the compiler
8394 compiled <- runCompilerJob comp id' provider (dependencyLookup map')
84− url store modified
95+ url store isModified
8596 putStrLn $ "Generated target: " ++ show id'
8697
8798 case url of
@@ -92,9 +103,18 @@ hakyllWith rules provider store = do
92103 makeDirectories path
93104 write path compiled
94105
106+ -- Store it in the cache
107+ storeResult store id' compiled
108+
95109 putStrLn ""
96110 return $ M.insert id' compiled map'
97111
98− dependencyLookup map' id' = case M.lookup id' map' of
99− Nothing -> error $ "dependencyLookup: " ++ show id' ++ " not found"
100− Just d -> d
112+ dependencyLookup map' id' = M.lookup id' map'
113+
114+modified :: ResourceProvider -- ^ Resource provider
115+ -> Store -- ^ Store
116+ -> [Identifier] -- ^ Identifiers to check
117+ -> IO (Set Identifier) -- ^ Modified resources
118+modified provider store ids = fmap S.fromList $ flip filterM ids $ \id' ->
119+ if resourceExists provider id' then resourceModified provider id' store
120+ else return False