@@ -1,14 +1,22 @@
1--------------------------------------------------------------------------------
1--------------------------------------------------------------------------------
2−{-# LANGUAGE BangPatterns #-}
3module Hakyll.Core.Dependencies
2module Hakyll.Core.Dependencies
8--------------------------------------------------------------------------------
9--------------------------------------------------------------------------------
10+import Control.Applicative ((<$>))
11+import Control.Monad (foldM, forM_, unless, when)
12+import Control.Monad.Reader (ask)
13+import Control.Monad.RWS (RWS, runRWS)
14+import Control.Monad.State (get, modify)
15+import Control.Monad.Writer (tell)
9−import Data.List (foldl')
16+import Data.List (find)
10import Data.Map (Map)
17import Data.Map (Map)
11import qualified Data.Map as M
18import qualified Data.Map as M
19+import Data.Maybe (fromMaybe)
12import Data.Set (Set)
20import Data.Set (Set)
13import qualified Data.Set as S
21import qualified Data.Set as S
@@ -34,26 +42,89 @@ outOfDate
34 :: [Identifier ()] -- ^ All known identifiers
42 :: [Identifier ()] -- ^ All known identifiers
35 -> Set (Identifier ()) -- ^ Initially out-of-date resources
43 -> Set (Identifier ()) -- ^ Initially out-of-date resources
36 -> DependencyFacts -- ^ Old dependency facts
44 -> DependencyFacts -- ^ Old dependency facts
37− -> (Set (Identifier ()), DependencyFacts)
45+ -> (Set (Identifier ()), DependencyFacts, [String])
38−outOfDate universe ood oldFacts = (ood, oldFacts)
46+outOfDate universe ood oldFacts =
47+ let (_, state, logs) = runRWS rws universe (DependencyState oldFacts ood)
48+ in (dependencyOod state, dependencyFacts state, logs)
56+--------------------------------------------------------------------------------
57+data DependencyState = DependencyState
58+ { dependencyFacts :: DependencyFacts
59+ , dependencyOod :: Set (Identifier ())
41--------------------------------------------------------------------------------
63--------------------------------------------------------------------------------
42−-- | Determine patterns with changed results
64+type DependencyM a = RWS [Identifier ()] [String] DependencyState a
44− :: [Identifier ()]
66+
45− -> DependencyFacts
67+--------------------------------------------------------------------------------
46− -> (Set (Identifier ()), DependencyFacts)
68+markOod :: Identifier () -> DependencyM ()
47−changedPatterns universe facts =
69+markOod id' = modify $ \s -> s {dependencyOod = S.insert id' $ dependencyOod s}
48− M.foldlWithKey' changed (S.empty, facts) facts
70+
72+--------------------------------------------------------------------------------
73+dependenciesFor :: Identifier () -> DependencyM [Identifier ()]
74+dependenciesFor id' = do
75+ facts <- dependencyFacts <$> get
76+ let relevant = fromMaybe [] $ M.lookup id' facts
77+ return [i | Identifier i <- relevant]
80+--------------------------------------------------------------------------------
81+checkNew :: DependencyM ()
84+ facts <- dependencyFacts <$> get
85+ forM_ universe $ \id' -> unless (id' `M.member` facts) $ do
86+ tell [show id' ++ " is out-of-date because it is new"]
90+--------------------------------------------------------------------------------
91+checkChangedPatterns :: DependencyM ()
92+checkChangedPatterns = do
93+ facts <- M.toList . dependencyFacts <$> get
94+ forM_ facts $ \(id', deps) -> do
95+ deps' <- foldM (go id') [] deps
97+ {dependencyFacts = M.insert id' deps' $ dependencyFacts s}
50− changed (!o, !f) id' deps =
51− let (o', deps') = foldr (changed' id') (o, []) deps
52− in (o', M.insert id' deps' f)
54− changed' _ (Identifier i) (o, d) = (o, Identifier i : d)
99+ go _ ds (Identifier i) = return $ Identifier i : ds
55− changed' id' (Pattern p ls) (o, d)
100+ go id' ds (Pattern p ls) = do
102+ let ls' = filterMatches p universe
104+ then return $ Pattern p ls : ds
106+ tell [show id' ++ " is out-of-date because a pattern changed"]
56− | ls == ls' = (o, Pattern p ls : d)
108+ return $ Pattern p ls' : ds
57− | otherwise = (S.insert id' o, Pattern p ls' : d)
109+
59− ls' = filterMatches p universe
111+--------------------------------------------------------------------------------
112+bruteForce :: DependencyM ()
118+ (todo', changed) <- foldM check ([], False) todo
119+ when changed (go todo')
121+ check (todo, changed) id' = do
122+ deps <- dependenciesFor id'
123+ ood <- dependencyOod <$> get
124+ case find (`S.member` ood) deps of
125+ Nothing -> return (id' : todo, changed)
127+ tell [show id' ++ " is out-of-date because " ++
128+ show d ++ " is out-of-date"]