on master help sign in
Support old directory versions...
commitb1f70c339e031c1f6abf04ff63566f2cb9757a07 authorJasper Van der Jeugt <m@jaspervdj.be> dateMon 19 Nov 2012, 15:52 (14 years ago) parent802742c
5 files changed+18−275
hakyll.cabal−2 src/Hakyll/Core/DependencyAnalyzer.hs−144 src/Hakyll/Core/DirectedGraph.hs−90 src/Hakyll/Core/DirectedGraph/Dot.hs−36 src/Hakyll/Core/Provider/Modified.hs+18−3
hakyll.cabal−2
@@ -134,8 +134,6 @@ Library
134134 Other-Modules:
135135 Hakyll.Core.Compiler.Internal
136136 Hakyll.Core.Compiler.Require
137− Hakyll.Core.DirectedGraph
138− Hakyll.Core.DirectedGraph.Dot
139137 Hakyll.Core.Item.SomeItem
140138 Hakyll.Core.Provider
141139 Hakyll.Core.Provider.Internal
src/Hakyll/Core/DependencyAnalyzer.hsdeleted−144
@@ -1,144 +0,0 @@
1−--------------------------------------------------------------------------------
2−module Hakyll.Core.DependencyAnalyzer
3− ( Analysis (..)
4− , analyze
5− ) where
6−
7−
8−--------------------------------------------------------------------------------
9−import Control.Applicative ((<$>))
10−import Control.DeepSeq (NFData (..))
11−import Control.Monad (filterM, forM_, msum, when)
12−import Control.Monad.Reader (ask)
13−import Control.Monad.RWS (RWS, runRWS)
14−import Control.Monad.State (evalState, get, modify)
15−import Control.Monad.Writer (tell)
16−import qualified Data.Map as M
17−import Data.Set (Set)
18−import qualified Data.Set as S
19−
20−
21−--------------------------------------------------------------------------------
22−import Hakyll.Core.DirectedGraph
23−
24−
25−--------------------------------------------------------------------------------
26−data Analysis a
27− = Cycle [a]
28− | Order [a]
29− deriving (Show)
30−
31−
32−--------------------------------------------------------------------------------
33−instance NFData a => NFData (Analysis a) where
34− rnf (Cycle c) = rnf c `seq` ()
35− rnf (Order o) = rnf o `seq` ()
36−
37−
38−--------------------------------------------------------------------------------
39−analyze :: Ord a
40− => DirectedGraph a -- ^ Old graph
41− -> DirectedGraph a -- ^ New graph
42− -> (a -> Bool) -- ^ Out of date?
43− -> Analysis a -- ^ Result
44−analyze old new ood = case findCycle new of
45− Just c -> Cycle c
46− Nothing -> Order $ findOrder old new ood
47−
48−
49−--------------------------------------------------------------------------------
50−-- | Simple algorithm do find a cycle in a graph, if any exists. This one can
51−-- still be optimised by a lot.
52−findCycle :: Ord a
53− => DirectedGraph a
54− -> Maybe [a]
55−findCycle dg = fmap reverse $ msum
56− [ findCycle' [x] x n
57− | x <- S.toList $ nodes dg
58− , n <- neighbours x dg
59− ]
60− where
61− findCycle' stack start x
62− | x == start = Just (x : stack)
63− | otherwise = msum
64− [ findCycle' (x : stack) start n
65− | n <- neighbours x dg
66− ]
67−
68−
69−--------------------------------------------------------------------------------
70−-- | Do not call this on graphs with cycles
71−findOrder :: Ord a
72− => DirectedGraph a
73− -> DirectedGraph a
74− -> (a -> Bool)
75− -> [a]
76−findOrder old new ood = ls
77− where
78− -- Make an extension of ood: an item is ood when it is actually ood OR if
79− -- the list of its dependencies has changed. Based on that, create a set of
80− -- dirty items.
81− ood' x = ood x || neighbours x old /= neighbours x new
82− dirty' = dirty ood' new
83−
84− -- Run all walks in our own little monad...
85− (_, _, ls) = runRWS walks new dirty'
86−
87−
88−--------------------------------------------------------------------------------
89−type Analyzer i a = RWS (DirectedGraph i) [i] (Set i) a
90−
91−
92−--------------------------------------------------------------------------------
93−isDirty :: Ord a => a -> Analyzer a Bool
94−isDirty x = (x `S.member`) <$> get
95−
96−
97−--------------------------------------------------------------------------------
98−walks :: Ord a
99− => Analyzer a ()
100−walks = do
101− dirty' <- get
102− if S.null dirty'
103− then return ()
104− else do
105− walk $ S.findMin dirty'
106− walks
107−
108−
109−--------------------------------------------------------------------------------
110−-- | Invariant: given node to walk /must/ be dirty
111−walk :: Ord a
112− => a
113− -> Analyzer a ()
114−walk x = do
115− -- Determine dirty neighbours and walk them
116− dg <- ask
117− forM_ (neighbours x dg) $ \n -> do
118− d <- isDirty n
119− when d $ walk n
120−
121− -- Once all dirty neighbours are done, we're safe to go
122− tell [x]
123− modify $ S.delete x
124−
125−
126−--------------------------------------------------------------------------------
127−-- | This auxiliary function checks which nodes are dirty: a node is dirty if
128−-- it's out-of-date or if one of its dependencies is dirty.
129−dirty :: Ord a
130− => (a -> Bool) -- ^ Out of date?
131− -> DirectedGraph a -- ^ Graph
132− -> Set a -- ^ All dirty items
133−dirty ood dg = S.fromList $ flip evalState M.empty $
134− filterM go $ S.toList $ nodes dg
135− where
136− go x = do
137− m <- get
138− case M.lookup x m of
139− Just d -> return d
140− Nothing -> do
141− nd <- mapM go $ neighbours x dg
142− let d = ood x || or nd
143− modify $ M.insert x d
144− return d
src/Hakyll/Core/DirectedGraph.hsdeleted−90
@@ -1,90 +0,0 @@
1−--------------------------------------------------------------------------------
2−-- | Representation of a directed graph. In Hakyll, this is used for dependency
3−-- tracking.
4−{-# LANGUAGE DeriveDataTypeable #-}
5−{-# LANGUAGE GeneralizedNewtypeDeriving #-}
6−module Hakyll.Core.DirectedGraph
7− ( DirectedGraph
8−
9− , fromList
10− , toList
11−
12− , member
13− , nodes
14− , neighbours
15− ) where
16−
17−
18−--------------------------------------------------------------------------------
19−import Control.Arrow (second)
20−import Control.DeepSeq (NFData)
21−import Data.Binary (Binary)
22−import Data.Map (Map)
23−import qualified Data.Map as M
24−import Data.Maybe (fromMaybe)
25−import Data.Monoid (Monoid (..))
26−import Data.Set (Set)
27−import qualified Data.Set as S
28−import Data.Typeable (Typeable)
29−import Prelude hiding (reverse)
30−
31−
32−--------------------------------------------------------------------------------
33−-- | Type used to represent a directed graph
34−newtype DirectedGraph a = DirectedGraph {unDirectedGraph :: Map a [a]}
35− deriving (Show, Binary, NFData, Typeable)
36−
37−
38−--------------------------------------------------------------------------------
39−-- | Allow users to concatenate different graphs
40−instance Ord a => Monoid (DirectedGraph a) where
41− mempty = DirectedGraph M.empty
42− mappend (DirectedGraph m1) (DirectedGraph m2) = DirectedGraph $
43− M.unionWith (\x y -> sortUnique (x ++ y)) m1 m2
44−
45−
46−--------------------------------------------------------------------------------
47−-- | Construction of directed graphs
48−fromList :: Ord a
49− => [(a, [a])] -- ^ List of (node, reachable neighbours)
50− -> DirectedGraph a -- ^ Resulting directed graph
51−fromList = DirectedGraph . M.fromList . map (second sortUnique)
52−
53−
54−--------------------------------------------------------------------------------
55−-- | Deconstruction of directed graphs
56−toList :: DirectedGraph a
57− -> [(a, [a])]
58−toList = M.toList . unDirectedGraph
59−
60−
61−--------------------------------------------------------------------------------
62−-- | Check if a node lies in the given graph
63−member :: Ord a
64− => a -- ^ Node to check for
65− -> DirectedGraph a -- ^ Directed graph to check in
66− -> Bool -- ^ If the node lies in the graph
67−member n = M.member n . unDirectedGraph
68−
69−
70−--------------------------------------------------------------------------------
71−-- | Get all nodes in the graph
72−nodes :: Ord a
73− => DirectedGraph a -- ^ Graph to get the nodes from
74− -> Set a -- ^ All nodes in the graph
75−nodes = M.keysSet . unDirectedGraph
76−
77−
78−--------------------------------------------------------------------------------
79−-- | Get a set of reachable neighbours from a directed graph
80−neighbours :: Ord a
81− => a -- ^ Node to get the neighbours of
82− -> DirectedGraph a -- ^ Graph to search in
83− -> [a] -- ^ Set containing the neighbours
84−neighbours x dg = fromMaybe [] $ M.lookup x $ unDirectedGraph dg
85−
86−
87−--------------------------------------------------------------------------------
88−-- | Sort and make unique
89−sortUnique :: Ord a => [a] -> [a]
90−sortUnique = S.toAscList . S.fromList
src/Hakyll/Core/DirectedGraph/Dot.hsdeleted−36
@@ -1,36 +0,0 @@
1−--------------------------------------------------------------------------------
2−-- | Dump a directed graph in dot format. Used for debugging purposes
3−module Hakyll.Core.DirectedGraph.Dot
4− ( toDot
5− , writeDot
6− ) where
7−
8−
9−--------------------------------------------------------------------------------
10−import qualified Data.Set as S
11−import Hakyll.Core.DirectedGraph
12−
13−
14−--------------------------------------------------------------------------------
15−-- | Convert a directed graph into dot format for debugging purposes
16−toDot :: Ord a
17− => (a -> String) -- ^ Convert nodes to dot names
18− -> DirectedGraph a -- ^ Graph to dump
19− -> String -- ^ Resulting string
20−toDot showTag graph = unlines $ concat
21− [ return "digraph dependencies {"
22− , map showNode (S.toList $ nodes graph)
23− , concatMap showEdges (S.toList $ nodes graph)
24− , return "}"
25− ]
26− where
27− showNode node = " \"" ++ showTag node ++ "\";"
28− showEdges node = map (showEdge node) $ neighbours node graph
29− showEdge x y = " \"" ++ showTag x ++ "\" -> \"" ++ showTag y ++ "\";"
30−
31−
32−--------------------------------------------------------------------------------
33−-- | Write out the @.dot@ file to a given file path. See 'toDot' for more
34−-- information.
35−writeDot :: Ord a => FilePath -> (a -> String) -> DirectedGraph a -> IO ()
36−writeDot path showTag = writeFile path . toDot showTag
src/Hakyll/Core/Provider/Modified.hs+18−3
@@ -1,4 +1,5 @@
11--------------------------------------------------------------------------------
2+{-# LANGUAGE CPP #-}
23module Hakyll.Core.Provider.Modified
34 ( resourceModified
45 , resourceModificationTime
@@ -15,7 +16,15 @@ import Data.IORef
1516import qualified Data.Map as M
1617import Data.Time (UTCTime)
1718import System.Directory (getModificationTime)
18−import System.FilePath ((</>))
19+
20+
21+--------------------------------------------------------------------------------
22+#if !MIN_VERSION_directory(1,2,0)
23+import Data.Time (readTime)
24+import System.Locale (defaultTimeLocale)
25+import System.Time (formatCalendarTime,
26+ toCalendarTime)
27+#endif
1928
2029
2130--------------------------------------------------------------------------------
@@ -82,5 +91,11 @@ fileDigest = fmap MD5.hashlazy . BL.readFile
8291
8392--------------------------------------------------------------------------------
8493resourceModificationTime :: Provider -> Identifier -> IO UTCTime
85−resourceModificationTime p i =
86− getModificationTime $ providerDirectory p </> toFilePath i
94+resourceModificationTime p i = do
95+#if MIN_VERSION_directory(1,2,0)
96+ getModificationTime $ resourceFilePath p i
97+#else
98+ ct <- toCalendarTime =<< getModificationTime (resourceFilePath p i)
99+ let str = formatCalendarTime defaultTimeLocale "%s" ct
100+ return $ readTime defaultTimeLocale "%s" str
101+#endif