@@ -1,40 +1,64 @@
1+--------------------------------------------------------------------------------
12module Hakyll.Preview.Poll
23 ( watchUpdates
34 ) where
45
6+
57--------------------------------------------------------------------------------
6−import Filesystem.Path.CurrentOS (decodeString, encodeString)
7−import System.FSNotify (startManagerConf, watchTree,
8− Event(..), WatchConfig(..))
8+import Control.Concurrent.MVar (newMVar, putMVar, takeMVar)
9+import Control.Monad (when)
10+import Filesystem.Path.CurrentOS (decodeString, encodeString)
11+import System.Directory (canonicalizePath)
12+import System.FilePath (pathSeparators)
13+import System.FSNotify (Event (..), WatchConfig (..),
14+ startManagerConf, watchTree)
15+
916
1017--------------------------------------------------------------------------------
1118import Hakyll.Core.Configuration
12−
19+import Hakyll.Core.Identifier
20+import Hakyll.Core.Identifier.Pattern
1321
1422
1523--------------------------------------------------------------------------------
1624-- | A thread that watches for updates in a 'providerDirectory' and recompiles
1725-- a site as soon as any changes occur
18−watchUpdates :: Configuration -> IO () -> IO ()
26+watchUpdates :: Configuration -> IO Pattern -> IO ()
1927watchUpdates conf update = do
20− _ <- update
21− manager <- startManagerConf (Debounce 0.1)
22− watchTree manager path (not . isRemove) update'
23− where
24− path = decodeString $ providerDirectory conf
25− update' evt = do
26− ignore <- shouldIgnoreFile conf $ eventPath evt
27− if ignore then return () else update
28+ let providerDir = decodeString $ providerDirectory conf
29+ lock <- newMVar ()
30+ pattern <- update
31+ fullProviderDir <- canonicalizePath $ providerDirectory conf
32+ manager <- startManagerConf (Debounce 0.1)
2833
34+ let allowed event = do
35+ -- Absolute path of the changed file. This must be inside provider
36+ -- dir, since that's the only dir we're watching.
37+ let path = eventPath event
38+ relative = dropWhile (`elem` pathSeparators) $
39+ drop (length fullProviderDir) path
40+ identifier = fromFilePath relative
2941
42+ shouldIgnore <- shouldIgnoreFile conf path
43+ return $ not shouldIgnore && matches pattern identifier
44+
45+ watchTree manager providerDir (not . isRemove) $ \event -> do
46+ () <- takeMVar lock
47+ allowed' <- allowed event
48+ when allowed' $ update >> return ()
49+ putMVar lock ()
50+
51+
52+--------------------------------------------------------------------------------
3053eventPath :: Event -> FilePath
3154eventPath evt = encodeString $ evtPath evt
3255 where
33− evtPath (Added p _) = p
56+ evtPath (Added p _) = p
3457 evtPath (Modified p _) = p
35− evtPath (Removed p _) = p
58+ evtPath (Removed p _) = p
3659
3760
61+--------------------------------------------------------------------------------
3862isRemove :: Event -> Bool
3963isRemove (Removed _ _) = True
40−isRemove _ = False
64+isRemove _ = False