@@ -0,0 +1,60 @@
1+-- | Filesystem polling with an inotify backend. Works only on linux.
2+--
3+module Hakyll.Web.Preview.INotify
4+ ( previewPoll
5+ ) where
6+
7+import Control.Monad (forM_, when, unless)
8+import System.Directory (doesDirectoryExist)
9+import System.FilePath ((</>))
10+import Data.List (isPrefixOf)
11+
12+import System.INotify
13+
14+import Hakyll.Core.Util.File
15+import Hakyll.Core.Configuration
16+
17+-- | Calls the given callback when the directory tree changes
18+--
19+previewPoll :: HakyllConfiguration -- ^ Configuration
20+ -> FilePath -- ^ Root directory
21+ -> IO () -- ^ Action called when something changes
22+ -> IO () -- ^ Can block forever
23+previewPoll conf directory callback = do
24+ -- Initialize inotify
25+ inotify <- initINotify
26+
27+ -- Start by watching all directories
28+ contents <- getRecursiveContents True directory
29+ forM_ contents $ \file -> do
30+ isDir <- doesDirectoryExist file
31+ when isDir $ watchDirectory conf inotify file callback
32+
33+-- | Start watching a directory recursively: when another directory is created
34+-- inside this directory, start watching that one as well...
35+--
36+watchDirectory :: HakyllConfiguration -- ^ Configuration
37+ -> INotify -- ^ INotify handle
38+ -> FilePath -- ^ Directory to watch
39+ -> IO () -- ^ Callback
40+ -> IO () -- ^ No result
41+watchDirectory conf inotify path callback =
42+ unless (isFileInternal conf path) $ do
43+ _ <- addWatch inotify interesting path $ \event -> do
44+ putStrLn $ "Triggered: " ++ show event
45+ callback' inotify path event
46+ return ()
47+ where
48+ callback' i p (Created True n) = watchDirectory conf i (p </> n) callback
49+ callback' _ _ (Created _ p) = whenProper $ Just p
50+ callback' _ _ (Modified _ p) = whenProper p
51+ callback' _ _ (MovedOut _ p _) = whenProper $ Just p
52+ callback' _ _ (MovedIn _ p _) = whenProper $ Just p
53+ callback' _ _ (Deleted _ p) = whenProper $ Just p
54+ callback' _ _ _ = return ()
55+
56+ interesting = [Modify, Create, Move, Delete]
57+
58+ -- Call the callback only for proper files
59+ whenProper Nothing = return ()
60+ whenProper (Just f) = unless ("." `isPrefixOf` f) callback