2012-11-12 11:23:34 +00:00
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
module Hakyll.Core.Dependencies
|
2012-11-12 13:31:33 +00:00
|
|
|
( Dependency (..)
|
|
|
|
, DependencyFacts
|
|
|
|
, outOfDate
|
2012-11-12 11:23:34 +00:00
|
|
|
) where
|
|
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
2012-11-12 13:31:33 +00:00
|
|
|
import Control.Applicative ((<$>))
|
|
|
|
import Control.Monad (foldM, forM_, unless, when)
|
|
|
|
import Control.Monad.Reader (ask)
|
|
|
|
import Control.Monad.RWS (RWS, runRWS)
|
|
|
|
import Control.Monad.State (get, modify)
|
|
|
|
import Control.Monad.Writer (tell)
|
|
|
|
import Data.List (find)
|
2012-11-12 11:23:34 +00:00
|
|
|
import Data.Map (Map)
|
|
|
|
import qualified Data.Map as M
|
2012-11-12 13:31:33 +00:00
|
|
|
import Data.Maybe (fromMaybe)
|
2012-11-12 11:23:34 +00:00
|
|
|
import Data.Set (Set)
|
|
|
|
import qualified Data.Set as S
|
|
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
import Hakyll.Core.Identifier
|
|
|
|
import Hakyll.Core.Identifier.Pattern
|
|
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
data Dependency
|
|
|
|
= Pattern (Pattern ()) [Identifier ()]
|
|
|
|
| Identifier (Identifier ())
|
|
|
|
deriving (Show)
|
|
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
type DependencyFacts = Map (Identifier ()) [Dependency]
|
|
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
outOfDate
|
|
|
|
:: [Identifier ()] -- ^ All known identifiers
|
|
|
|
-> Set (Identifier ()) -- ^ Initially out-of-date resources
|
|
|
|
-> DependencyFacts -- ^ Old dependency facts
|
2012-11-12 13:31:33 +00:00
|
|
|
-> (Set (Identifier ()), DependencyFacts, [String])
|
|
|
|
outOfDate universe ood oldFacts =
|
|
|
|
let (_, state, logs) = runRWS rws universe (DependencyState oldFacts ood)
|
|
|
|
in (dependencyOod state, dependencyFacts state, logs)
|
|
|
|
where
|
|
|
|
rws = do
|
|
|
|
checkNew
|
|
|
|
checkChangedPatterns
|
|
|
|
bruteForce
|
|
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
data DependencyState = DependencyState
|
|
|
|
{ dependencyFacts :: DependencyFacts
|
|
|
|
, dependencyOod :: Set (Identifier ())
|
|
|
|
} deriving (Show)
|
2012-11-12 11:23:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
2012-11-12 13:31:33 +00:00
|
|
|
type DependencyM a = RWS [Identifier ()] [String] DependencyState a
|
|
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
markOod :: Identifier () -> DependencyM ()
|
|
|
|
markOod id' = modify $ \s -> s {dependencyOod = S.insert id' $ dependencyOod s}
|
|
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
dependenciesFor :: Identifier () -> DependencyM [Identifier ()]
|
|
|
|
dependenciesFor id' = do
|
|
|
|
facts <- dependencyFacts <$> get
|
|
|
|
let relevant = fromMaybe [] $ M.lookup id' facts
|
|
|
|
return [i | Identifier i <- relevant]
|
|
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
checkNew :: DependencyM ()
|
|
|
|
checkNew = do
|
|
|
|
universe <- ask
|
|
|
|
facts <- dependencyFacts <$> get
|
|
|
|
forM_ universe $ \id' -> unless (id' `M.member` facts) $ do
|
|
|
|
tell [show id' ++ " is out-of-date because it is new"]
|
|
|
|
markOod id'
|
|
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
checkChangedPatterns :: DependencyM ()
|
|
|
|
checkChangedPatterns = do
|
|
|
|
facts <- M.toList . dependencyFacts <$> get
|
|
|
|
forM_ facts $ \(id', deps) -> do
|
|
|
|
deps' <- foldM (go id') [] deps
|
|
|
|
modify $ \s -> s
|
|
|
|
{dependencyFacts = M.insert id' deps' $ dependencyFacts s}
|
2012-11-12 11:23:34 +00:00
|
|
|
where
|
2012-11-12 13:31:33 +00:00
|
|
|
go _ ds (Identifier i) = return $ Identifier i : ds
|
|
|
|
go id' ds (Pattern p ls) = do
|
|
|
|
universe <- ask
|
|
|
|
let ls' = filterMatches p universe
|
|
|
|
if ls == ls'
|
|
|
|
then return $ Pattern p ls : ds
|
|
|
|
else do
|
|
|
|
tell [show id' ++ " is out-of-date because a pattern changed"]
|
|
|
|
markOod id'
|
|
|
|
return $ Pattern p ls' : ds
|
|
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
bruteForce :: DependencyM ()
|
|
|
|
bruteForce = do
|
|
|
|
todo <- ask
|
|
|
|
go todo
|
|
|
|
where
|
|
|
|
go todo = do
|
|
|
|
(todo', changed) <- foldM check ([], False) todo
|
|
|
|
when changed (go todo')
|
|
|
|
|
|
|
|
check (todo, changed) id' = do
|
|
|
|
deps <- dependenciesFor id'
|
|
|
|
ood <- dependencyOod <$> get
|
|
|
|
case find (`S.member` ood) deps of
|
|
|
|
Nothing -> return (id' : todo, changed)
|
|
|
|
Just d -> do
|
|
|
|
tell [show id' ++ " is out-of-date because " ++
|
|
|
|
show d ++ " is out-of-date"]
|
|
|
|
markOod id'
|
|
|
|
return (todo, True)
|