summaryrefslogtreecommitdiff
path: root/src/Hakyll/Core/Run.hs
blob: 1b45f3823ea7d89305a2db53a9505c9b3d567e3e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
-- | This is the module which binds it all together
--
module Hakyll.Core.Run where

import Control.Arrow ((&&&))
import Control.Monad (foldM, forM_)
import qualified Data.Map as M
import Data.Monoid (mempty)
import Data.Typeable (Typeable)
import Data.Binary (Binary)
import System.FilePath ((</>))

import Hakyll.Core.Route
import Hakyll.Core.Identifier
import Hakyll.Core.Util.File
import Hakyll.Core.Compiler
import Hakyll.Core.Compiler.Internal
import Hakyll.Core.ResourceProvider
import Hakyll.Core.ResourceProvider.FileResourceProvider
import Hakyll.Core.Rules
import Hakyll.Core.DirectedGraph
import Hakyll.Core.DirectedGraph.Dot
import Hakyll.Core.DirectedGraph.DependencySolver
import Hakyll.Core.Writable
import Hakyll.Core.Store
import Hakyll.Core.CompiledItem

hakyll :: Rules -> IO ()
hakyll rules = do
    store <- makeStore "_store"
    provider <- fileResourceProvider
    hakyllWith rules provider store

hakyllWith :: Rules -> ResourceProvider -> Store -> IO ()
hakyllWith rules provider store = do
    let -- Get the rule set
        ruleSet = runRules rules provider

        -- Get all identifiers and compilers
        compilers = rulesCompilers ruleSet

        -- Get all dependencies
        dependencies = flip map compilers $ \(id', compiler) ->
            let deps = runCompilerDependencies compiler provider
            in (id', deps)

        -- Create a compiler map
        compilerMap = M.fromList compilers

        -- Create and solve the graph, creating a compiler order
        graph = fromList dependencies
        ordered = solveDependencies graph

        -- Join the order with the compilers again
        orderedCompilers = map (id &&& (compilerMap M.!)) ordered

        -- Fetch the routes
        route' = rulesRoute ruleSet

    putStrLn "Writing dependency graph to dependencies.dot..."
    writeDot "dependencies.dot" show graph

    -- Generate all the targets in order
    _ <- foldM (addTarget route') M.empty orderedCompilers

    putStrLn "DONE."
  where
    addTarget route' map' (id', comp) = do
        let url = runRoute route' id'
        
        -- Check if the resource was modified
        modified <- if resourceExists provider id'
                        then resourceModified provider id' store
                        else return False

        -- Run the compiler
        compiled <- runCompilerJob comp id' provider (dependencyLookup map')
                                   url store modified
        putStrLn $ "Generated target: " ++ show id'

        case url of
            Nothing -> return ()
            Just r  -> do
                putStrLn $ "Routing " ++ show id' ++ " to " ++ r
                let path = "_site" </> r
                makeDirectories path
                write path compiled

        putStrLn ""
        return $ M.insert id' compiled map'

    dependencyLookup map' id' = case M.lookup id' map' of
        Nothing -> error $ "dependencyLookup: " ++ show id' ++ " not found"
        Just d  -> d