on master help sign in
Merge pull request #131 from simukis/fsnotify

Migrate to filesystem notification

commit5f6035b8e95c0fa5747d8b46b15f6e6c75651abd authorJasper Van der Jeugt <jaspervdj@gmail.com> dateThu 4 Apr 2013, 01:43 (14 years ago) parentcbfc7c15a9a869
3 files changed+41−53
hakyll.cabal+7−3 src/Hakyll/Commands.hs+5−13 src/Hakyll/Preview/Poll.hs+29−37
hakyll.cabal+7−3
@@ -165,7 +165,9 @@ Library
165165 If flag(previewServer)
166166 Build-depends:
167167 snap-core >= 0.6 && < 0.10,
168− snap-server >= 0.6 && < 0.10
168+ snap-server >= 0.6 && < 0.10,
169+ fsnotify >= 0.0.6 && < 0.1,
170+ system-filepath >= 0.4.6 && <= 0.5
169171 Cpp-options:
170172 -DPREVIEW_SERVER
171173 Other-modules:
@@ -238,8 +240,10 @@ Test-suite hakyll-tests
238240
239241 If flag(previewServer)
240242 Build-depends:
241− snap-core >= 0.6 && < 0.10,
242− snap-server >= 0.6 && < 0.10
243+ snap-core >= 0.6 && < 0.10,
244+ snap-server >= 0.6 && < 0.10,
245+ fsnotify >= 0.0.6 && < 0.1,
246+ system-filepath >= 0.4.6 && <= 0.5
243247 Cpp-options:
244248 -DPREVIEW_SERVER
245249 Other-modules:
src/Hakyll/Commands.hs+5−13
@@ -13,7 +13,7 @@ module Hakyll.Commands
1313
1414
1515--------------------------------------------------------------------------------
16−import System.Exit (ExitCode (ExitSuccess), exitWith)
16+import System.Exit (exitWith)
1717
1818
1919--------------------------------------------------------------------------------
@@ -27,10 +27,6 @@ import Hakyll.Core.Util.File
2727
2828--------------------------------------------------------------------------------
2929#ifdef PREVIEW_SERVER
30−import Control.Concurrent (forkIO)
31−import qualified Data.Set as S
32−import Hakyll.Core.Identifier
33−import Hakyll.Core.Rules.Internal
3430import Hakyll.Preview.Poll
3531import Hakyll.Preview.Server
3632#endif
@@ -68,16 +64,12 @@ clean conf = do
6864preview :: Configuration -> Verbosity -> Rules a -> Int -> IO ()
6965#ifdef PREVIEW_SERVER
7066preview conf verbosity rules port = do
71− -- Run the server in a separate thread
72− _ <- forkIO $ server conf port
73− previewPoll conf update
67+ watchUpdates conf update
68+ server conf port
7469 where
7570 update = do
76− (exitCode, ruleSet) <- run conf verbosity rules
77− case exitCode of
78− ExitSuccess -> return $ map toFilePath $ S.toList $
79− rulesResources ruleSet
80− _ -> exitWith exitCode
71+ _ <- run conf verbosity rules
72+ return ()
8173#else
8274preview _ _ _ _ = previewServerDisabled
8375#endif
src/Hakyll/Preview/Poll.hs+29−37
@@ -1,48 +1,40 @@
1−--------------------------------------------------------------------------------
2−-- | Interval-based implementation of preview polling
3−{-# LANGUAGE CPP #-}
41module Hakyll.Preview.Poll
5− ( previewPoll
2+ ( watchUpdates
63 ) where
74
8−
95--------------------------------------------------------------------------------
10−import Control.Applicative ((<$>))
11−import Control.Concurrent (threadDelay)
12−import Control.Monad (filterM)
13−#if MIN_VERSION_directory(1,2,0)
14−import Data.Time (getCurrentTime)
15−#else
16−import System.Time (getClockTime)
17−#endif
18−import System.Directory (doesFileExist, getModificationTime)
19−
6+import Filesystem.Path.CurrentOS (decodeString, encodeString)
7+import System.FSNotify (startManagerConf, watchTree,
8+ Event(..), WatchConfig(..))
209
2110--------------------------------------------------------------------------------
2211import Hakyll.Core.Configuration
2312
2413
14+
2515--------------------------------------------------------------------------------
26−-- | A preview thread that periodically recompiles the site.
27−previewPoll :: Configuration -- ^ Configuration
28− -> IO [FilePath] -- ^ Updating action
29− -> IO () -- ^ Can block forever
30−previewPoll _ update = do
31−#if MIN_VERSION_directory(1,2,0)
32− time <- getCurrentTime
33−#else
34− time <- getClockTime
35−#endif
36− loop time =<< update
16+-- | A thread that watches for updates in a 'providerDirectory' and recompiles
17+-- a site as soon as any changes occur
18+watchUpdates :: Configuration -> IO () -> IO ()
19+watchUpdates conf update = do
20+ _ <- update
21+ manager <- startManagerConf (Debounce 0.1)
22+ watchTree manager path (not . isRemove) update'
3723 where
38− delay = 1000000
39− loop time files = do
40− threadDelay delay
41− files' <- filterM doesFileExist files
42− filesTime <- case files' of
43− [] -> return time
44− _ -> maximum <$> mapM getModificationTime files'
45−
46− if filesTime > time || files' /= files
47− then loop filesTime =<< update
48− else loop time files'
24+ path = decodeString $ providerDirectory conf
25+ update' evt = do
26+ ignore <- shouldIgnoreFile conf $ eventPath evt
27+ if ignore then return () else update
28+
29+
30+eventPath :: Event -> FilePath
31+eventPath evt = encodeString $ evtPath evt
32+ where
33+ evtPath (Added p _) = p
34+ evtPath (Modified p _) = p
35+ evtPath (Removed p _) = p
36+
37+
38+isRemove :: Event -> Bool
39+isRemove (Removed _ _) = True
40+isRemove _ = False