hakyll/src-inotify/Hakyll/Web/Preview/Poll.hs
2011-04-12 10:09:03 +02:00

50 lines
1.7 KiB
Haskell

-- | Filesystem polling with an inotify backend. Works only on linux.
--
module Hakyll.Web.Preview.Poll
( previewPoll
) where
import Control.Monad (forM_, when)
import Data.Set (Set)
import qualified Data.Set as S
import System.FilePath (takeDirectory, (</>))
import Data.List (isPrefixOf)
import System.INotify
import Hakyll.Core.Configuration
import Hakyll.Core.Resource
-- | Calls the given callback when the directory tree changes
--
previewPoll :: HakyllConfiguration -- ^ Configuration
-> Set Resource -- ^ Resources to watch
-> IO () -- ^ Action called when something changes
-> IO () -- ^ Can block forever
previewPoll _ resources callback = do
-- Initialize inotify
inotify <- initINotify
let -- A set of file paths
paths = S.map unResource resources
-- A list of directories. Run it through a set so we have every
-- directory only once.
directories = S.toList $ S.map (notEmpty . takeDirectory) paths
-- Problem: we can't add a watcher for "". So we make sure a directory
-- name is not empty
notEmpty "" = "."
notEmpty x = x
-- Execute the callback when path is known
ifResource path =
let path' = if "./" `isPrefixOf` path then drop 2 path else path
in when (path' `S.member` paths) callback
-- Add a watcher for every directory
forM_ directories $ \directory -> do
_ <- addWatch inotify [Modify] directory $ \e -> case e of
(Modified _ (Just p)) -> ifResource $ directory </> p
_ -> return ()
return ()